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 PEGASUS_USING_STD;
63
64 PEGASUS_NAMESPACE_BEGIN
65
66 ////////////////////////////////////////////////////////////////////////////////
67 //
68 // HTTPAcceptorRep
69 //
70 ////////////////////////////////////////////////////////////////////////////////
71
|
72 kumpf 1.25 class HTTPAcceptorRep
|
73 mike 1.2 {
|
74 kumpf 1.25 public:
75 HTTPAcceptorRep(Boolean local)
76 {
77 if (local)
78 {
|
79 kumpf 1.11 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
|
80 kumpf 1.25 address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
81 address_size = sizeof(struct sockaddr_un);
|
82 kumpf 1.11 #else
|
83 kumpf 1.25 PEGASUS_ASSERT(false);
|
84 kumpf 1.11 #endif
|
85 david 1.27 }
|
86 kumpf 1.25 else
87 {
88 address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
89 address_size = sizeof(struct sockaddr_in);
90 }
91 }
92
93 struct sockaddr* address;
94
95 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
96 size_t address_size;
|
97 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))
|
98 kumpf 1.25 socklen_t address_size;
99 #else
100 int address_size;
101 #endif
|
102 mday 1.28 Mutex _connection_mut;
103
104 Sint32 socket;
105 Array<HTTPConnection*> connections;
|
106 mike 1.2 };
107
108 ////////////////////////////////////////////////////////////////////////////////
109 //
110 // HTTPAcceptor
111 //
112 ////////////////////////////////////////////////////////////////////////////////
113
|
114 kumpf 1.25 HTTPAcceptor::HTTPAcceptor(Monitor* monitor,
115 MessageQueue* outputMessageQueue,
116 Boolean localConnection,
117 Uint32 portNumber,
|
118 mike 1.2 SSLContext * sslcontext)
|
119 kumpf 1.25 : Base(PEGASUS_QUEUENAME_HTTPACCEPTOR), // ATTN: Need unique names?
120 _monitor(monitor),
121 _outputMessageQueue(outputMessageQueue),
122 _rep(0),
123 _entry_index(-1),
124 _localConnection(localConnection),
125 _portNumber(portNumber),
126 _sslcontext(sslcontext)
|
127 mike 1.2 {
|
128 mday 1.7 Socket::initializeInterface();
|
129 mike 1.2 }
130
131 HTTPAcceptor::~HTTPAcceptor()
132 {
|
133 mday 1.7 unbind();
|
134 kumpf 1.25 // ATTN: Is this correct in a multi-HTTPAcceptor server?
|
135 mday 1.7 Socket::uninitializeInterface();
|
136 mike 1.2 }
137
|
138 mday 1.7 void HTTPAcceptor::handleEnqueue(Message *message)
|
139 mike 1.2 {
|
140 mday 1.7 if (! message)
141 return;
142
143 switch (message->getType())
144 {
145 case SOCKET_MESSAGE:
146 {
147 SocketMessage* socketMessage = (SocketMessage*)message;
|
148 mday 1.32
|
149 mday 1.7 // If this is a connection request:
150
151 if (socketMessage->socket == _rep->socket &&
152 socketMessage->events | SocketMessage::READ)
153 {
154 _acceptConnection();
155 }
156 else
157 {
158 // ATTN! this can't happen!
159 }
160
161 break;
162 }
163
164 case CLOSE_CONNECTION_MESSAGE:
165 {
166 CloseConnectionMessage* closeConnectionMessage
167 = (CloseConnectionMessage*)message;
168
|
169 mday 1.28 _rep->_connection_mut.lock(pegasus_thread_self());
170
|
171 mday 1.7 for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
172 {
173 HTTPConnection* connection = _rep->connections[i];
174 Sint32 socket = connection->getSocket();
|
175 mike 1.2
|
176 mday 1.7 if (socket == closeConnectionMessage->socket)
|
177 mike 1.2 {
|
178 mday 1.7 _monitor->unsolicitSocketMessages(socket);
179 _rep->connections.remove(i);
|
180 kumpf 1.17 delete connection;
|
181 mday 1.7 break;
|
182 mike 1.2 }
|
183 mday 1.7 }
|
184 mday 1.28 _rep->_connection_mut.unlock();
|
185 mday 1.7 }
|
186 mike 1.2
|
187 kumpf 1.10 default:
188 // ATTN: need unexpected message error!
|
189 mday 1.7 break;
190 };
|
191 mike 1.2
|
192 mday 1.7 delete message;
193 }
|
194 mike 1.2
195
|
196 mday 1.7 void HTTPAcceptor::handleEnqueue()
197 {
198 Message* message = dequeue();
|
199 mike 1.2
|
200 mday 1.7 if (!message)
201 return;
202
203 handleEnqueue(message);
|
204 mike 1.2
205 }
206
|
207 kumpf 1.25 void HTTPAcceptor::bind()
|
208 mike 1.2 {
|
209 humberto 1.30 if (_rep){
210 //l10n
211 //throw BindFailedException("HTTPAcceptor already bound");
212 String s0 = "HTTPAcceptor";
213 MessageLoaderParms parms("Common.HTTPAcceptor.ALREADY_BOUND",
214 "$0 already bound",
215 s0);
216 throw BindFailedException(parms);
217 }
|
218 mike 1.2
|
219 kumpf 1.25 _rep = new HTTPAcceptorRep(_localConnection);
|
220 mike 1.2
|
221 mday 1.7 // bind address
222 _bind();
|
223 mike 1.2
|
224 mday 1.7 return;
|
225 mike 1.2 }
226
227 /**
|
228 mday 1.7 _bind - creates a new server socket and bind socket to the port address.
|
229 kumpf 1.11 If PEGASUS_LOCAL_DOMAIN_SOCKET is defined, the port number is ignored and
230 a domain socket is bound.
|
231 mike 1.2 */
232 void HTTPAcceptor::_bind()
233 {
234
|
235 mday 1.7 // Create address:
|
236 mike 1.2
|
237 kumpf 1.25 memset(_rep->address, 0, sizeof(*_rep->address));
|
238 kumpf 1.6
|
239 kumpf 1.25 if (_localConnection)
240 {
|
241 kumpf 1.11 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
|
242 kumpf 1.25 reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_family =
243 AF_UNIX;
244 strcpy(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path,
245 PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
246 ::unlink(reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
|
247 kumpf 1.6 #else
|
248 kumpf 1.25 PEGASUS_ASSERT(false);
|
249 kumpf 1.11 #endif
|
250 kumpf 1.25 }
251 else
252 {
253 reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_addr.s_addr =
254 INADDR_ANY;
255 reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_family =
256 AF_INET;
257 reinterpret_cast<struct sockaddr_in*>(_rep->address)->sin_port =
258 htons(_portNumber);
259 }
|
260 mike 1.2
|
261 mday 1.7 // Create socket:
|
262 mike 1.2
|
263 kumpf 1.25 if (_localConnection)
264 {
265 _rep->socket = socket(AF_UNIX, SOCK_STREAM, 0);
266 }
267 else
268 {
269 _rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
270 }
|
271 mike 1.2
|
272 mday 1.7 if (_rep->socket < 0)
273 {
274 delete _rep;
275 _rep = 0;
|
276 humberto 1.30 //l10n
277 //throw BindFailedException("Failed to create socket");
278 MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_CREATE_SOCKET",
279 "Failed to create socket");
280 throw BindFailedException(parms);
|
281 mday 1.7 }
282
|
283 mday 1.28
284 // set the close-on-exec bit for this file handle.
285 // any unix that forks needs this bit set.
286 #ifndef PEGASUS_PLATFORM_WIN32_IX86_MSVC
287 int sock_flags;
288 if( (sock_flags = fcntl(_rep->socket, F_GETFD, 0)) < 0)
289 {
290 PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
291 "HTTPAcceptor: fcntl(F_GETFD) failed");
292 }
293 else
294 {
295 sock_flags |= FD_CLOEXEC;
296 if (fcntl(_rep->socket, F_SETFD, sock_flags) < 0)
297 {
298 PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
299 "HTTPAcceptor: fcntl(F_SETFD) failed");
300 }
301 }
302 #endif
303
304 mday 1.28
|
305 mday 1.7 //
306 // Set the socket option SO_REUSEADDR to reuse the socket address so
307 // that we can rebind to a new socket using the same address when we
308 // need to resume the cimom as a result of a timeout during a Shutdown
309 // operation.
310 //
311 int opt=1;
312 if (setsockopt(_rep->socket, SOL_SOCKET, SO_REUSEADDR,
313 (char *)&opt, sizeof(opt)) < 0)
314 {
|
315 mday 1.28 Socket::close(_rep->socket);
|
316 mday 1.7 delete _rep;
317 _rep = 0;
|
318 humberto 1.30 //l10n
319 //throw BindFailedException("Failed to set socket option");
320 MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SET_SOCKET_OPTION",
321 "Failed to set socket option");
322 throw BindFailedException(parms);
|
323 mday 1.7 }
324
325 // Bind socket to port:
326
|
327 kumpf 1.25 if (::bind(_rep->socket, _rep->address, _rep->address_size) < 0)
|
328 mday 1.7 {
329 Socket::close(_rep->socket);
330 delete _rep;
331 _rep = 0;
|
332 humberto 1.30 //l10n
333 //throw BindFailedException("Failed to bind socket");
334 MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
335 "Failed to bind socket");
336 throw BindFailedException(parms);
|
337 mday 1.7 }
338
|
339 kumpf 1.11 // Set up listening on the given socket:
|
340 mday 1.7
341 int const MAX_CONNECTION_QUEUE_LENGTH = 5;
342
343 if (listen(_rep->socket, MAX_CONNECTION_QUEUE_LENGTH) < 0)
344 {
345 Socket::close(_rep->socket);
346 delete _rep;
347 _rep = 0;
|
348 humberto 1.30 //l10n
349 //throw BindFailedException("Failed to bind socket");
350 MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_BIND_SOCKET",
351 "Failed to bind socket");
352 throw BindFailedException(parms);
|
353 mday 1.7 }
354
355 // Register to receive SocketMessages on this socket:
356
|
357 mday 1.21 if ( -1 == ( _entry_index = _monitor->solicitSocketMessages(
|
358 mday 1.7 _rep->socket,
359 SocketMessage::READ | SocketMessage::EXCEPTION,
|
360 mday 1.16 getQueueId(),
|
361 mday 1.21 Monitor::ACCEPTOR)))
|
362 mday 1.7 {
363 Socket::close(_rep->socket);
364 delete _rep;
365 _rep = 0;
|
366 humberto 1.30 //l10n
367 //throw BindFailedException("Failed to solicit socket messaeges");
368 MessageLoaderParms parms("Common.HTTPAcceptor.FAILED_SOLICIT_SOCKET_MESSAGES",
369 "Failed to solicit socket messaeges");
370 throw BindFailedException(parms);
|
371 mday 1.7 }
|
372 mike 1.2 }
373
374 /**
|
375 mday 1.7 closeConnectionSocket - close the server listening socket to disallow
376 new client connections.
|
377 mike 1.2 */
378 void HTTPAcceptor::closeConnectionSocket()
379 {
|
380 mday 1.7 if (_rep)
381 {
382 // unregister the socket
383 _monitor->unsolicitSocketMessages(_rep->socket);
384
385 // close the socket
386 Socket::close(_rep->socket);
387 }
|
388 mike 1.2 }
389
390 /**
|
391 mday 1.7 reopenConnectionSocket - creates a new server socket.
|
392 mike 1.2 */
393 void HTTPAcceptor::reopenConnectionSocket()
394 {
|
395 mday 1.7 if (_rep)
396 {
397 _bind();
398 }
|
399 mike 1.2 }
400
401 /**
|
402 mday 1.7 getOutstandingRequestCount - returns the number of outstanding requests.
|
403 mike 1.2 */
404 Uint32 HTTPAcceptor::getOutstandingRequestCount()
405 {
|
406 mday 1.28 Uint32 count = 0;
407
408 _rep->_connection_mut.lock(pegasus_thread_self());
|
409 mday 1.7 if (_rep->connections.size() > 0)
410 {
411 HTTPConnection* connection = _rep->connections[0];
|
412 mday 1.28 count = connection->getRequestCount();
|
413 mday 1.7 }
|
414 mday 1.28 _rep->_connection_mut.unlock();
415 return count;
|
416 mike 1.2 }
417
418 void HTTPAcceptor::unbind()
419 {
|
420 mday 1.7 if (_rep)
421 {
422 Socket::close(_rep->socket);
|
423 kumpf 1.25
424 if (_localConnection)
425 {
426 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
427 ::unlink(
428 reinterpret_cast<struct sockaddr_un*>(_rep->address)->sun_path);
429 #else
430 PEGASUS_ASSERT(false);
431 #endif
432 }
433
|
434 mday 1.7 delete _rep;
435 _rep = 0;
436 }
|
437 mike 1.2 }
438
439 void HTTPAcceptor::destroyConnections()
440 {
|
441 mday 1.28
442
|
443 mday 1.7 // For each connection created by this object:
|
444 mike 1.2
|
445 mday 1.28 _rep->_connection_mut.lock(pegasus_thread_self());
|
446 mday 1.7 for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
447 {
448 HTTPConnection* connection = _rep->connections[i];
449 Sint32 socket = connection->getSocket();
|
450 mike 1.2
|
451 mday 1.7 // Unsolicit SocketMessages:
|
452 mike 1.2
|
453 mday 1.7 _monitor->unsolicitSocketMessages(socket);
|
454 mike 1.2
|
455 mday 1.7 // Destroy the connection (causing it to close):
|
456 mike 1.2
|
457 kumpf 1.17 while (connection->refcount.value()) { }
|
458 mday 1.7 delete connection;
459 }
|
460 mike 1.2
|
461 mday 1.7 _rep->connections.clear();
|
462 mday 1.28 _rep->_connection_mut.unlock();
|
463 mike 1.2 }
464
465 void HTTPAcceptor::_acceptConnection()
466 {
|
467 mday 1.7 // This function cannot be called on an invalid socket!
|
468 mike 1.2
|
469 mday 1.7 PEGASUS_ASSERT(_rep != 0);
|
470 mike 1.2
|
471 mday 1.7 if (!_rep)
472 return;
|
473 mike 1.2
|
474 mday 1.7 // Accept the connection (populate the address):
|
475 mike 1.2
|
476 kumpf 1.25 struct sockaddr* accept_address;
477 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
478 size_t address_size;
|
479 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))
|
480 kumpf 1.25 socklen_t address_size;
|
481 mike 1.2 #else
|
482 kumpf 1.25 int address_size;
|
483 mike 1.2 #endif
484
|
485 kumpf 1.25 if (_localConnection)
486 {
487 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
488 accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_un);
489 address_size = sizeof(struct sockaddr_un);
|
490 mike 1.2 #else
|
491 kumpf 1.25 PEGASUS_ASSERT(false);
|
492 mike 1.2 #endif
|
493 kumpf 1.25 }
494 else
495 {
496 accept_address = reinterpret_cast<struct sockaddr*>(new struct sockaddr_in);
497 address_size = sizeof(struct sockaddr_in);
498 }
499
500 Sint32 socket = accept(_rep->socket, accept_address, &address_size);
501
502 delete accept_address;
|
503 mike 1.2
|
504 mday 1.7 if (socket < 0)
505 {
|
506 david 1.27 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
507 "HTTPAcceptor - accept() failure. errno: $0"
508 ,errno);
509
|
510 kumpf 1.19 PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
511 "HTTPAcceptor: accept() failed");
|
512 mday 1.7 return;
513 }
|
514 david 1.27
|
515 mday 1.28 // set the close on exec flag
516 #ifndef PEGASUS_PLATFORM_WIN32_IX86_MSVC
517 int sock_flags;
518 if( (sock_flags = fcntl(socket, F_GETFD, 0)) < 0)
519 {
520 PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
521 "HTTPAcceptor: fcntl(F_GETFD) failed");
522 }
523 else
524 {
525 sock_flags |= FD_CLOEXEC;
526 if (fcntl(socket, F_SETFD, sock_flags) < 0)
527 {
528 PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
529 "HTTPAcceptor: fcntl(F_SETFD) failed");
530 }
531 }
532 #endif
533
534
|
535 david 1.27 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
536 "HTTPAcceptor - accept() success. Socket: $1"
537 ,socket);
|
538 mike 1.2
|
539 mday 1.7 // Create a new conection and add it to the connection list:
|
540 mike 1.2
|
541 mday 1.7 MP_Socket * mp_socket = new MP_Socket(socket, _sslcontext);
|
542 kumpf 1.19 if (mp_socket->accept() < 0)
543 {
544 PEG_TRACE_STRING(TRC_HTTP, Tracer::LEVEL2,
545 "HTTPAcceptor: SSL_accept() failed");
|
546 mday 1.7 return;
547 }
|
548 mike 1.2
|
549 mday 1.7 HTTPConnection* connection = new HTTPConnection(
|
550 mday 1.16 _monitor, mp_socket, this, static_cast<MessageQueue *>(_outputMessageQueue));
|
551 mike 1.2
|
552 mday 1.7 // Solicit events on this new connection's socket:
|
553 mday 1.21 int index;
554
|
555 mday 1.22 if (-1 == (index = _monitor->solicitSocketMessages(
|
556 mday 1.7 socket,
557 SocketMessage::READ | SocketMessage::EXCEPTION,
|
558 mday 1.21 connection->getQueueId(), Monitor::CONNECTION)) )
|
559 mday 1.7 {
560 delete connection;
561 Socket::close(socket);
562 }
|
563 mike 1.2
|
564 mday 1.7 // Save the socket for cleanup later:
|
565 mday 1.21 connection->_entry_index = index;
|
566 mday 1.28 _rep->_connection_mut.lock(pegasus_thread_self());
|
567 mday 1.7 _rep->connections.append(connection);
|
568 mday 1.28 _rep->_connection_mut.unlock();
|
569 mike 1.2 }
|
570 mday 1.32
571 AsyncDQueue<pegasus_acceptor> pegasus_acceptor::acceptors(true, 0);
572
573 pegasus_acceptor::pegasus_acceptor(monitor_2* monitor,
574 MessageQueue* outputMessageQueue,
575 Boolean localConnection,
576 Uint32 portNumber,
577 SSLContext* sslcontext)
578 : _monitor(monitor), _outputMessageQueue(outputMessageQueue),
579 _localConnection(localConnection), _portNumber(portNumber),
580 _sslcontext(sslcontext), connections(true, 0)
581 {
582
583 Socket::initializeInterface();
584 try {
585 acceptors.insert_first(this);
586 }
587 catch(...){
588 }
589
590 }
591 mday 1.32
592 pegasus_acceptor::~pegasus_acceptor(void)
593 {
594 unbind();
595 Socket::uninitializeInterface();
596 try {
597 acceptors.remove(this);
598 }
599 catch(...){
600 }
601
602 }
603
604
605 void pegasus_acceptor::bind()
606 {
607
608 PEGASUS_SOCKLEN_SIZE addr_size;
609 struct sockaddr *addr;
610 struct sockaddr_in addr_in;
611 # ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
612 mday 1.32 struct sockaddr_un addr_un;
613 #endif
614
615 memset(&addr_in, 0, sizeof(addr_in));
616 addr_in.sin_addr.s_addr = INADDR_ANY;
617 addr_in.sin_family = AF_INET;
618 addr_in.sin_port = htons(_portNumber);
619 addr = (struct sockaddr*) &addr_in;
620 addr_size = sizeof(addr_in);
621
622 // first step: determine which kind of socket factory to initialize,
623 // then create the socket and bind it to an address
624 if(_localConnection == true){
625 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET
626 unix_socket_factory sf;
627 pegasus_socket temp(&sf);
628 _listener = temp;
629
630 memset(&addr_un, 0, sizeof(addr_un));
631 addr.sun_family = AF_UNIX;
632 strcpy(addr.sun_path, PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
633 mday 1.32 addr = (struct sockaddr*) &addr_un;
634 addr_size = sizeof(addr_un);
635 _listener.socket(AF_UNIX, SOCK_STREAM, 0);
636 #else
637 bsd_socket_factory sf;
638 pegasus_socket temp(&sf);
639 _listener = temp;
640 _listener.socket(AF_UNIX, SOCK_STREAM, 0);
641 #endif
642 }
643 else if( _sslcontext != 0 ) {
644 #ifdef PEGASUS_HAS_SSL
645 ssl_socket_factory sf;
646 #else
647 bsd_socket_factory sf;
648 #endif
649 pegasus_socket temp(&sf);
650 _listener = temp;
651 _listener.socket(PF_INET, SOCK_STREAM, 0);
652 }
653 else {
654 mday 1.32 bsd_socket_factory sf;
655 pegasus_socket temp(&sf);
656 _listener = temp;
657 _listener.socket(PF_INET, SOCK_STREAM, 0);
658 }
659
660 _listener.bind((struct sockaddr*)addr, addr_size);
661
662 // second step: listen on the socket
663
664 _listener.listen(5);
665
666 // third step: add this listening socket to the monitor
667
668 _monitor->tickle();
669 _monitor->add_entry(_listener, LISTEN, this, this);
670 }
671
672
673 /** Unbind from the given port.
674 */
675 mday 1.32 void pegasus_acceptor::unbind()
676 {
677 // remove the socket from the monitor
678 _monitor->remove_entry((Sint32)_listener);
679
680 // close the socket
681 _listener.close();
682 }
683
684
685 /** Close the connection socket.
686 */
687 void pegasus_acceptor::closeConnectionSocket()
688 {
689 unbind();
690 }
691
692
693 /** Reopen the connection socket.
694 */
695 void pegasus_acceptor::reopenConnectionSocket()
696 mday 1.32 {
697 bind();
698 }
699
700
701 /** Returns the number of outstanding requests
702 */
703 Uint32 pegasus_acceptor::getOutstandingRequestCount()
704 {
705 return _monitor->getOutstandingRequestCount();
706 }
707
708 Boolean pegasus_acceptor::operator ==(const pegasus_acceptor& pa)
709 {
710 if(this == &pa)
711 return true;
712 return false;
713 }
714
715 Boolean pegasus_acceptor::operator ==(void* pa)
716 {
717 mday 1.32 if((void*)this == pa)
718 return true;
719 return false;
720 }
721
722
723 pegasus_acceptor* pegasus_acceptor::find_acceptor(Boolean local, Uint32 port)
724 {
725 pegasus_acceptor* temp = 0;
726
727 try {
728 acceptors.try_lock(pegasus_thread_self());
729 temp = acceptors.next(temp);
730 while(temp){
731 if( local == true ){
732 if(temp->_localConnection){
733 acceptors.unlock();
734 return temp;
735 }
736 }
737 if(temp->_localConnection == local && temp->_portNumber ==port){
738 mday 1.32 acceptors.unlock();
739 return temp;
740 }
741 temp = acceptors.next(temp);
742 }
743 acceptors.unlock();
744 }
745 catch(...){
746 }
747 return temp;
748 }
749
750 class m2e_rep;
751
752 void pegasus_acceptor::accept_dispatch(monitor_2_entry *entry)
753 {
754 pegasus_acceptor* myself = (pegasus_acceptor*)entry->get_accept();
755
756 HTTPConnection2* connection = new HTTPConnection2(entry->_rep->psock, myself->_outputMessageQueue);
757
758 // set the entry's dispatch parameter to point to the connection object
759 mday 1.32 entry->set_dispatch ((void*)connection);
760
761 try {
762 myself->connections.insert_first(connection);
763 }
764 catch(...){
765 }
766 }
767
|
768 mike 1.2
769 PEGASUS_NAMESPACE_END
|