(file) Return to HTTPAcceptor.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

  1 mike  1.1.2.1 //%/////////////////////////////////////////////////////////////////////////////
  2               //
  3               // Copyright (c) 2000, 2001 BMC Software, Hewlett-Packard Company, IBM, 
  4               // The Open Group, Tivoli Systems
  5               //
  6               // Permission is hereby granted, free of charge, to any person obtaining a copy
  7               // 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               // 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               // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN 
 14               // 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               // 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               // 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 mike  1.1.2.1 //==============================================================================
 23               //
 24               // Author: Mike Brasher (mbrasher@bmc.com)
 25               //
 26               // Modified By:
 27 kumpf 1.1.2.9 //         Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com)
 28 mike  1.1.2.1 //
 29               //%/////////////////////////////////////////////////////////////////////////////
 30               
 31               #include "Config.h"
 32 sage  1.1.2.10 #include <iostream>
 33 mike  1.1.2.1  #include "Socket.h"
 34                
 35                #ifdef PEGASUS_OS_TYPE_WINDOWS
 36                # include <winsock.h>
 37                #else
 38                # include <cctype>
 39                # include <unistd.h>
 40                # include <cstdlib>
 41                # include <errno.h>
 42                # include <fcntl.h>
 43                # include <netdb.h>
 44                # include <netinet/in.h>
 45                # include <arpa/inet.h>
 46                # include <sys/socket.h>
 47                #endif
 48                
 49                #include "Socket.h"
 50 sage  1.1.2.10 #include "TLS.h"
 51 mike  1.1.2.1  #include "HTTPAcceptor.h"
 52                #include "HTTPConnection.h"
 53                
 54                PEGASUS_USING_STD;
 55                
 56                PEGASUS_NAMESPACE_BEGIN
 57                
 58                ////////////////////////////////////////////////////////////////////////////////
 59                //
 60                // HTTPAcceptorRep
 61                //
 62                ////////////////////////////////////////////////////////////////////////////////
 63                
 64                struct HTTPAcceptorRep
 65                {
 66                    struct sockaddr_in address;
 67                    Sint32 socket;
 68                    Array<HTTPConnection*> connections;
 69                };
 70                
 71                ////////////////////////////////////////////////////////////////////////////////
 72 mike  1.1.2.1  //
 73                // HTTPAcceptor
 74                //
 75                ////////////////////////////////////////////////////////////////////////////////
 76                
 77 mike  1.1.2.4  HTTPAcceptor::HTTPAcceptor(Monitor* monitor, MessageQueue* outputMessageQueue)
 78 sage  1.1.2.10     : _monitor(monitor), _outputMessageQueue(outputMessageQueue), _rep(0),
 79                      _sslcontext(NULL)
 80                {
 81                    Socket::initializeInterface();
 82                }
 83                
 84                HTTPAcceptor::HTTPAcceptor(Monitor* monitor, MessageQueue* outputMessageQueue,
 85                                           SSLContext * sslcontext)
 86                    : _monitor(monitor), _outputMessageQueue(outputMessageQueue), _rep(0),
 87                      _sslcontext(sslcontext)
 88 mike  1.1.2.1  {
 89 mike  1.1.2.6      Socket::initializeInterface();
 90 mike  1.1.2.1  }
 91                
 92                HTTPAcceptor::~HTTPAcceptor()
 93                {
 94                    unbind();
 95 mike  1.1.2.6      Socket::uninitializeInterface();
 96 mike  1.1.2.1  }
 97                
 98                void HTTPAcceptor::handleEnqueue()
 99                {
100                    Message* message = dequeue();
101                
102                    if (!message)
103                        return;
104                
105                    switch (message->getType())
106                    {
107                	case SOCKET_MESSAGE:
108                	{
109                	    SocketMessage* socketMessage = (SocketMessage*)message;
110                
111                	    // If this is a connection request:
112                
113                	    if (socketMessage->socket == _rep->socket &&
114                		socketMessage->events | SocketMessage::READ)
115                	    {
116                		_acceptConnection();
117 mike  1.1.2.1  	    }
118                	    else
119                	    {
120                		// ATTN! this can't happen!
121                	    }
122                
123                	    break;
124                	}
125                
126                	case CLOSE_CONNECTION_MESSAGE:
127                	{
128                	    CloseConnectionMessage* closeConnectionMessage 
129                		= (CloseConnectionMessage*)message;
130                
131                	    for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
132                	    {
133                		HTTPConnection* connection = _rep->connections[i];	
134                		Sint32 socket = connection->getSocket();
135                
136                		if (socket == closeConnectionMessage->socket)
137                		{
138 mike  1.1.2.1  		    _monitor->unsolicitSocketMessages(socket);
139                		    _rep->connections.remove(i);
140                		    delete connection;
141                		    break;
142                		}
143                	    }
144                	}
145                
146                	default:
147                	    // ATTN: need unexpected message error!
148                	    break;
149                    };
150                
151                    delete message;
152 mike  1.1.2.7  }
153                
154                const char* HTTPAcceptor::getQueueName() const
155                {
156                    return "HTTPAcceptor";
157 mike  1.1.2.1  }
158                
159                void HTTPAcceptor::bind(Uint32 portNumber)
160                {
161                    if (_rep)
162                	throw BindFailed("HTTPAcceptor already bound");
163                
164                    _rep = new HTTPAcceptorRep;
165                
166 kumpf 1.1.2.9      _portNumber = portNumber;
167                
168                    // bind address
169                    _bind();
170                
171                    return;
172                }
173                
174                /**
175                 _bind - creates a new server socket and bind socket to the port address.
176                */
177                void HTTPAcceptor::_bind()
178                {
179                
180 mike  1.1.2.1      // Create address:
181                
182                    memset(&_rep->address, 0, sizeof(_rep->address));
183                    _rep->address.sin_addr.s_addr = INADDR_ANY;
184                    _rep->address.sin_family = AF_INET;
185 kumpf 1.1.2.9      _rep->address.sin_port = htons(_portNumber);
186 mike  1.1.2.1  
187                    // Create socket:
188                    
189                    _rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
190                
191                    if (_rep->socket < 0)
192                    {
193                	delete _rep;
194                	_rep = 0;
195                	throw BindFailed("Failed to create socket");
196                    }
197                
198 kumpf 1.1.2.9      //
199                    // Set the socket option SO_REUSEADDR to reuse the socket address so
200                    // that we can rebind to a new socket using the same address when we
201                    // need to resume the cimom as a result of a timeout during a Shutdown
202                    // operation.
203                    //
204                    int opt=1;
205                    if (setsockopt(_rep->socket, SOL_SOCKET, SO_REUSEADDR,
206                                 (char *)&opt, sizeof(opt)) < 0)
207                    {
208                        delete _rep;
209                        _rep = 0;
210                        throw BindFailed("Failed to set socket option");
211                    }
212                
213 mike  1.1.2.1      // Bind socket to port:
214                
215                    if (::bind(_rep->socket, 
216                	(struct sockaddr*)(void*)&_rep->address, 
217                	sizeof(_rep->address)) < 0)
218                    {
219                	Socket::close(_rep->socket);
220                	delete _rep;
221                	_rep = 0;
222                	throw BindFailed("Failed to bind socket to port");
223                    }
224                
225                    // Set up listening on the given port:
226                
227                    int const MAX_CONNECTION_QUEUE_LENGTH = 5;
228                
229                    if (listen(_rep->socket, MAX_CONNECTION_QUEUE_LENGTH) < 0)
230                    {
231                	Socket::close(_rep->socket);
232                	delete _rep;
233                	_rep = 0;
234 mike  1.1.2.1  	throw BindFailed("Failed to bind socket to port");
235                    }
236                
237                    // Register to receive SocketMessages on this socket:
238                
239                    if (!_monitor->solicitSocketMessages(
240                	_rep->socket,
241                	SocketMessage::READ | SocketMessage::EXCEPTION,
242                	getQueueId()))
243                    {
244                	Socket::close(_rep->socket);
245                	delete _rep;
246                	_rep = 0;
247                	throw BindFailed("Failed to solicit socket messaeges");
248 kumpf 1.1.2.9      }
249                }
250                
251                /**
252                 closeConnectionSocket - close the server listening socket to disallow
253                 new client connections.
254                */
255                void HTTPAcceptor::closeConnectionSocket()
256                {
257                    if (_rep)
258                    {
259                        // unregister the socket
260                        _monitor->unsolicitSocketMessages(_rep->socket);
261                
262                        // close the socket
263                        Socket::close(_rep->socket);
264                    }
265                }
266                
267                /**
268                 reopenConnectionSocket - creates a new server socket.
269 kumpf 1.1.2.9  */
270                void HTTPAcceptor::reopenConnectionSocket()
271                {
272                    if (_rep)
273                    {
274                        _bind();
275 mike  1.1.2.1      }
276                }
277                
278                void HTTPAcceptor::unbind()
279                {
280                    if (_rep)
281                    {
282                	Socket::close(_rep->socket);
283                	delete _rep;
284                	_rep = 0;
285                    }
286                }
287                
288                void HTTPAcceptor::destroyConnections()
289                {
290                    // For each connection created by this object:
291                
292                    for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
293                    {
294                	HTTPConnection* connection = _rep->connections[i];	
295                	Sint32 socket = connection->getSocket();
296 mike  1.1.2.1  
297                	// Unsolicit SocketMessages:
298                
299                	_monitor->unsolicitSocketMessages(socket);
300                
301                	// Destroy the connection (causing it to close):
302                
303                	delete connection;
304                    }
305                
306                    _rep->connections.clear();
307                }
308                
309                void HTTPAcceptor::_acceptConnection()
310                {
311                    // This function cannot be called on an invalid socket!
312                
313                    PEGASUS_ASSERT(_rep != 0);
314                
315                    if (!_rep)
316                	return;
317 mike  1.1.2.1  
318                    // Accept the connection (populate the address):
319                
320                    sockaddr_in address;
321 sage  1.1.2.8  
322                #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
323                    size_t n = sizeof(address);
324                #else
325 mike  1.1.2.1      int n = sizeof(address);
326 sage  1.1.2.8  #endif
327                
328 mday  1.1.2.2  #if defined(PEGASUS_PLATFORM_LINUX_IX86_GNU)    
329 mike  1.1.2.3      Sint32 socket = accept(
330                	_rep->socket, (struct sockaddr*)&address, (socklen_t *)&n);
331 mday  1.1.2.2  #else
332 mike  1.1.2.1      Sint32 socket = accept(_rep->socket, (struct sockaddr*)&address, &n);
333 mday  1.1.2.2  #endif
334 mike  1.1.2.1  
335                    if (socket < 0)
336                    {
337                	if (getenv("PEGASUS_TRACE"))
338                	    cerr <<"HTTPAcceptor: accept() failed" << endl;
339                
340                	return;
341                    }
342                
343                    // Create a new conection and add it to the connection list:
344                
345 sage  1.1.2.10     MP_Socket * mp_socket = new MP_Socket(socket, _sslcontext);
346                    if (mp_socket->accept() < 0) {
347                	if (getenv("PEGASUS_TRACE"))
348                	    cerr <<"HTTPAcceptor: SSL_accept() failed" << endl;
349                
350                	return;
351                    }
352                
353 mike  1.1.2.4      HTTPConnection* connection = new HTTPConnection(
354 sage  1.1.2.10 	_monitor, mp_socket, this, _outputMessageQueue);
355 mike  1.1.2.1  
356 mike  1.1.2.6      // Solicit events on this new connection's socket:
357 mike  1.1.2.1  
358                    if (!_monitor->solicitSocketMessages(
359                	socket,
360                	SocketMessage::READ | SocketMessage::EXCEPTION,
361                	connection->getQueueId()))
362                    {
363                	delete connection;
364                	Socket::close(socket);
365                    }
366                
367                    // Save the socket for cleanup later:
368                
369                    _rep->connections.append(connection);
370                }
371                
372                PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2