(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               //
 28               //%/////////////////////////////////////////////////////////////////////////////
 29               
 30               #include <iostream>
 31               #include "Config.h"
 32               #include "Socket.h"
 33               
 34               #ifdef PEGASUS_OS_TYPE_WINDOWS
 35               # include <winsock.h>
 36               #else
 37               # include <cctype>
 38               # include <unistd.h>
 39               # include <cstdlib>
 40               # include <errno.h>
 41               # include <fcntl.h>
 42               # include <netdb.h>
 43 mike  1.1.2.1 # include <netinet/in.h>
 44               # include <arpa/inet.h>
 45               # include <sys/socket.h>
 46               #endif
 47               
 48               #include "Socket.h"
 49               #include "HTTPAcceptor.h"
 50               #include "HTTPConnection.h"
 51               
 52               PEGASUS_USING_STD;
 53               
 54               PEGASUS_NAMESPACE_BEGIN
 55               
 56               ////////////////////////////////////////////////////////////////////////////////
 57               //
 58               // HTTPAcceptorRep
 59               //
 60               ////////////////////////////////////////////////////////////////////////////////
 61               
 62               struct HTTPAcceptorRep
 63               {
 64 mike  1.1.2.1     struct sockaddr_in address;
 65                   Sint32 socket;
 66                   Array<HTTPConnection*> connections;
 67               };
 68               
 69               ////////////////////////////////////////////////////////////////////////////////
 70               //
 71               // HTTPAcceptor
 72               //
 73               ////////////////////////////////////////////////////////////////////////////////
 74               
 75 mike  1.1.2.4 HTTPAcceptor::HTTPAcceptor(Monitor* monitor, MessageQueue* outputMessageQueue)
 76                   : _monitor(monitor), _outputMessageQueue(outputMessageQueue), _rep(0)
 77 mike  1.1.2.1 {
 78 mike  1.1.2.6     Socket::initializeInterface();
 79 mike  1.1.2.1 }
 80               
 81               HTTPAcceptor::~HTTPAcceptor()
 82               {
 83                   unbind();
 84 mike  1.1.2.6     Socket::uninitializeInterface();
 85 mike  1.1.2.1 }
 86               
 87               void HTTPAcceptor::handleEnqueue()
 88               {
 89 mike  1.1.2.5     // cout << "HTTPAcceptor::handleEnqueue()" << endl;
 90 mike  1.1.2.1 
 91                   Message* message = dequeue();
 92               
 93                   if (!message)
 94                       return;
 95               
 96                   switch (message->getType())
 97                   {
 98               	case SOCKET_MESSAGE:
 99               	{
100               	    SocketMessage* socketMessage = (SocketMessage*)message;
101               
102               	    // If this is a connection request:
103               
104               	    if (socketMessage->socket == _rep->socket &&
105               		socketMessage->events | SocketMessage::READ)
106               	    {
107               		_acceptConnection();
108               	    }
109               	    else
110               	    {
111 mike  1.1.2.1 		// ATTN! this can't happen!
112               	    }
113               
114               	    break;
115               	}
116               
117               	case CLOSE_CONNECTION_MESSAGE:
118               	{
119               	    CloseConnectionMessage* closeConnectionMessage 
120               		= (CloseConnectionMessage*)message;
121               
122               	    for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
123               	    {
124               		HTTPConnection* connection = _rep->connections[i];	
125               		Sint32 socket = connection->getSocket();
126               
127               		if (socket == closeConnectionMessage->socket)
128               		{
129               		    _monitor->unsolicitSocketMessages(socket);
130               		    _rep->connections.remove(i);
131               		    delete connection;
132 mike  1.1.2.1 		    break;
133               		}
134               	    }
135               	}
136               
137               	default:
138               	    // ATTN: need unexpected message error!
139               	    break;
140                   };
141               
142                   delete message;
143 mike  1.1.2.7 }
144               
145               const char* HTTPAcceptor::getQueueName() const
146               {
147                   return "HTTPAcceptor";
148 mike  1.1.2.1 }
149               
150               void HTTPAcceptor::bind(Uint32 portNumber)
151               {
152                   if (_rep)
153               	throw BindFailed("HTTPAcceptor already bound");
154               
155                   _rep = new HTTPAcceptorRep;
156               
157                   // Create address:
158               
159                   memset(&_rep->address, 0, sizeof(_rep->address));
160                   _rep->address.sin_addr.s_addr = INADDR_ANY;
161                   _rep->address.sin_family = AF_INET;
162                   _rep->address.sin_port = htons(portNumber);
163               
164                   // Create socket:
165                   
166                   _rep->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
167               
168                   if (_rep->socket < 0)
169 mike  1.1.2.1     {
170               	delete _rep;
171               	_rep = 0;
172               	throw BindFailed("Failed to create socket");
173                   }
174               
175                   // Bind socket to port:
176               
177                   if (::bind(_rep->socket, 
178               	(struct sockaddr*)(void*)&_rep->address, 
179               	sizeof(_rep->address)) < 0)
180                   {
181               	Socket::close(_rep->socket);
182               	delete _rep;
183               	_rep = 0;
184               	throw BindFailed("Failed to bind socket to port");
185                   }
186               
187                   // Set up listening on the given port:
188               
189                   int const MAX_CONNECTION_QUEUE_LENGTH = 5;
190 mike  1.1.2.1 
191                   if (listen(_rep->socket, MAX_CONNECTION_QUEUE_LENGTH) < 0)
192                   {
193               	Socket::close(_rep->socket);
194               	delete _rep;
195               	_rep = 0;
196               	throw BindFailed("Failed to bind socket to port");
197                   }
198               
199                   // Register to receive SocketMessages on this socket:
200               
201                   if (!_monitor->solicitSocketMessages(
202               	_rep->socket,
203               	SocketMessage::READ | SocketMessage::EXCEPTION,
204               	getQueueId()))
205                   {
206               	Socket::close(_rep->socket);
207               	delete _rep;
208               	_rep = 0;
209               	throw BindFailed("Failed to solicit socket messaeges");
210                   }
211 mike  1.1.2.1 }
212               
213               void HTTPAcceptor::unbind()
214               {
215                   if (_rep)
216                   {
217               	Socket::close(_rep->socket);
218               	delete _rep;
219               	_rep = 0;
220                   }
221               }
222               
223               void HTTPAcceptor::destroyConnections()
224               {
225                   // For each connection created by this object:
226               
227                   for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
228                   {
229               	HTTPConnection* connection = _rep->connections[i];	
230               	Sint32 socket = connection->getSocket();
231               
232 mike  1.1.2.1 	// Unsolicit SocketMessages:
233               
234               	_monitor->unsolicitSocketMessages(socket);
235               
236               	// Destroy the connection (causing it to close):
237               
238               	delete connection;
239                   }
240               
241                   _rep->connections.clear();
242               }
243               
244               void HTTPAcceptor::_acceptConnection()
245               {
246                   // This function cannot be called on an invalid socket!
247               
248                   PEGASUS_ASSERT(_rep != 0);
249               
250                   if (!_rep)
251               	return;
252               
253 mike  1.1.2.1     // Accept the connection (populate the address):
254               
255                   sockaddr_in address;
256                   int n = sizeof(address);
257 mday  1.1.2.2 #if defined(PEGASUS_PLATFORM_LINUX_IX86_GNU)    
258 mike  1.1.2.3     Sint32 socket = accept(
259               	_rep->socket, (struct sockaddr*)&address, (socklen_t *)&n);
260 mday  1.1.2.2 #else
261 mike  1.1.2.1     Sint32 socket = accept(_rep->socket, (struct sockaddr*)&address, &n);
262 mday  1.1.2.2 #endif
263 mike  1.1.2.1 
264                   if (socket < 0)
265                   {
266               	if (getenv("PEGASUS_TRACE"))
267               	    cerr <<"HTTPAcceptor: accept() failed" << endl;
268               
269               	return;
270                   }
271               
272                   // Create a new conection and add it to the connection list:
273               
274 mike  1.1.2.4     HTTPConnection* connection = new HTTPConnection(
275 mike  1.1.2.5 	_monitor, socket, this, _outputMessageQueue);
276 mike  1.1.2.1 
277 mike  1.1.2.6     // Solicit events on this new connection's socket:
278 mike  1.1.2.1 
279                   if (!_monitor->solicitSocketMessages(
280               	socket,
281               	SocketMessage::READ | SocketMessage::EXCEPTION,
282               	connection->getQueueId()))
283                   {
284               	delete connection;
285               	Socket::close(socket);
286                   }
287               
288                   // Save the socket for cleanup later:
289               
290                   _rep->connections.append(connection);
291               }
292               
293               PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2