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