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