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