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