(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 kumpf        1.72     delete _rep;
197                       Socket::uninitializeInterface();
198 mike         1.2  }
199                   
200 mday         1.4  void HTTPConnector::handleEnqueue(Message *message)
201 mike         1.2  {
202 kumpf        1.72     if (!message)
203                           return;
204 mike         1.2  
205 kumpf        1.72     switch (message->getType())
206                       {
207                           // It might be useful to catch socket messages later to implement
208                           // asynchronous establishment of connections.
209 mike         1.2  
210 kumpf        1.72         case SOCKET_MESSAGE:
211                               break;
212 h.sterling   1.55 
213 kumpf        1.72         case CLOSE_CONNECTION_MESSAGE:
214 h.sterling   1.55         {
215 kumpf        1.72             CloseConnectionMessage* closeConnectionMessage =
216                                   (CloseConnectionMessage*)message;
217                   
218                               for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
219                               {
220                                   HTTPConnection* connection = _rep->connections[i];
221                                   SocketHandle socket = connection->getSocket();
222                   
223                                   if (socket == closeConnectionMessage->socket)
224                                   {
225                                       _monitor->unsolicitSocketMessages(socket);
226                                       _rep->connections.remove(i);
227                                       delete connection;
228                                       break;
229                                   }
230                               }
231 h.sterling   1.55         }
232 mday         1.4  
233 kumpf        1.72         default:
234                               // ATTN: need unexpected message error!
235                               break;
236                       }
237 mday         1.4  
238 kumpf        1.72     delete message;
239 mday         1.4  }
240 mike         1.2  
241                   
242 mday         1.4  void HTTPConnector::handleEnqueue()
243                   {
244 kumpf        1.72     Message* message = dequeue();
245 mday         1.4  
246 kumpf        1.72     if (!message)
247                           return;
248 mday         1.4  
249 kumpf        1.72     handleEnqueue(message);
250 mike         1.2  }
251                   
252                   HTTPConnection* HTTPConnector::connect(
253 kumpf        1.72     const String& host,
254                       const Uint32 portNumber,
255                       SSLContext * sslContext,
256                       MessageQueue* outputMessageQueue)
257 mike         1.2  {
258 kumpf        1.72     SocketHandle socket;
259 kumpf        1.10 
260 h.sterling   1.55 #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
261 kumpf        1.72     if (host == String::EMPTY)
262                       {
263                           // Set up the domain socket for a local connection
264                   
265                           sockaddr_un address;
266                           address.sun_family = AF_UNIX;
267                           strcpy(address.sun_path, PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
268 chuck        1.41 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
269 kumpf        1.72         AtoE(address.sun_path);
270 chuck        1.41 #endif
271 kumpf        1.10 
272 kumpf        1.72         socket = Socket::createSocket(AF_UNIX, SOCK_STREAM, 0);
273                           if (socket == PEGASUS_INVALID_SOCKET)
274                               throw CannotCreateSocketException();
275                   
276                           // Connect the socket to the address:
277                   
278                           if (::connect(socket,
279                                   reinterpret_cast<sockaddr*>(&address),
280                                   sizeof(address)) < 0)
281                           {
282                               MessageLoaderParms parms(
283                                   "Common.HTTPConnector.CONNECTION_FAILED_LOCAL_CIM_SERVER",
284                                   "Cannot connect to local CIM server. Connection failed.");
285                               Socket::close(socket);
286                               throw CannotConnectException(parms);
287                           }
288                       }
289                       else
290                       {
291 kumpf        1.10 #endif
292                   
293 kumpf        1.72         // Make the internet address:
294                   
295                           sockaddr_in address;
296                   
297                           if (!_MakeAddress((const char*)host.getCString(), portNumber, address))
298                           {
299                               char portStr [32];
300                               sprintf (portStr, "%u", portNumber);
301                               throw InvalidLocatorException(host + ":" + portStr);
302                           }
303 mike         1.2  
304                   
305 kumpf        1.72         // Create the socket:
306                           socket = Socket::createSocket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
307                           if (socket == PEGASUS_INVALID_SOCKET)
308                               throw CannotCreateSocketException();
309                   
310                           // Conect the socket to the address:
311                           if (::connect(socket,
312                                   reinterpret_cast<sockaddr*>(&address),
313                                   sizeof(address)) < 0)
314                           {
315                               char portStr[32];
316                               sprintf(portStr, "%u", portNumber);
317                               MessageLoaderParms parms(
318                                   "Common.HTTPConnector.CONNECTION_FAILED_TO",
319                                   "Cannot connect to $0:$1. Connection failed.",
320                                   host,
321                                   portStr);
322                               Socket::close(socket);
323                               throw CannotConnectException(parms);
324                           }
325 kumpf        1.10 
326 h.sterling   1.55 #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
327 kumpf        1.72     }
328 kumpf        1.10 #endif
329 mike         1.2  
330 kumpf        1.72     // Create HTTPConnection object:
331                   
332                       AutoPtr<MP_Socket> mp_socket(new MP_Socket(socket, sslContext, 0));
333                       if (mp_socket->connect() < 0)
334                       {
335                           char portStr[32];
336                           sprintf(portStr, "%u", portNumber);
337                           MessageLoaderParms parms(
338                               "Common.HTTPConnector.CONNECTION_FAILED_TO",
339                               "Cannot connect to $0:$1. Connection failed.",
340                               host,
341                               portStr);
342                           mp_socket->close();
343                           throw CannotConnectException(parms);
344                       }
345 mike         1.2  
346 kumpf        1.72     HTTPConnection* connection = new HTTPConnection(
347 kumpf        1.70         _monitor, mp_socket, String::EMPTY, this,
348                           static_cast<MessageQueueService *>(outputMessageQueue));
349 mike         1.2  
350 kumpf        1.72     // Solicit events on this new connection's socket:
351 mike         1.2  
352 kumpf        1.72     if (-1 == (_entry_index = _monitor->solicitSocketMessages(
353                               connection->getSocket(),
354                               SocketMessage::READ | SocketMessage::EXCEPTION,
355                               connection->getQueueId(), Monitor::CONNECTOR)))
356                       {
357                           (connection->getMPSocket()).close();
358                       }
359 mike         1.2  
360 kumpf        1.72     // Save the socket for cleanup later:
361 a.arora      1.47 
362 kumpf        1.72     _rep->connections.append(connection);
363 mike         1.2  
364 kumpf        1.72     return connection;
365 mike         1.2  }
366                   
367                   void HTTPConnector::destroyConnections()
368                   {
369 kumpf        1.72     // For each connection created by this object:
370 mike         1.2  
371 kumpf        1.72     for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
372                       {
373                           _deleteConnection(_rep->connections[i]);
374                       }
375 mike         1.2  
376 kumpf        1.72     _rep->connections.clear();
377 mike         1.2  }
378                   
379 mday         1.32 
380 kumpf        1.7  void HTTPConnector::disconnect(HTTPConnection* currentConnection)
381                   {
382                       //
383                       // find and delete the specified connection
384                       //
385 denise.eckstein 1.56 
386                          Uint32 index = PEG_NOT_FOUND;
387 kumpf           1.7      for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
388                          {
389                              if (currentConnection == _rep->connections[i])
390                              {
391 denise.eckstein 1.56             index = i;
392                                  break;
393                              }
394                           }
395                      
396                          PEGASUS_ASSERT(index != PEG_NOT_FOUND);
397 tony            1.34 
398 mike            1.66     SocketHandle socket = currentConnection->getSocket();
399 denise.eckstein 1.56     _monitor->unsolicitSocketMessages(socket);
400                          _rep->connections.remove(index);
401                          delete currentConnection;
402 kumpf           1.7  }
403 kumpf           1.9  
404                      void HTTPConnector::_deleteConnection(HTTPConnection* httpConnection)
405 dj.gorey        1.45 {
406 mike            1.66     SocketHandle socket = httpConnection->getSocket();
407 dj.gorey        1.45 
408                          // Unsolicit SocketMessages:
409                      
410                          _monitor->unsolicitSocketMessages(socket);
411                      
412                          // Destroy the connection (causing it to close):
413                      
414                          delete httpConnection;
415                      }
416                      
417 mike            1.2  PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2