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 1.74 // David Dillard, Symantec Corp. (david_dillard@symantec.com)
|
43 j.alex 1.67 // John Alex, IBM (johnalex@us.ibm.com) for Bug#3312
|
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 david.dillard 1.65
|
85 a.arora 1.51 static int MAX_CONNECTION_QUEUE_LENGTH = -1;
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 konrad.r 1.69 ~HTTPAcceptorRep()
114 {
|
115 david.dillard 1.73 delete address;
|
116 konrad.r 1.69 }
|
117 kumpf 1.25 struct sockaddr* address;
118
|
119 mike 1.77 PEGASUS_SOCKLEN_T address_size;
120 Mutex _connection_mut;
|
121 david.dillard 1.64
|
122 mike 1.77 PEGASUS_SOCKET socket;
123 Array<HTTPConnection*> connections;
|
124 mike 1.2 };
125
126 ////////////////////////////////////////////////////////////////////////////////
127 //
128 // HTTPAcceptor
129 //
130 ////////////////////////////////////////////////////////////////////////////////
131
|
132 kumpf 1.25 HTTPAcceptor::HTTPAcceptor(Monitor* monitor,
133 MessageQueue* outputMessageQueue,
134 Boolean localConnection,
135 Uint32 portNumber,
|
136 kumpf 1.49 SSLContext * sslcontext,
|
137 nag.boranna 1.59 Boolean exportConnection,
138 ReadWriteSem* sslContextObjectLock)
|
139 kumpf 1.25 : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR), // ATTN: Need unique names?
140 _monitor(monitor),
141 _outputMessageQueue(outputMessageQueue),
142 _rep(0),
143 _entry_index(-1),
144 _localConnection(localConnection),
145 _portNumber(portNumber),
|
146 kumpf 1.49 _sslcontext(sslcontext),
|
147 nag.boranna 1.59 _exportConnection(exportConnection),
148 _sslContextObjectLock(sslContextObjectLock)
|
149 mike 1.2 {
|
150 mday 1.7 Socket::initializeInterface();
|
151 david.dillard 1.64
|
152 a.arora 1.51 /*
153 Platforms interpret the value of MAX_CONNECTION_QUEUE_LENGTH differently. Some platforms interpret
154 the value literally, while others multiply a fudge factor. When the server is under
155 stress from multiple clients with multiple requests, toggling this number may prevent clients from
156 being dropped. Instead of hard coding the value, we allow an environment variable to be set which
157 specifies a number greater than the maximum concurrent client connections possible. If this environment
158 var is not specified, then MAX_CONNECTION_QUEUE_LENGTH = 15.
159 */
160
161 //To engage runtime backlog queue length: uncomment the following block AND comment out the line MAX_CONNECTION_QUEUE_LENGTH = 15
162
163 /*
164 if(MAX_CONNECTION_QUEUE_LENGTH == -1){
165 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
166 #pragma convert(37)
|
167 h.sterling 1.63 const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE");
168 EtoA(env);
|
169 a.arora 1.51 #pragma convert(0)
170 #else
|
171 h.sterling 1.63 const char* env = getenv("PEGASUS_MAX_BACKLOG_CONNECTION_QUEUE");
|
172 a.arora 1.51 #endif
|
173 h.sterling 1.63 if(!env){
174 MAX_CONNECTION_QUEUE_LENGTH = 15;
|
175 david.dillard 1.64 }else{
|
176 h.sterling 1.63 char *end = NULL;
177 MAX_CONNECTION_QUEUE_LENGTH = strtol(env, &end, 10);
178 if(*end)
179 MAX_CONNECTION_QUEUE_LENGTH = 15;
180 cout << " MAX_CONNECTION_QUEUE_LENGTH = " << MAX_CONNECTION_QUEUE_LENGTH << endl;
181 }
|
182 a.arora 1.51 }
183 */
184 MAX_CONNECTION_QUEUE_LENGTH = 15;
|
185 david.dillard 1.64
|
186 mike 1.2 }
187
188 HTTPAcceptor::~HTTPAcceptor()
189 {
|
190 konrad.r 1.70 destroyConnections();
|
191 mday 1.7 unbind();
|
192 kumpf 1.25 // ATTN: Is this correct in a multi-HTTPAcceptor server?
|
193 mday 1.7 Socket::uninitializeInterface();
|
194 mike 1.2 }
195
|
196 mday 1.7 void HTTPAcceptor::handleEnqueue(Message *message)
|
197 mike 1.2 {
|
198 mday 1.7 if (! message)
199 return;
|
200 david.dillard 1.64
|
201 konrad.r 1.68 PEGASUS_ASSERT(_rep != 0);
|
202 mday 1.7 switch (message->getType())
203 {
204 case SOCKET_MESSAGE:
205 {
|
206 h.sterling 1.63 SocketMessage* socketMessage = (SocketMessage*)message;
|
207 david.dillard 1.64
|
208 h.sterling 1.63 // If this is a connection request:
209
210 if (socketMessage->socket == _rep->socket &&
211 socketMessage->events & SocketMessage::READ)
212 {
213 _acceptConnection();
214 }
215 else
216 {
217 // ATTN! this can't happen!
|
218 kumpf 1.44 Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
219 "HTTPAcceptor::handleEnqueue: Invalid SOCKET_MESSAGE received.");
|
220 h.sterling 1.63 }
|
221 mday 1.7
|
222 h.sterling 1.63 break;
|
223 mday 1.7 }
224
225 case CLOSE_CONNECTION_MESSAGE:
226 {
|
227 david.dillard 1.64 CloseConnectionMessage* closeConnectionMessage
|
228 h.sterling 1.63 = (CloseConnectionMessage*)message;
229
230 AutoMutex autoMut(_rep->_connection_mut);
|
231 david.dillard 1.64
|
232 h.sterling 1.63 for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
233 {
|
234 david.dillard 1.64 HTTPConnection* connection = _rep->connections[i];
|
235 david.dillard 1.74 PEGASUS_SOCKET socket = connection->getSocket();
|
236 mday 1.7
|
237 h.sterling 1.63 if (socket == closeConnectionMessage->socket)
238 {
239 _monitor->unsolicitSocketMessages(socket);
240 _rep->connections.remove(i);
|
241 kumpf 1.17 delete connection;
|
242 h.sterling 1.63 break;
243 }
244 }
|
245 david.dillard 1.64
|
246 h.sterling 1.63 break;
|
247 mday 1.7 }
|
248 mike 1.2
|
249 kumpf 1.10 default:
250 // ATTN: need unexpected message error!
|
251 kumpf 1.44 Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
252 "HTTPAcceptor::handleEnqueue: Invalid MESSAGE received.");
|
253 mday 1.7 break;
254 };
|
255 mike 1.2
|
256 mday 1.7 delete message;
257 }
|
258 mike 1.2
259
|
260 mday 1.7 void HTTPAcceptor::handleEnqueue()
261 {
262 Message* message = dequeue();
|
263 mike 1.2
|
264 mday 1.7 if (!message)
|
265 kumpf 1.44 {
266 Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
267 "HTTPAcceptor::handleEnqueue(): No message on queue.");
|
268 mday 1.7 return;
|
269 kumpf 1.44 }
|
270 david.dillard 1.64
|
271 mday 1.7 handleEnqueue(message);
|
272 mike 1.2
273 }
274
|
275 kumpf 1.25 void HTTPAcceptor::bind()
|
276 mike 1.2 {
|
277 humberto 1.30 if (_rep){
|
278 h.sterling 1.63 //l10n
|
279 david.dillard 1.64 //throw BindFailedException("HTTPAcceptor already bound");
|
280 humberto 1.34
|
281 humberto 1.30 MessageLoaderParms parms("Common.HTTPAcceptor.ALREADY_BOUND",
|
282 h.sterling 1.63 "HTTPAcceptor already bound");
|
283 humberto 1.34
|
284 kumpf 1.44 Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
285 "HTTPAcceptor::bind: HTTPAcceptor already bound.");
|
286 humberto 1.30 throw BindFailedException(parms);
287 }
|
288 mike 1.2
|
289 kumpf 1.25 _rep = new HTTPAcceptorRep(_localConnection);
|
290 mike 1.2
|
291 mday 1.7 // bind address
292 _bind();
|
293 mike 1.2
|
294 mday 1.7 return;
|
295 mike 1.2 }
296
297 /**
|
298 mday 1.7 _bind - creates a new server socket and bind socket to the port address.
|
299 h.sterling 1.63 If PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET is not defined, the port number is ignored and
|
300 kumpf 1.11 a domain socket is bound.
|
301 mike 1.2 */
302 void HTTPAcceptor::_bind()
303 {
304
|
305 konrad.r 1.68 PEGASUS_ASSERT(_rep != 0);
|
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 david.dillard 1.65 PEGASUS_SOCKLEN_T bufSize = sizeof(buf);
|
429 david.dillard 1.64 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 j.alex 1.67 // Unlink Local Domain Socket Bug# 3312
516 if (_localConnection)
517 {
518 #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
|
519 denise.eckstein 1.71 PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
|
520 j.alex 1.67 "HTTPAcceptor::closeConnectionSocket Unlinking local connection." );
521 ::unlink(
522 reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
523 #else
524 PEGASUS_ASSERT(false);
525 #endif
526 }
527
|
528 mday 1.7 }
|
529 kumpf 1.44 else
530 {
531 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
532 "HTTPAcceptor::closeConnectionSocket failure _rep is null." );
533 }
|
534 mike 1.2 }
535
536 /**
|
537 mday 1.7 reopenConnectionSocket - creates a new server socket.
|
538 mike 1.2 */
539 void HTTPAcceptor::reopenConnectionSocket()
540 {
|
541 mday 1.7 if (_rep)
542 {
543 _bind();
544 }
|
545 kumpf 1.44 else
546 {
547 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
548 "HTTPAcceptor::reopenConnectionSocket failure _rep is null." );
549 }
|
550 mike 1.2 }
551
552 /**
|
553 mday 1.7 getOutstandingRequestCount - returns the number of outstanding requests.
|
554 mike 1.2 */
|
555 david.dillard 1.64 Uint32 HTTPAcceptor::getOutstandingRequestCount() const
|
556 mike 1.2 {
|
557 mday 1.28 Uint32 count = 0;
|
558 konrad.r 1.68 if (_rep)
|
559 mday 1.7 {
|
560 konrad.r 1.68 AutoMutex autoMut(_rep->_connection_mut);
561 if (_rep->connections.size() > 0)
562 {
563 HTTPConnection* connection = _rep->connections[0];
564 count = connection->getRequestCount();
565 }
|
566 mday 1.7 }
|
567 mday 1.28 return count;
|
568 mike 1.2 }
569
|
570 david.dillard 1.64
571 /**
572 getPortNumber - returns the port number used for the connection
573 */
574 Uint32 HTTPAcceptor::getPortNumber() const
575 {
576 return _portNumber;
577 }
578
|
579 mike 1.2 void HTTPAcceptor::unbind()
580 {
|
581 mday 1.7 if (_rep)
582 {
|
583 david.dillard 1.64 _portNumber = 0;
|
584 mday 1.7 Socket::close(_rep->socket);
|
585 kumpf 1.25
586 if (_localConnection)
587 {
|
588 h.sterling 1.63 #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
|
589 kumpf 1.25 ::unlink(
590 reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
591 #else
592 PEGASUS_ASSERT(false);
593 #endif
594 }
595
|
596 mday 1.7 delete _rep;
597 _rep = 0;
598 }
|
599 kumpf 1.44 else
600 {
601 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
602 "HTTPAcceptor::unbind failure _rep is null." );
603 }
|
604 mike 1.2 }
605
606 void HTTPAcceptor::destroyConnections()
607 {
|
608 konrad.r 1.68 if (_rep)
609 {
610 // For each connection created by this object:
|
611 mday 1.28
|
612 konrad.r 1.68 AutoMutex autoMut(_rep->_connection_mut);
613 for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
614 {
615 HTTPConnection* connection = _rep->connections[i];
|
616 david.dillard 1.74 PEGASUS_SOCKET socket = connection->getSocket();
|
617 mike 1.2
|
618 konrad.r 1.68 // Unsolicit SocketMessages:
|
619 mike 1.2
|
620 konrad.r 1.68 _monitor->unsolicitSocketMessages(socket);
|
621 mike 1.2
|
622 konrad.r 1.68 // Destroy the connection (causing it to close):
|
623 mike 1.2
|
624 mike 1.75 while (connection->refcount.get()) { }
|
625 konrad.r 1.68 delete connection;
626 }
|
627 mike 1.2
|
628 konrad.r 1.68 _rep->connections.clear();
|
629 mday 1.7 }
|
630 mike 1.2 }
631
632 void HTTPAcceptor::_acceptConnection()
633 {
|
634 mday 1.7 // This function cannot be called on an invalid socket!
|
635 mike 1.2
|
636 mday 1.7 PEGASUS_ASSERT(_rep != 0);
|
637 mike 1.2
|
638 mday 1.7 if (!_rep)
639 return;
|
640 mike 1.2
|
641 mday 1.7 // Accept the connection (populate the address):
|
642 mike 1.2
|
643 kumpf 1.25 struct sockaddr* accept_address;
|
644 mike 1.77 PEGASUS_SOCKLEN_T address_size;
|
645 mike 1.2
|
646 kumpf 1.25 if (_localConnection)
647 {
|
648 h.sterling 1.63 #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
|
649 kumpf 1.25 accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
650 address_size = sizeof(struct sockaddr_un);
|
651 mike 1.2 #else
|
652 kumpf 1.25 PEGASUS_ASSERT(false);
|
653 mike 1.2 #endif
|
654 kumpf 1.25 }
655 else
656 {
657 accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
658 address_size = sizeof(struct sockaddr_in);
659 }
660
|
661 david.dillard 1.73 PEGASUS_SOCKET socket = accept(_rep->socket, accept_address, &address_size);
|
662 kumpf 1.25
663 delete accept_address;
|
664 mike 1.2
|
665 mday 1.7 if (socket < 0)
666 {
|
667 mday 1.36
|
668 david 1.27 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
|
669 h.sterling 1.63 "HTTPAcceptor - accept() failure. errno: $0"
670 ,errno);
|
671 david 1.27
|
672 kumpf 1.44 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
|
673 kumpf 1.19 "HTTPAcceptor: accept() failed");
|
674 mday 1.7 return;
675 }
|
676 david 1.27
|
677 david.dillard 1.64 // set the close on exec flag
|
678 gs.keenan 1.58 #if !defined PEGASUS_PLATFORM_WIN32_IX86_MSVC && !defined(PEGASUS_OS_VMS)
|
679 mday 1.28 int sock_flags;
680 if( (sock_flags = fcntl(socket, F_GETFD, 0)) < 0)
681 {
|
682 kumpf 1.44 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
|
683 mday 1.28 "HTTPAcceptor: fcntl(F_GETFD) failed");
684 }
685 else
686 {
687 sock_flags |= FD_CLOEXEC;
688 if (fcntl(socket, F_SETFD, sock_flags) < 0)
689 {
|
690 kumpf 1.44 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
|
691 mday 1.28 "HTTPAcceptor: fcntl(F_SETFD) failed");
692 }
693 }
|
694 david.dillard 1.64 #endif
|
695 mday 1.28
696
|
697 mike 1.76 PEG_LOGGER_TRACE((Logger::STANDARD_LOG, System::CIMSERVER, 0,
698 "HTTPAcceptor - accept() success. Socket: $1" ,socket));
|
699 mike 1.2
|
700 kumpf 1.72 AutoPtr<MP_Socket> mp_socket(new MP_Socket(
701 socket, _sslcontext, _sslContextObjectLock, _exportConnection));
|
702 mike 1.2
|
703 kumpf 1.72 // Perform the SSL handshake, if applicable. Make the socket non-blocking
704 // for this operation so we can send it back to the Monitor's select() loop
705 // if it takes a while.
706
707 mp_socket->disableBlocking();
708 Sint32 socketAcceptStatus = mp_socket->accept();
709 mp_socket->enableBlocking();
|
710 nag.boranna 1.59
|
711 kumpf 1.72 if (socketAcceptStatus < 0)
|
712 kumpf 1.19 {
|
713 nag.boranna 1.61 PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2,
|
714 kumpf 1.19 "HTTPAcceptor: SSL_accept() failed");
|
715 nag.boranna 1.61 mp_socket->close();
716 return;
|
717 mday 1.7 }
|
718 mike 1.2
|
719 kumpf 1.72 // Create a new connection and add it to the connection list:
720
|
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 kumpf 1.72 if (socketAcceptStatus == 0)
725 {
726 PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
727 "HTTPAcceptor: SSL_accept() pending");
728 connection->_acceptPending = true;
729 }
730
|
731 mday 1.7 // Solicit events on this new connection's socket:
|
732 mday 1.21 int index;
|
733 david.dillard 1.64
|
734 mday 1.22 if (-1 == (index = _monitor->solicitSocketMessages(
|
735 h.sterling 1.63 connection->getSocket(),
736 SocketMessage::READ | SocketMessage::EXCEPTION,
737 connection->getQueueId(), Monitor::CONNECTION)) )
|
738 mday 1.7 {
|
739 kumpf 1.37 // ATTN-DE-P2-2003100503::TODO::Need to enhance code to return
740 // an error message to Client application.
|
741 kumpf 1.44 Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
742 "HTTPAcceptor::_acceptConnection: Attempt to allocate entry in _entries table failed.");
|
743 mday 1.7 delete connection;
744 Socket::close(socket);
|
745 kumpf 1.37 return;
|
746 mday 1.7 }
|
747 a.arora 1.48
|
748 mday 1.7 // Save the socket for cleanup later:
|
749 mday 1.21 connection->_entry_index = index;
|
750 a.arora 1.50 AutoMutex autoMut(_rep->_connection_mut);
|
751 mday 1.7 _rep->connections.append(connection);
|
752 mike 1.2 }
|
753 mday 1.32
|
754 mike 1.2 PEGASUS_NAMESPACE_END
|