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
|