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