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