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