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