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

  1 karl  1.63 //%2006////////////////////////////////////////////////////////////////////////
  2 mike  1.2  //
  3 karl  1.50 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
  4            // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
  5            // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
  6 karl  1.43 // IBM Corp.; EMC Corporation, The Open Group.
  7 karl  1.50 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  8            // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
  9 karl  1.53 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 10            // EMC Corporation; VERITAS Software Corporation; The Open Group.
 11 karl  1.63 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 12            // EMC Corporation; Symantec Corporation; The Open Group.
 13 mike  1.2  //
 14            // Permission is hereby granted, free of charge, to any person obtaining a copy
 15 kumpf 1.16 // of this software and associated documentation files (the "Software"), to
 16            // deal in the Software without restriction, including without limitation the
 17            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 18 mike  1.2  // sell copies of the Software, and to permit persons to whom the Software is
 19            // furnished to do so, subject to the following conditions:
 20            // 
 21 kumpf 1.16 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 22 mike  1.2  // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 23            // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 24 kumpf 1.16 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 25            // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 26            // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 27 mike  1.2  // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 28            // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 29            //
 30            //==============================================================================
 31            //
 32            //%/////////////////////////////////////////////////////////////////////////////
 33            
 34 mike  1.67 #include "Network.h"
 35 mike  1.2  #include "Config.h"
 36            #include <iostream>
 37 kumpf 1.12 #include "Constants.h"
 38 mike  1.2  #include "Socket.h"
 39 kumpf 1.73 #include <Pegasus/Common/MessageLoader.h>
 40 mike  1.2  #include "Socket.h"
 41            #include "TLS.h"
 42            #include "HTTPConnector.h"
 43            #include "HTTPConnection.h"
 44            
 45 david 1.38 #ifdef PEGASUS_OS_OS400
 46 kumpf 1.72 # include "EBCDIC_OS400.h"
 47 david 1.38 #endif
 48            
 49 marek 1.44 #ifdef PEGASUS_OS_ZOS
 50 kumpf 1.72 # include <resolv.h>  // MAXHOSTNAMELEN
 51 marek 1.44 #endif
 52            
 53 mike  1.2  PEGASUS_USING_STD;
 54            
 55            PEGASUS_NAMESPACE_BEGIN
 56            
 57 a.arora 1.46 class bsd_socket_rep;
 58              
 59 mike    1.2  ////////////////////////////////////////////////////////////////////////////////
 60              //
 61              // Local routines:
 62              //
 63              ////////////////////////////////////////////////////////////////////////////////
 64              
 65              static Boolean _MakeAddress(
 66 kumpf   1.72     const char* hostname,
 67                  int port,
 68                  sockaddr_in& address)
 69 mike    1.2  {
 70 kumpf   1.72     if (!hostname)
 71                      return false;
 72 david   1.38 
 73              #ifdef PEGASUS_OS_OS400
 74                  char ebcdicHost[256];
 75                  if (strlen(hostname) < 256)
 76 h.sterling 1.55     strcpy(ebcdicHost, hostname);
 77 david      1.38     else
 78 h.sterling 1.55     return false;
 79 david      1.38     AtoE(ebcdicHost);
 80                 #endif
 81 kumpf      1.72 
 82 dave.sudlik 1.49 ////////////////////////////////////////////////////////////////////////////////
 83                  // This code used to check if the first character of "hostname" was alphabetic
 84 kumpf       1.72 // to indicate hostname instead of IP address. But RFC 1123, section 2.1,
 85                  // relaxed this requirement to alphabetic character *or* digit. So bug 1462
 86                  // changed the flow here to call inet_addr first to check for a valid IP
 87                  // address in dotted decimal notation. If it's not a valid IP address, then
 88                  // try to validate it as a hostname.
 89                  // RFC 1123 states: The host SHOULD check the string syntactically for a
 90                  // dotted-decimal number before looking it up in the Domain Name System.
 91 dave.sudlik 1.49 // Hence the call to inet_addr() first.
 92                  ////////////////////////////////////////////////////////////////////////////////
 93                  
 94                  #ifdef PEGASUS_OS_OS400
 95 kumpf       1.72     unsigned long tmp_addr = inet_addr(ebcdicHost);
 96 dave.sudlik 1.49 #else
 97 kumpf       1.72     unsigned long tmp_addr = inet_addr((char *)hostname);
 98 kumpf       1.62 #endif
 99 dave.sudlik 1.49 
100 kumpf       1.72     struct hostent* hostEntry;
101 dave.sudlik 1.49 
102                  // Note: 0xFFFFFFFF is actually a valid IP address (255.255.255.255).
103                  //       A better solution would be to use inet_aton() or equivalent, as
104                  //       inet_addr() is now considered "obsolete".
105                  
106 kumpf       1.72     if (tmp_addr == 0xFFFFFFFF)  // if hostname is not an IP address
107                      {
108 kumpf       1.62 #if defined(PEGASUS_OS_LINUX)
109 kumpf       1.72         char hostEntryBuffer[8192];
110                          struct hostent hostEntryStruct;
111                          int hostEntryErrno;
112                  
113                          gethostbyname_r(
114                              hostname,
115                              &hostEntryStruct,
116                              hostEntryBuffer,
117                              sizeof(hostEntryBuffer),
118                              &hostEntry,
119                              &hostEntryErrno);
120 kumpf       1.62 #elif defined(PEGASUS_OS_SOLARIS)
121 kumpf       1.72         char hostEntryBuffer[8192];
122                          struct hostent hostEntryStruct;
123                          int hostEntryErrno;
124                  
125                          hostEntry = gethostbyname_r(
126                              (char *)hostname,
127                              &hostEntryStruct,
128                              hostEntryBuffer,
129                              sizeof(hostEntryBuffer),
130                              &hostEntryErrno);
131 david       1.38 #elif defined(PEGASUS_OS_OS400)
132 kumpf       1.72         hostEntry = gethostbyname(ebcdicHost);
133 marek       1.44 #elif defined(PEGASUS_OS_ZOS)
134 kumpf       1.72         if (String::equalNoCase("localhost",String(hostname)))
135                          {
136                              char hostName[PEGASUS_MAXHOSTNAMELEN + 1];
137                              gethostname( hostName, sizeof( hostName ) );
138                              hostName[sizeof(hostName)-1] = 0;
139                              hostEntry = gethostbyname(hostName);
140                          }
141                          else
142                          {
143                              hostEntry = gethostbyname((char *)hostname);
144                          }
145 keith.petley 1.36 #else
146 kumpf        1.72         hostEntry = gethostbyname((char *)hostname);
147 keith.petley 1.36 #endif
148 kumpf        1.72         if (!hostEntry)
149                           {
150                               return false;
151                           }
152 mike         1.2  
153 kumpf        1.72         memset(&address, 0, sizeof(address));
154                           memcpy(&address.sin_addr, hostEntry->h_addr, hostEntry->h_length);
155                           address.sin_family = hostEntry->h_addrtype;
156                           address.sin_port = htons(port);
157                       }
158                       else    // else hostname *is* a dotted-decimal IP address
159                       {
160                           memset(&address, 0, sizeof(address));
161                           address.sin_family = AF_INET;
162                           address.sin_addr.s_addr = tmp_addr;
163                           address.sin_port = htons(port);
164                       }
165                   
166                       return true;
167 mike         1.2  }
168                   
169                   ////////////////////////////////////////////////////////////////////////////////
170                   //
171                   // HTTPConnectorRep
172                   //
173                   ////////////////////////////////////////////////////////////////////////////////
174                   
175                   struct HTTPConnectorRep
176                   {
177 kumpf        1.72     Array<HTTPConnection*> connections;
178 mike         1.2  };
179                   
180                   ////////////////////////////////////////////////////////////////////////////////
181                   //
182                   // HTTPConnector
183                   //
184                   ////////////////////////////////////////////////////////////////////////////////
185                   
186                   HTTPConnector::HTTPConnector(Monitor* monitor)
187 kumpf        1.72     : Base(PEGASUS_QUEUENAME_HTTPCONNECTOR),
188                         _monitor(monitor), _entry_index(-1)
189 mike         1.2  {
190 kumpf        1.72     _rep = new HTTPConnectorRep;
191                       Socket::initializeInterface();
192 mike         1.2  }
193                   
194                   HTTPConnector::~HTTPConnector()
195                   {
196 thilo.boehm  1.74     PEG_METHOD_ENTER(TRC_HTTP, "HTTPConnector::~HTTPConnector()");
197 kumpf        1.72     delete _rep;
198                       Socket::uninitializeInterface();
199 thilo.boehm  1.74     PEG_METHOD_EXIT();
200 mike         1.2  }
201                   
202 mday         1.4  void HTTPConnector::handleEnqueue(Message *message)
203 mike         1.2  {
204 kumpf        1.72     if (!message)
205                           return;
206 mike         1.2  
207 kumpf        1.72     switch (message->getType())
208                       {
209                           // It might be useful to catch socket messages later to implement
210                           // asynchronous establishment of connections.
211 mike         1.2  
212 kumpf        1.72         case SOCKET_MESSAGE:
213                               break;
214 h.sterling   1.55 
215 kumpf        1.72         case CLOSE_CONNECTION_MESSAGE:
216 h.sterling   1.55         {
217 kumpf        1.72             CloseConnectionMessage* closeConnectionMessage =
218                                   (CloseConnectionMessage*)message;
219                   
220                               for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
221                               {
222                                   HTTPConnection* connection = _rep->connections[i];
223                                   SocketHandle socket = connection->getSocket();
224                   
225                                   if (socket == closeConnectionMessage->socket)
226                                   {
227                                       _monitor->unsolicitSocketMessages(socket);
228                                       _rep->connections.remove(i);
229                                       delete connection;
230                                       break;
231                                   }
232                               }
233 h.sterling   1.55         }
234 mday         1.4  
235 kumpf        1.72         default:
236                               // ATTN: need unexpected message error!
237                               break;
238                       }
239 mday         1.4  
240 kumpf        1.72     delete message;
241 mday         1.4  }
242 mike         1.2  
243                   
244 mday         1.4  void HTTPConnector::handleEnqueue()
245                   {
246 kumpf        1.72     Message* message = dequeue();
247 mday         1.4  
248 kumpf        1.72     if (!message)
249                           return;
250 mday         1.4  
251 kumpf        1.72     handleEnqueue(message);
252 mike         1.2  }
253                   
254                   HTTPConnection* HTTPConnector::connect(
255 kumpf        1.72     const String& host,
256                       const Uint32 portNumber,
257                       SSLContext * sslContext,
258                       MessageQueue* outputMessageQueue)
259 mike         1.2  {
260 kumpf        1.75     PEG_METHOD_ENTER(TRC_HTTP, "HTTPConnector::connect()");
261 thilo.boehm  1.74 
262 kumpf        1.72     SocketHandle socket;
263 kumpf        1.10 
264 h.sterling   1.55 #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
265 kumpf        1.72     if (host == String::EMPTY)
266                       {
267                           // Set up the domain socket for a local connection
268                   
269                           sockaddr_un address;
270                           address.sun_family = AF_UNIX;
271                           strcpy(address.sun_path, PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
272 chuck        1.41 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
273 kumpf        1.72         AtoE(address.sun_path);
274 chuck        1.41 #endif
275 kumpf        1.10 
276 kumpf        1.72         socket = Socket::createSocket(AF_UNIX, SOCK_STREAM, 0);
277                           if (socket == PEGASUS_INVALID_SOCKET)
278 thilo.boehm  1.74         {
279                               PEG_METHOD_EXIT();
280 kumpf        1.72             throw CannotCreateSocketException();
281 thilo.boehm  1.74         }
282                               
283 kumpf        1.72 
284                           // Connect the socket to the address:
285                   
286                           if (::connect(socket,
287                                   reinterpret_cast<sockaddr*>(&address),
288                                   sizeof(address)) < 0)
289                           {
290                               MessageLoaderParms parms(
291                                   "Common.HTTPConnector.CONNECTION_FAILED_LOCAL_CIM_SERVER",
292                                   "Cannot connect to local CIM server. Connection failed.");
293                               Socket::close(socket);
294 thilo.boehm  1.74             PEG_METHOD_EXIT();
295 kumpf        1.72             throw CannotConnectException(parms);
296                           }
297                       }
298                       else
299                       {
300 kumpf        1.10 #endif
301                   
302 kumpf        1.72         // Make the internet address:
303                   
304                           sockaddr_in address;
305                   
306                           if (!_MakeAddress((const char*)host.getCString(), portNumber, address))
307                           {
308                               char portStr [32];
309                               sprintf (portStr, "%u", portNumber);
310 thilo.boehm  1.74             PEG_METHOD_EXIT();
311 kumpf        1.72             throw InvalidLocatorException(host + ":" + portStr);
312                           }
313 mike         1.2  
314                   
315 kumpf        1.72         // Create the socket:
316                           socket = Socket::createSocket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
317                           if (socket == PEGASUS_INVALID_SOCKET)
318 thilo.boehm  1.74         {
319                               PEG_METHOD_EXIT();
320 kumpf        1.72             throw CannotCreateSocketException();
321 thilo.boehm  1.74         }
322                               
323 kumpf        1.72 
324                           // Conect the socket to the address:
325                           if (::connect(socket,
326                                   reinterpret_cast<sockaddr*>(&address),
327                                   sizeof(address)) < 0)
328                           {
329                               char portStr[32];
330                               sprintf(portStr, "%u", portNumber);
331                               MessageLoaderParms parms(
332                                   "Common.HTTPConnector.CONNECTION_FAILED_TO",
333                                   "Cannot connect to $0:$1. Connection failed.",
334                                   host,
335                                   portStr);
336                               Socket::close(socket);
337 thilo.boehm  1.74             PEG_METHOD_EXIT();
338 kumpf        1.72             throw CannotConnectException(parms);
339                           }
340 kumpf        1.10 
341 h.sterling   1.55 #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
342 kumpf        1.72     }
343 kumpf        1.10 #endif
344 mike         1.2  
345 kumpf        1.72     // Create HTTPConnection object:
346                   
347 kumpf        1.76     SharedPtr<MP_Socket> mp_socket(new MP_Socket(socket, sslContext, 0));
348 kumpf        1.72     if (mp_socket->connect() < 0)
349                       {
350                           char portStr[32];
351                           sprintf(portStr, "%u", portNumber);
352                           MessageLoaderParms parms(
353                               "Common.HTTPConnector.CONNECTION_FAILED_TO",
354                               "Cannot connect to $0:$1. Connection failed.",
355                               host,
356                               portStr);
357                           mp_socket->close();
358 thilo.boehm  1.74         PEG_METHOD_EXIT();
359 kumpf        1.72         throw CannotConnectException(parms);
360                       }
361 mike         1.2  
362 kumpf        1.72     HTTPConnection* connection = new HTTPConnection(
363 kumpf        1.70         _monitor, mp_socket, String::EMPTY, this,
364                           static_cast<MessageQueueService *>(outputMessageQueue));
365 mike         1.2  
366 kumpf        1.72     // Solicit events on this new connection's socket:
367 mike         1.2  
368 kumpf        1.72     if (-1 == (_entry_index = _monitor->solicitSocketMessages(
369                               connection->getSocket(),
370                               SocketMessage::READ | SocketMessage::EXCEPTION,
371                               connection->getQueueId(), Monitor::CONNECTOR)))
372                       {
373                           (connection->getMPSocket()).close();
374                       }
375 mike         1.2  
376 kumpf        1.72     // Save the socket for cleanup later:
377 a.arora      1.47 
378 kumpf        1.72     _rep->connections.append(connection);
379 thilo.boehm  1.74     PEG_METHOD_EXIT();
380 kumpf        1.72     return connection;
381 mike         1.2  }
382                   
383                   void HTTPConnector::destroyConnections()
384                   {
385 kumpf        1.72     // For each connection created by this object:
386 mike         1.2  
387 kumpf        1.72     for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
388                       {
389                           _deleteConnection(_rep->connections[i]);
390                       }
391 mike         1.2  
392 kumpf        1.72     _rep->connections.clear();
393 mike         1.2  }
394                   
395 mday         1.32 
396 kumpf        1.7  void HTTPConnector::disconnect(HTTPConnection* currentConnection)
397                   {
398                       //
399                       // find and delete the specified connection
400                       //
401 denise.eckstein 1.56 
402                          Uint32 index = PEG_NOT_FOUND;
403 kumpf           1.7      for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
404                          {
405                              if (currentConnection == _rep->connections[i])
406                              {
407 denise.eckstein 1.56             index = i;
408                                  break;
409                              }
410                           }
411                      
412                          PEGASUS_ASSERT(index != PEG_NOT_FOUND);
413 tony            1.34 
414 mike            1.66     SocketHandle socket = currentConnection->getSocket();
415 denise.eckstein 1.56     _monitor->unsolicitSocketMessages(socket);
416                          _rep->connections.remove(index);
417                          delete currentConnection;
418 kumpf           1.7  }
419 kumpf           1.9  
420                      void HTTPConnector::_deleteConnection(HTTPConnection* httpConnection)
421 dj.gorey        1.45 {
422 mike            1.66     SocketHandle socket = httpConnection->getSocket();
423 dj.gorey        1.45 
424                          // Unsolicit SocketMessages:
425                      
426                          _monitor->unsolicitSocketMessages(socket);
427                      
428                          // Destroy the connection (causing it to close):
429                      
430                          delete httpConnection;
431                      }
432                      
433 mike            1.2  PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2