1 karl 1.52 //%2004////////////////////////////////////////////////////////////////////////
|
2 mike 1.2 //
|
3 karl 1.52 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
|
6 karl 1.43 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.52 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
|
9 mike 1.2 //
10 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
11 kumpf 1.20 // of this software and associated documentation files (the "Software"), to
12 // deal in the Software without restriction, including without limitation the
13 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
14 mike 1.2 // sell copies of the Software, and to permit persons to whom the Software is
15 // furnished to do so, subject to the following conditions:
16 //
|
17 kumpf 1.20 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
18 mike 1.2 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
19 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
20 kumpf 1.20 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
21 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
23 mike 1.2 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 //
26 //==============================================================================
27 //
28 // Author: Mike Brasher (mbrasher@bmc.com)
29 //
30 // Modified By:
31 // Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com)
|
32 kumpf 1.6 // Nag Boranna, Hewlett-Packard Company (nagaraja_boranna@hp.com)
|
33 david 1.27 // Dave Rosckes (rosckes@us.ibm.com)
|
34 kumpf 1.45 // Denise Eckstein (denise.eckstein@hp.com)
|
35 a.arora 1.50 // Alagaraja Ramasubramanian (alags_raj@in.ibm.com) for Bug#1090
|
36 mike 1.2 //
37 //%/////////////////////////////////////////////////////////////////////////////
38
39 #include "Config.h"
|
40 kumpf 1.15 #include "Constants.h"
|
41 mike 1.2 #include <iostream>
42 #include "Socket.h"
43
44 #ifdef PEGASUS_PLATFORM_WIN32_IX86_MSVC
|
45 mday 1.12 #include <windows.h>
|
46 mike 1.2 #else
47 # include <cctype>
48 # include <cstdlib>
49 # include <errno.h>
50 # include <fcntl.h>
51 # include <netdb.h>
52 # include <netinet/in.h>
53 # include <arpa/inet.h>
54 # include <sys/socket.h>
|
55 kumpf 1.11 # ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
|
56 kumpf 1.26 # include <unistd.h>
|
57 kumpf 1.11 # include <sys/un.h>
58 # endif
|
59 mike 1.2 #endif
60
61 #include "Socket.h"
62 #include "TLS.h"
63 #include "HTTPAcceptor.h"
64 #include "HTTPConnection.h"
|
65 kumpf 1.19 #include "Tracer.h"
|
66 humberto 1.30 #include <Pegasus/Common/MessageLoader.h> //l10n
|
67 mike 1.2
|
68 chuck 1.38 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
69 #include "OS400ConvertChar.h"
70 #endif
71
|
72 mike 1.2 PEGASUS_USING_STD;
73
74 PEGASUS_NAMESPACE_BEGIN
75
|
76 a.arora 1.51 static int MAX_CONNECTION_QUEUE_LENGTH = -1;
77
78
|
79 mike 1.2 ////////////////////////////////////////////////////////////////////////////////
80 //
81 // HTTPAcceptorRep
82 //
83 ////////////////////////////////////////////////////////////////////////////////
84
|
85 kumpf 1.25 class HTTPAcceptorRep
|
86 mike 1.2 {
|
87 kumpf 1.25 public:
88 HTTPAcceptorRep(Boolean local)
89 {
90 if (local)
91 {
|
92 kumpf 1.11 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
|
93 kumpf 1.25 address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
94 address_size = sizeof(struct sockaddr_un);
|
95 kumpf 1.11 #else
|
96 kumpf 1.25 PEGASUS_ASSERT(false);
|
97 kumpf 1.11 #endif
|
98 david 1.27 }
|
99 kumpf 1.25 else
100 {
101 address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
102 address_size = sizeof(struct sockaddr_in);
103 }
104 }
105
106 struct sockaddr* address;
107
108 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
109 size_t address_size;
|
110 keith.petley 1.31 #elif defined(PEGASUS_PLATFORM_AIX_RS_IBMCXX) || defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || (defined(PEGASUS_PLATFORM_SOLARIS_SPARC_CC) && !defined(SUNOS_5_6))
|
111 kumpf 1.25 socklen_t address_size;
112 #else
113 int address_size;
114 #endif
|
115 mday 1.28 Mutex _connection_mut;
116
117 Sint32 socket;
118 Array<HTTPConnection*> connections;
|
119 mike 1.2 };
120
121 ////////////////////////////////////////////////////////////////////////////////
122 //
123 // HTTPAcceptor
124 //
125 ////////////////////////////////////////////////////////////////////////////////
126
|
127 kumpf 1.25 HTTPAcceptor::HTTPAcceptor(Monitor* monitor,
128 MessageQueue* outputMessageQueue,
129 Boolean localConnection,
130 Uint32 portNumber,
|
131 kumpf 1.49 SSLContext * sslcontext,
132 Boolean exportConnection)
|
133 kumpf 1.25 : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR), // ATTN: Need unique names?
134 _monitor(monitor),
135 _outputMessageQueue(outputMessageQueue),
136 _rep(0),
137 _entry_index(-1),
138 _localConnection(localConnection),
139 _portNumber(portNumber),
|
140 kumpf 1.49 _sslcontext(sslcontext),
141 _exportConnection(exportConnection)
|
142 mike 1.2 {
|
143 mday 1.7 Socket::initializeInterface();
|
144 a.arora 1.51
145 /*
146 Platforms interpret the value of MAX_CONNECTION_QUEUE_LENGTH differently. Some platforms interpret
147 the value literally, while others multiply a fudge factor. When the server is under
148 stress from multiple clients with multiple requests, toggling this number may prevent clients from
149 being dropped. Instead of hard coding the value, we allow an environment variable to be set which
150 specifies a number greater than the maximum concurrent client connections possible. If this environment
151 var is not specified, then MAX_CONNECTION_QUEUE_LENGTH = 15.
152 */
153
154 //To engage runtime backlog queue length: uncomment the following block AND comment out the line MAX_CONNECTION_QUEUE_LENGTH = 15
155
156 /*
157 if(MAX_CONNECTION_QUEUE_LENGTH == -1){
158 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
159 #pragma convert(37)
160 const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE");
161 EtoA(env);
162 #pragma convert(0)
163 #else
164 const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE");
165 a.arora 1.51 #endif
166 if(!env){
167 MAX_CONNECTION_QUEUE_LENGTH = 15;
168 }else{
169 char *end = NULL;
170 MAX_CONNECTION_QUEUE_LENGTH = strtol(env, &end, 10);
171 if(*end)
172 MAX_CONNECTION_QUEUE_LENGTH = 15;
173 cout << " MAX_CONNECTION_QUEUE_LENGTH = " << MAX_CONNECTION_QUEUE_LENGTH << endl;
174 }
175 }
176 */
177 MAX_CONNECTION_QUEUE_LENGTH = 15;
178
|
179 mike 1.2 }
180
181 HTTPAcceptor::~HTTPAcceptor()
182 {
|
183 mday 1.7 unbind();
|
184 kumpf 1.25 // ATTN: Is this correct in a multi-HTTPAcceptor server?
|
185 mday 1.7 Socket::uninitializeInterface();
|
186 mike 1.2 }
187
|
188 mday 1.7 void HTTPAcceptor::handleEnqueue(Message *message)
|
189 mike 1.2 {
|
190 mday 1.7 if (! message)
191 return;
192
193 switch (message->getType())
194 {
195 case SOCKET_MESSAGE:
196 {
197 SocketMessage* socketMessage = (SocketMessage*)message;
|
198 mday 1.32
|
199 mday 1.7 // If this is a connection request:
200
201 if (socketMessage->socket == _rep->socket &&
202 socketMessage->events | SocketMessage::READ)
203 {
204 _acceptConnection();
205 }
206 else
207 {
208 // ATTN! this can't happen!
|
209 kumpf 1.44 Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
210 "HTTPAcceptor::handleEnqueue: Invalid SOCKET_MESSAGE received.");
|
211 mday 1.7 }
212
213 break;
214 }
215
216 case CLOSE_CONNECTION_MESSAGE:
217 {
218 CloseConnectionMessage* closeConnectionMessage
219 = (CloseConnectionMessage*)message;
220
|
221 a.arora 1.50 AutoMutex autoMut(_rep->_connection_mut);
|
222 mday 1.28
|
223 mday 1.7 for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
224 {
225 HTTPConnection* connection = _rep->connections[i];
226 Sint32 socket = connection->getSocket();
|
227 mike 1.2
|
228 mday 1.7 if (socket == closeConnectionMessage->socket)
|
229 mike 1.2 {
|
230 mday 1.7 _monitor->unsolicitSocketMessages(socket);
231 _rep->connections.remove(i);
|
232 kumpf 1.17 delete connection;
|
233 mday 1.7 break;
|
234 mike 1.2 }
|
235 mday 1.7 }
|
236 a.arora 1.50
|
237 kumpf 1.44 break;
|
238 mday 1.7 }
|
239 mike 1.2
|
240 kumpf 1.10 default:
241 // ATTN: need unexpected message error!
|
242 kumpf 1.44 Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
243 "HTTPAcceptor::handleEnqueue: Invalid MESSAGE received.");
|
244 mday 1.7 break;
245 };
|
246 mike 1.2
|
247 mday 1.7 delete message;
248 }
|
249 mike 1.2
250
|
251 mday 1.7 void HTTPAcceptor::handleEnqueue()
252 {
253 Message* message = dequeue();
|
254 mike 1.2
|
255 mday 1.7 if (!message)
|
256 kumpf 1.44 {
257 Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
258 "HTTPAcceptor::handleEnqueue(): No message on queue.");
|
259 mday 1.7 return;
|
260 kumpf 1.44 }
|
261 mday 1.7
262 handleEnqueue(message);
|
263 mike 1.2
264 }
265
|
266 kumpf 1.25 void HTTPAcceptor::bind()
|
267 mike 1.2 {
|
268 humberto 1.30 if (_rep){
269 //l10n
270 //throw BindFailedException("HTTPAcceptor already bound");
|
271 humberto 1.34
|
272 humberto 1.30 MessageLoaderParms parms("Common.HTTPAcceptor.ALREADY_BOUND",
|
273 humberto 1.34 "HTTPAcceptor already bound");
274
|
275 kumpf 1.44 Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
276 "HTTPAcceptor::bind: HTTPAcceptor already bound.");
|
277 humberto 1.30 throw BindFailedException(parms);
278 }
|
279 mike 1.2
|
280 kumpf 1.25 _rep = new HTTPAcceptorRep(_localConnection);
|
281 mike 1.2
|
282 mday 1.7 // bind address
283 _bind();
|
284 mike 1.2
|
285 mday 1.7 return;
|
286 mike 1.2 }
287
288 /**
|
289 mday 1.7 _bind - creates a new server socket and bind socket to the port address.
|
290 kumpf 1.11 If PEGASUS_LOCAL_DOMAIN_SOCKET is defined, the port number is ignored and
291 a domain socket is bound.
|
292 mike 1.2 */
293 void HTTPAcceptor::_bind()
294 {
295
|
296 mday 1.7 // Create address:
|
297 mike 1.2
|
298 kumpf 1.25 memset(_rep->address, 0, sizeof(*_rep->address));
|
299 kumpf 1.6
|
300 kumpf 1.25 if (_localConnection)
301 {
|
302 kumpf 1.11 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
|
303 kumpf 1.25 reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_family =
304 AF_UNIX;
305 strcpy(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path,
306 PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
|
307 chuck 1.38 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
308 AtoE(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
309 #endif
|
310 kumpf 1.25 ::unlink(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
|
311 kumpf 1.6 #else
|
312 kumpf 1.25 PEGASUS_ASSERT(false);
|
313 kumpf 1.11 #endif
|
314 kumpf 1.25 }
315 else
316 {
317 reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_addr.s_addr =
318 INADDR_ANY;
319 reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_family =
320 AF_INET;
321 reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_port =
322 htons(_portNumber);
323 }
|
324 mike 1.2
|
325 mday 1.7 // Create socket:
|
326 mike 1.2
|
327 kumpf 1.25 if (_localConnection)
328 {
329 _rep->socket = socket(AF_UNIX, SOCK_STREAM, 0);
330 }
331 else
332 {
333 _rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
334 }
|
335 mike 1.2
|
336 mday 1.7 if (_rep->socket < 0)
337 {
338 delete _rep;
339 _rep = 0;
|
340 humberto 1.30 //l10n
341 //throw BindFailedException("Failed to create socket");
342 MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_CREATE_SOCKET",
|
343 humberto 1.34 "Failed to create socket");
|
344 kumpf 1.44 Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
345 "HTTPAcceptor::_bind _rep->socket < 0");
|
346 humberto 1.30 throw BindFailedException(parms);
|
347 mday 1.7 }
348
|
349 mday 1.28
350 // set the close-on-exec bit for this file handle.
351 // any unix that forks needs this bit set.
352 #ifndef PEGASUS_PLATFORM_WIN32_IX86_MSVC
353 int sock_flags;
354 if( (sock_flags = fcntl(_rep->socket, F_GETFD, 0)) < 0)
355 {
|
356 kumpf 1.44 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
357 "HTTPAcceptor::_bind: fcntl(F_GETFD) failed");
|
358 mday 1.28 }
359 else
360 {
361 sock_flags |= FD_CLOEXEC;
362 if (fcntl(_rep->socket, F_SETFD, sock_flags) < 0)
363 {
|
364 kumpf 1.44 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
365 "HTTPAcceptor::_bind: fcntl(F_SETFD) failed");
|
366 mday 1.28 }
367 }
368 #endif
369
370
|
371 mday 1.7 //
372 // Set the socket option SO_REUSEADDR to reuse the socket address so
373 // that we can rebind to a new socket using the same address when we
374 // need to resume the cimom as a result of a timeout during a Shutdown
375 // operation.
376 //
377 int opt=1;
378 if (setsockopt(_rep->socket, SOL_SOCKET, SO_REUSEADDR,
379 (char *)&opt, sizeof(opt)) < 0)
380 {
|
381 mday 1.28 Socket::close(_rep->socket);
|
382 mday 1.7 delete _rep;
383 _rep = 0;
|
384 humberto 1.30 //l10n
385 //throw BindFailedException("Failed to set socket option");
386 MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SET_SOCKET_OPTION",
|
387 humberto 1.34 "Failed to set socket option");
|
388 kumpf 1.44 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
389 "HTTPAcceptor::_bind: Failed to set socket option.");
|
390 humberto 1.30 throw BindFailedException(parms);
|
391 mday 1.7 }
392
393 // Bind socket to port:
394
|
395 kumpf 1.25 if (::bind(_rep->socket, _rep->address, _rep->address_size) < 0)
|
396 mday 1.7 {
397 Socket::close(_rep->socket);
398 delete _rep;
399 _rep = 0;
|
400 humberto 1.30 //l10n
401 //throw BindFailedException("Failed to bind socket");
402 MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
|
403 humberto 1.34 "Failed to bind socket");
|
404 kumpf 1.44 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
405 "HTTPAcceptor::_bind: Failed to bind socket.");
|
406 humberto 1.30 throw BindFailedException(parms);
|
407 mday 1.7 }
408
|
409 w.otsuka 1.52.2.1 //
410 // Change permissions on Linux local domain socket to allow writes by others.
411 //
412 #if defined(PEGASUS_LOCAL_DOMAIN_SOCKET) && defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU)
413 if (_localConnection)
414 {
415 if (::chmod( PEGASUS_LOCAL_DOMAIN_SOCKET_PATH,
416 S_IRUSR | S_IWUSR | S_IXUSR |
417 S_IRGRP | S_IWGRP | S_IXGRP |
418 S_IROTH | S_IWOTH | S_IXOTH ) < 0 )
419 {
420 Socket::close(_rep->socket);
421 delete _rep;
422 _rep = 0;
423 //l10n
424 //throw BindFailedException("Failed to bind socket");
425 MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
426 "Failed to bind socket");
427 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
428 "HTTPAcceptor::_bind: Failed to set domain socket permissions.");
429 throw BindFailedException(parms);
430 w.otsuka 1.52.2.1 }
431 }
432 #endif
433
|
434 kumpf 1.11 // Set up listening on the given socket:
|
435 mday 1.7
|
436 a.arora 1.51 //int const MAX_CONNECTION_QUEUE_LENGTH = 15;
|
437 mday 1.7
438 if (listen(_rep->socket, MAX_CONNECTION_QUEUE_LENGTH) < 0)
439 {
440 Socket::close(_rep->socket);
441 delete _rep;
442 _rep = 0;
|
443 humberto 1.30 //l10n
444 //throw BindFailedException("Failed to bind socket");
445 MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
|
446 humberto 1.34 "Failed to bind socket");
|
447 kumpf 1.44 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
448 "HTTPAcceptor::_bind: Failed to bind socket(1).");
|
449 humberto 1.30 throw BindFailedException(parms);
|
450 mday 1.7 }
451
452 // Register to receive SocketMessages on this socket:
453
|
454 mday 1.21 if ( -1 == ( _entry_index = _monitor->solicitSocketMessages(
|
455 mday 1.7 _rep->socket,
456 SocketMessage::READ | SocketMessage::EXCEPTION,
|
457 mday 1.16 getQueueId(),
|
458 mday 1.21 Monitor::ACCEPTOR)))
|
459 mday 1.7 {
460 Socket::close(_rep->socket);
461 delete _rep;
462 _rep = 0;
|
463 humberto 1.30 //l10n
464 //throw BindFailedException("Failed to solicit socket messaeges");
465 MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SOLICIT_SOCKET_MESSAGES",
|
466 humberto 1.34 "Failed to solicit socket messaeges");
|
467 kumpf 1.44 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
468 "HTTPAcceptor::_bind: Failed to solicit socket messages(2).");
|
469 humberto 1.30 throw BindFailedException(parms);
|
470 mday 1.7 }
|
471 mike 1.2 }
472
473 /**
|
474 mday 1.7 closeConnectionSocket - close the server listening socket to disallow
475 new client connections.
|
476 mike 1.2 */
477 void HTTPAcceptor::closeConnectionSocket()
478 {
|
479 mday 1.7 if (_rep)
480 {
481 // unregister the socket
|
482 kumpf 1.35
483 // ATTN - comment out - see CIMServer::stopClientConnection()
484 //_monitor->unsolicitSocketMessages(_rep->socket);
|
485 mday 1.7
486 // close the socket
487 Socket::close(_rep->socket);
488 }
|
489 kumpf 1.44 else
490 {
491 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
492 "HTTPAcceptor::closeConnectionSocket failure _rep is null." );
493 }
|
494 mike 1.2 }
495
496 /**
|
497 mday 1.7 reopenConnectionSocket - creates a new server socket.
|
498 mike 1.2 */
499 void HTTPAcceptor::reopenConnectionSocket()
500 {
|
501 mday 1.7 if (_rep)
502 {
503 _bind();
504 }
|
505 kumpf 1.44 else
506 {
507 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
508 "HTTPAcceptor::reopenConnectionSocket failure _rep is null." );
509 }
|
510 mike 1.2 }
511
512 /**
|
513 mday 1.7 getOutstandingRequestCount - returns the number of outstanding requests.
|
514 mike 1.2 */
515 Uint32 HTTPAcceptor::getOutstandingRequestCount()
516 {
|
517 mday 1.28 Uint32 count = 0;
518
|
519 a.arora 1.50 AutoMutex autoMut(_rep->_connection_mut);
|
520 mday 1.7 if (_rep->connections.size() > 0)
521 {
522 HTTPConnection* connection = _rep->connections[0];
|
523 mday 1.28 count = connection->getRequestCount();
|
524 mday 1.7 }
|
525 a.arora 1.50
|
526 mday 1.28 return count;
|
527 mike 1.2 }
528
529 void HTTPAcceptor::unbind()
530 {
|
531 mday 1.7 if (_rep)
532 {
533 Socket::close(_rep->socket);
|
534 kumpf 1.25
535 if (_localConnection)
536 {
537 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
538 ::unlink(
539 reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
540 #else
541 PEGASUS_ASSERT(false);
542 #endif
543 }
544
|
545 mday 1.7 delete _rep;
546 _rep = 0;
547 }
|
548 kumpf 1.44 else
549 {
550 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
551 "HTTPAcceptor::unbind failure _rep is null." );
552 }
|
553 mike 1.2 }
554
555 void HTTPAcceptor::destroyConnections()
556 {
|
557 mday 1.28
558
|
559 mday 1.7 // For each connection created by this object:
|
560 mike 1.2
|
561 a.arora 1.50 AutoMutex autoMut(_rep->_connection_mut);
|
562 mday 1.7 for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
563 {
564 HTTPConnection* connection = _rep->connections[i];
565 Sint32 socket = connection->getSocket();
|
566 mike 1.2
|
567 mday 1.7 // Unsolicit SocketMessages:
|
568 mike 1.2
|
569 mday 1.7 _monitor->unsolicitSocketMessages(socket);
|
570 mike 1.2
|
571 mday 1.7 // Destroy the connection (causing it to close):
|
572 mike 1.2
|
573 kumpf 1.17 while (connection->refcount.value()) { }
|
574 mday 1.7 delete connection;
575 }
|
576 mike 1.2
|
577 mday 1.7 _rep->connections.clear();
|
578 a.arora 1.50
|
579 mike 1.2 }
580
581 void HTTPAcceptor::_acceptConnection()
582 {
|
583 mday 1.7 // This function cannot be called on an invalid socket!
|
584 mike 1.2
|
585 mday 1.7 PEGASUS_ASSERT(_rep != 0);
|
586 mike 1.2
|
587 mday 1.7 if (!_rep)
588 return;
|
589 mike 1.2
|
590 mday 1.7 // Accept the connection (populate the address):
|
591 mike 1.2
|
592 kumpf 1.25 struct sockaddr* accept_address;
593 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
594 size_t address_size;
|
595 keith.petley 1.42 #elif defined(PEGASUS_PLATFORM_AIX_RS_IBMCXX) || defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || (defined(PEGASUS_OS_SOLARIS) && !defined(SUNOS_5_6))
|
596 kumpf 1.25 socklen_t address_size;
|
597 mike 1.2 #else
|
598 kumpf 1.25 int address_size;
|
599 mike 1.2 #endif
600
|
601 kumpf 1.25 if (_localConnection)
602 {
603 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
604 accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
605 address_size = sizeof(struct sockaddr_un);
|
606 mike 1.2 #else
|
607 kumpf 1.25 PEGASUS_ASSERT(false);
|
608 mike 1.2 #endif
|
609 kumpf 1.25 }
610 else
611 {
612 accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
613 address_size = sizeof(struct sockaddr_in);
614 }
615
616 Sint32 socket = accept(_rep->socket, accept_address, &address_size);
617
618 delete accept_address;
|
619 mike 1.2
|
620 mday 1.7 if (socket < 0)
621 {
|
622 mday 1.36
|
623 david 1.27 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
624 "HTTPAcceptor - accept() failure. errno: $0"
625 ,errno);
626
|
627 kumpf 1.44 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
|
628 kumpf 1.19 "HTTPAcceptor: accept() failed");
|
629 mday 1.7 return;
630 }
|
631 david 1.27
|
632 mday 1.28 // set the close on exec flag
633 #ifndef PEGASUS_PLATFORM_WIN32_IX86_MSVC
634 int sock_flags;
635 if( (sock_flags = fcntl(socket, F_GETFD, 0)) < 0)
636 {
|
637 kumpf 1.44 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
|
638 mday 1.28 "HTTPAcceptor: fcntl(F_GETFD) failed");
639 }
640 else
641 {
642 sock_flags |= FD_CLOEXEC;
643 if (fcntl(socket, F_SETFD, sock_flags) < 0)
644 {
|
645 kumpf 1.44 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
|
646 mday 1.28 "HTTPAcceptor: fcntl(F_SETFD) failed");
647 }
648 }
649 #endif
650
651
|
652 david 1.27 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
653 "HTTPAcceptor - accept() success. Socket: $1"
654 ,socket);
|
655 mike 1.2
|
656 mday 1.7 // Create a new conection and add it to the connection list:
|
657 mike 1.2
|
658 kumpf 1.49 AutoPtr<MP_Socket> mp_socket(new MP_Socket(socket, _sslcontext, _exportConnection));
|
659 kumpf 1.19 if (mp_socket->accept() < 0)
660 {
|
661 kumpf 1.44 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
|
662 kumpf 1.19 "HTTPAcceptor: SSL_accept() failed");
|
663 mday 1.7 return;
664 }
|
665 mike 1.2
|
666 kumpf 1.49 HTTPConnection* connection = new HTTPConnection(_monitor, mp_socket,
667 this, static_cast<MessageQueue *>(_outputMessageQueue), _exportConnection);
|
668 mike 1.2
|
669 mday 1.7 // Solicit events on this new connection's socket:
|
670 mday 1.21 int index;
671
|
672 mday 1.22 if (-1 == (index = _monitor->solicitSocketMessages(
|
673 mday 1.7 socket,
674 SocketMessage::READ | SocketMessage::EXCEPTION,
|
675 mday 1.21 connection->getQueueId(), Monitor::CONNECTION)) )
|
676 mday 1.7 {
|
677 kumpf 1.37 // ATTN-DE-P2-2003100503::TODO::Need to enhance code to return
678 // an error message to Client application.
|
679 kumpf 1.44 Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
680 "HTTPAcceptor::_acceptConnection: Attempt to allocate entry in _entries table failed.");
|
681 mday 1.7 delete connection;
682 Socket::close(socket);
|
683 kumpf 1.37 return;
|
684 mday 1.7 }
|
685 a.arora 1.48
686 mp_socket.release();
|
687 mike 1.2
|
688 mday 1.7 // Save the socket for cleanup later:
|
689 mday 1.21 connection->_entry_index = index;
|
690 a.arora 1.50 AutoMutex autoMut(_rep->_connection_mut);
|
691 mday 1.7 _rep->connections.append(connection);
|
692 a.arora 1.50
|
693 mike 1.2 }
|
694 mday 1.32
695 AsyncDQueue<pegasus_acceptor> pegasus_acceptor::acceptors(true, 0);
696
|
697 mday 1.39 void pegasus_acceptor::close_all_acceptors(void)
698 {
699 try
700 {
701 pegasus_acceptor* temp = acceptors.remove_first();
702 while(temp)
703 {
704 delete temp;
705 temp = acceptors.remove_first();
706 }
707 }
708 catch(...)
709 {
710 }
711
712 }
713
714
715
|
716 mday 1.32 pegasus_acceptor::pegasus_acceptor(monitor_2* monitor,
717 MessageQueue* outputMessageQueue,
718 Boolean localConnection,
719 Uint32 portNumber,
720 SSLContext* sslcontext)
721 : _monitor(monitor), _outputMessageQueue(outputMessageQueue),
722 _localConnection(localConnection), _portNumber(portNumber),
723 _sslcontext(sslcontext), connections(true, 0)
724 {
725
726 Socket::initializeInterface();
727 try {
728 acceptors.insert_first(this);
729 }
730 catch(...){
731 }
732
733 }
734
735 pegasus_acceptor::~pegasus_acceptor(void)
736 {
737 mday 1.32 unbind();
738 Socket::uninitializeInterface();
739 try {
740 acceptors.remove(this);
741 }
742 catch(...){
743 }
744
745 }
746
747
748 void pegasus_acceptor::bind()
749 {
750
751 PEGASUS_SOCKLEN_SIZE addr_size;
752 struct sockaddr *addr;
753 struct sockaddr_in addr_in;
754 # ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
755 struct sockaddr_un addr_un;
756 #endif
757
758 mday 1.32 memset(&addr_in, 0, sizeof(addr_in));
759 addr_in.sin_addr.s_addr = INADDR_ANY;
760 addr_in.sin_family = AF_INET;
761 addr_in.sin_port = htons(_portNumber);
762 addr = (struct sockaddr*) &addr_in;
763 addr_size = sizeof(addr_in);
764
765 // first step: determine which kind of socket factory to initialize,
766 // then create the socket and bind it to an address
767 if(_localConnection == true){
768 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
769 unix_socket_factory sf;
770 pegasus_socket temp(&sf);
771 _listener = temp;
772
773 memset(&addr_un, 0, sizeof(addr_un));
|
774 mday 1.33 addr_un.sun_family = AF_UNIX;
775 strcpy(addr_un.sun_path, PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
|
776 chuck 1.38 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
777 AtoE(addr_un.sun_path);
778 #endif
|
779 mday 1.32 addr = (struct sockaddr*) &addr_un;
780 addr_size = sizeof(addr_un);
781 _listener.socket(AF_UNIX, SOCK_STREAM, 0);
782 #else
783 bsd_socket_factory sf;
784 pegasus_socket temp(&sf);
785 _listener = temp;
786 _listener.socket(AF_UNIX, SOCK_STREAM, 0);
787 #endif
788 }
789 else if( _sslcontext != 0 ) {
790 #ifdef PEGASUS_HAS_SSL
791 ssl_socket_factory sf;
|
792 konrad.r 1.47 pegasus_socket temp(&sf, _sslcontext);
|
793 mday 1.32 #else
794 bsd_socket_factory sf;
|
795 konrad.r 1.47 pegasus_socket temp(&sf);
|
796 mday 1.32 #endif
797 _listener = temp;
798 _listener.socket(PF_INET, SOCK_STREAM, 0);
799 }
800 else {
801 bsd_socket_factory sf;
802 pegasus_socket temp(&sf);
803 _listener = temp;
804 _listener.socket(PF_INET, SOCK_STREAM, 0);
805 }
806
807 _listener.bind((struct sockaddr*)addr, addr_size);
808
809 // second step: listen on the socket
810
811 _listener.listen(5);
812
813 // third step: add this listening socket to the monitor
814
815 _monitor->tickle();
816 _monitor->add_entry(_listener, LISTEN, this, this);
817 mday 1.32 }
818
819
820 /** Unbind from the given port.
821 */
822 void pegasus_acceptor::unbind()
823 {
824 // remove the socket from the monitor
825 _monitor->remove_entry((Sint32)_listener);
826
827 // close the socket
828 _listener.close();
829 }
830
831
832 /** Close the connection socket.
833 */
834 void pegasus_acceptor::closeConnectionSocket()
835 {
836 unbind();
837 }
838 mday 1.32
839
840 /** Reopen the connection socket.
841 */
842 void pegasus_acceptor::reopenConnectionSocket()
843 {
844 bind();
845 }
846
847
848 /** Returns the number of outstanding requests
849 */
850 Uint32 pegasus_acceptor::getOutstandingRequestCount()
851 {
852 return _monitor->getOutstandingRequestCount();
853 }
854
855 Boolean pegasus_acceptor::operator ==(const pegasus_acceptor& pa)
856 {
857 if(this == &pa)
858 return true;
859 mday 1.32 return false;
860 }
861
862 Boolean pegasus_acceptor::operator ==(void* pa)
863 {
864 if((void*)this == pa)
865 return true;
866 return false;
867 }
868
869
870 pegasus_acceptor* pegasus_acceptor::find_acceptor(Boolean local, Uint32 port)
871 {
872 pegasus_acceptor* temp = 0;
873
874 try {
875 acceptors.try_lock(pegasus_thread_self());
876 temp = acceptors.next(temp);
877 while(temp){
878 if( local == true ){
879 if(temp->_localConnection){
880 mday 1.32 acceptors.unlock();
881 return temp;
882 }
883 }
884 if(temp->_localConnection == local && temp->_portNumber ==port){
885 acceptors.unlock();
886 return temp;
887 }
888 temp = acceptors.next(temp);
889 }
890 acceptors.unlock();
891 }
892 catch(...){
893 }
894 return temp;
895 }
896
897 class m2e_rep;
898
899 void pegasus_acceptor::accept_dispatch(monitor_2_entry *entry)
900 {
901 mday 1.32 pegasus_acceptor* myself = (pegasus_acceptor*)entry->get_accept();
902
903 HTTPConnection2* connection = new HTTPConnection2(entry->_rep->psock, myself->_outputMessageQueue);
904
905 // set the entry's dispatch parameter to point to the connection object
906 entry->set_dispatch ((void*)connection);
907
|
908 mday 1.36 monitor_2::insert_connection(connection);
|
909 mday 1.39
|
910 mday 1.32 }
911
|
912 mike 1.2
913 PEGASUS_NAMESPACE_END
|