(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 humberto 1.33 #include <Pegasus/Common/MessageLoader.h> //l10n
 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 mike     1.68 #  include "EBCDIC_OS400.h"
 47 david    1.38 #endif
 48               
 49 marek    1.44 #ifdef PEGASUS_OS_ZOS
 50               #  include <resolv.h>  // MAXHOSTNAMELEN
 51               #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 mday     1.4     const char* hostname, 
 67                  int port, 
 68                  sockaddr_in& address)
 69 mike     1.2  {
 70 keith.petley 1.36    if (!hostname)
 71 mday         1.4        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 h.sterling   1.55     
 82 dave.sudlik  1.49 ////////////////////////////////////////////////////////////////////////////////
 83                   // This code used to check if the first character of "hostname" was alphabetic
 84                   // to indicate hostname instead of IP address. But RFC 1123, section 2.1, relaxed
 85                   // this requirement to alphabetic character *or* digit. So bug 1462 changed the
 86                   // flow here to call inet_addr first to check for a valid IP address in dotted
 87                   // decimal notation. If it's not a valid IP address, then try to validate
 88                   // 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                   // Hence the call to inet_addr() first.
 92                   ////////////////////////////////////////////////////////////////////////////////
 93                   
 94                   #ifdef PEGASUS_OS_OS400
 95                      unsigned long tmp_addr = inet_addr(ebcdicHost);
 96                   #else
 97                      unsigned long tmp_addr = inet_addr((char *)hostname);
 98 kumpf        1.62 #endif
 99 dave.sudlik  1.49 
100 kumpf        1.62    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                      if (tmp_addr == 0xFFFFFFFF)  // if hostname is not an IP address
107 keith.petley 1.36    {
108 kumpf        1.62 #if defined(PEGASUS_OS_LINUX)
109                         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                   #elif defined(PEGASUS_OS_SOLARIS)
121                         char hostEntryBuffer[8192];
122                         struct hostent hostEntryStruct;
123                         int hostEntryErrno;
124                   
125                         hostEntry = gethostbyname_r(
126                             (char *)hostname,
127                             &hostEntryStruct,
128                             hostEntryBuffer,
129 kumpf        1.62           sizeof(hostEntryBuffer),
130                             &hostEntryErrno);
131 david        1.38 #elif defined(PEGASUS_OS_OS400)
132 kumpf        1.62       hostEntry = gethostbyname(ebcdicHost);
133 marek        1.44 #elif defined(PEGASUS_OS_ZOS)
134 h.sterling   1.55       if (String::equalNoCase("localhost",String(hostname)))
135                         {
136 kumpf        1.62           char hostName[PEGASUS_MAXHOSTNAMELEN + 1];
137 h.sterling   1.55           gethostname( hostName, sizeof( hostName ) );
138 kumpf        1.60           hostName[sizeof(hostName)-1] = 0;
139 kumpf        1.62           hostEntry = gethostbyname(hostName);
140 h.sterling   1.55       } else {
141 kumpf        1.62           hostEntry = gethostbyname((char *)hostname);
142 h.sterling   1.55       }
143 keith.petley 1.36 #else
144 kumpf        1.62       hostEntry = gethostbyname((char *)hostname);
145 keith.petley 1.36 #endif
146 kumpf        1.62       if (!hostEntry)
147 keith.petley 1.36       {
148 kumpf        1.62           return false;
149 keith.petley 1.36       }
150                   
151                         memset(&address, 0, sizeof(address));
152 kumpf        1.62       memcpy(&address.sin_addr, hostEntry->h_addr, hostEntry->h_length);
153                         address.sin_family = hostEntry->h_addrtype;
154 keith.petley 1.36       address.sin_port = htons(port);
155                      }     
156 dave.sudlik  1.49    else    // else hostname *is* a dotted-decimal IP address
157 mday         1.4     {
158 karl         1.25       memset(&address, 0, sizeof(address));
159                         address.sin_family = AF_INET;
160 keith.petley 1.36       address.sin_addr.s_addr = tmp_addr;
161 karl         1.25       address.sin_port = htons(port);
162 mday         1.4     }
163 mike         1.2  
164 mday         1.4     return true;
165 mike         1.2  }
166                   
167                   ////////////////////////////////////////////////////////////////////////////////
168                   //
169                   // HTTPConnectorRep
170                   //
171                   ////////////////////////////////////////////////////////////////////////////////
172                   
173                   struct HTTPConnectorRep
174                   {
175 mday         1.4        Array<HTTPConnection*> connections;
176 mike         1.2  };
177                   
178                   ////////////////////////////////////////////////////////////////////////////////
179                   //
180                   // HTTPConnector
181                   //
182                   ////////////////////////////////////////////////////////////////////////////////
183                   
184                   HTTPConnector::HTTPConnector(Monitor* monitor)
185 kumpf        1.12    : Base(PEGASUS_QUEUENAME_HTTPCONNECTOR),
186 mday         1.19      _monitor(monitor), _entry_index(-1)
187 mike         1.2  {
188 mday         1.3     _rep = new HTTPConnectorRep;
189                      Socket::initializeInterface();
190 mike         1.2  }
191                   
192                   HTTPConnector::~HTTPConnector()
193                   {
194 mday         1.4     delete _rep;
195                      Socket::uninitializeInterface();
196 mike         1.2  }
197                   
198 mday         1.4  void HTTPConnector::handleEnqueue(Message *message)
199 mike         1.2  {
200                   
201 mday         1.4     if (!message)
202                         return;
203 mike         1.2  
204 mday         1.4     switch (message->getType())
205                      {
206                         // It might be useful to catch socket messages later to implement
207                         // asynchronous establishment of connections.
208 mike         1.2  
209 mday         1.4        case SOCKET_MESSAGE:
210 h.sterling   1.55      break;
211 mike         1.2  
212 mday         1.4        case CLOSE_CONNECTION_MESSAGE:
213                         {
214 h.sterling   1.55      CloseConnectionMessage* closeConnectionMessage 
215                           = (CloseConnectionMessage*)message;
216 mike         1.2  
217 h.sterling   1.55      for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
218                        {
219                           HTTPConnection* connection = _rep->connections[i];  
220 mike         1.66         SocketHandle socket = connection->getSocket();
221 h.sterling   1.55 
222                           if (socket == closeConnectionMessage->socket)
223                           {
224                              _monitor->unsolicitSocketMessages(socket);
225                              _rep->connections.remove(i);
226                              delete connection;
227                              break;
228                           }
229                        }
230 mday         1.4        }
231                   
232                         default:
233 h.sterling   1.55      // ATTN: need unexpected message error!
234                        break;
235 mday         1.4     };
236                   
237                      delete message;
238                   }
239 mike         1.2  
240                   
241 mday         1.4  void HTTPConnector::handleEnqueue()
242                   {
243                   
244                      Message* message = dequeue();
245                   
246                      if (!message)
247                         return;
248 mike         1.2  
249 mday         1.4     handleEnqueue(message);
250 mike         1.2  }
251                   
252                   HTTPConnection* HTTPConnector::connect(
253 kumpf        1.24    const String& host, 
254                      const Uint32 portNumber,
255 kumpf        1.11    SSLContext * sslContext,
256 mday         1.4     MessageQueue* outputMessageQueue)
257 mike         1.2  {
258 mike         1.66    SocketHandle socket;
259 kumpf        1.10 
260 h.sterling   1.55 #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
261 kumpf        1.24    if (host == String::EMPTY)
262 kumpf        1.10    {
263                         // Set up the domain socket for a local connection
264                   
265                         sockaddr_un address;
266                         address.sun_family = AF_UNIX;
267 kumpf        1.28       strcpy(address.sun_path, PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
268 chuck        1.41 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
269                         AtoE(address.sun_path);
270                   #endif
271 kumpf        1.10 
272 thilo.boehm  1.71       socket = Socket::createSocket(AF_UNIX, SOCK_STREAM, 0);
273 david.dillard 1.58       if (socket == PEGASUS_INVALID_SOCKET)
274 kumpf         1.20          throw CannotCreateSocketException();
275 kumpf         1.10 
276                          // Connect the socket to the address:
277                    
278                          if (::connect(socket,
279                                        reinterpret_cast<sockaddr*>(&address),
280                                        sizeof(address)) < 0)
281                          {
282 h.sterling    1.55      
283                            //l10n
284 humberto      1.33          //throw CannotConnectException("Cannot connect to local CIM server. Connection failed.");
285                             MessageLoaderParms parms("Common.HTTPConnector.CONNECTION_FAILED_LOCAL_CIM_SERVER",
286 h.sterling    1.55                                   "Cannot connect to local CIM server. Connection failed.");
287 nag.boranna   1.54          Socket::close(socket);
288 humberto      1.33          throw CannotConnectException(parms);
289 kumpf         1.10       }
290                       }
291                       else
292                       {
293                    #endif
294                    
295 mday          1.4     // Make the internet address:
296 mike          1.2  
297 mday          1.4     sockaddr_in address;
298 mike          1.2  
299 kumpf         1.24    if (!_MakeAddress((const char*)host.getCString(), portNumber, address))
300 mday          1.4     {
301 kumpf         1.24       char portStr [32];
302                          sprintf (portStr, "%u", portNumber);
303 kumpf         1.27       throw InvalidLocatorException(host + ":" + portStr);
304 mday          1.4     }
305 mike          1.2  
306                    
307 mday          1.4     // Create the socket:
308 thilo.boehm   1.71    socket = Socket::createSocket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
309 david.dillard 1.58    if (socket == PEGASUS_INVALID_SOCKET)
310 kumpf         1.20       throw CannotCreateSocketException();
311 marek         1.64    
312 mday          1.4     // Conect the socket to the address:
313 kumpf         1.10    if (::connect(socket,
314                                     reinterpret_cast<sockaddr*>(&address),
315                                     sizeof(address)) < 0)
316                       {
317 kumpf         1.24       char portStr [32];
318                          sprintf (portStr, "%u", portNumber);
319 humberto      1.33       //l10n
320                          //throw CannotConnectException("Cannot connect to " + host + ":" + portStr +". Connection failed.");
321                          MessageLoaderParms parms("Common.HTTPConnector.CONNECTION_FAILED_TO",
322 h.sterling    1.55                                "Cannot connect to $0:$1. Connection failed.",
323                                                   host,
324                                                   portStr);
325 nag.boranna   1.54       Socket::close(socket);
326 humberto      1.33       throw CannotConnectException(parms);
327 kumpf         1.10    }
328                    
329 h.sterling    1.55 #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
330 kumpf         1.10    }
331                    #endif
332 mike          1.2  
333 mday          1.4     // Create HTTPConnection object:
334 mike          1.2  
335 sushma.fernandes 1.69    AutoPtr<MP_Socket> mp_socket(new MP_Socket(socket, sslContext, 0));
336 mday             1.4     if (mp_socket->connect() < 0) {
337 kumpf            1.24       char portStr [32];
338                             sprintf (portStr, "%u", portNumber);
339 humberto         1.33       //l10n
340                             //throw CannotConnectException("Cannot connect to " + host + ":" + portStr +". Connection failed.");
341                             MessageLoaderParms parms("Common.HTTPConnector.CONNECTION_FAILED_TO",
342 h.sterling       1.55                                "Cannot connect to $0:$1. Connection failed.",
343                                                      host,
344                                                      portStr);
345 nag.boranna      1.54       mp_socket->close();
346 humberto         1.33       throw CannotConnectException(parms);
347 mday             1.4     }
348 mike             1.2      
349 kumpf            1.70    HTTPConnection* connection = new HTTPConnection(
350                               _monitor, mp_socket, String::EMPTY, this,
351                               static_cast<MessageQueueService *>(outputMessageQueue));
352 mike             1.2  
353 mday             1.4     // Solicit events on this new connection's socket:
354 mike             1.2  
355 mday             1.31    if (-1 == (_entry_index = _monitor->solicitSocketMessages(
356 h.sterling       1.55       connection->getSocket(),
357                             SocketMessage::READ | SocketMessage::EXCEPTION,
358                             connection->getQueueId(), Monitor::CONNECTOR)))
359 mday             1.31    {
360 a.arora          1.51       (connection->getMPSocket()).close();
361 mday             1.31    }
362 mike             1.2  
363 mday             1.4     // Save the socket for cleanup later:
364 a.arora          1.47 
365 mday             1.4     _rep->connections.append(connection);
366 mike             1.2  
367 mday             1.4     return connection;
368 mike             1.2  }
369                       
370                       void HTTPConnector::destroyConnections()
371                       {
372 mday             1.4     // For each connection created by this object:
373 mike             1.2  
374 mday             1.4     for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
375                          {
376 kumpf            1.9        _deleteConnection(_rep->connections[i]);
377 mday             1.4     }
378 mike             1.2  
379 mday             1.4     _rep->connections.clear();
380 mike             1.2  }
381                       
382 mday             1.32 
383 kumpf            1.7  void HTTPConnector::disconnect(HTTPConnection* currentConnection)
384                       {
385                           //
386                           // find and delete the specified connection
387                           //
388 denise.eckstein  1.56 
389                           Uint32 index = PEG_NOT_FOUND;
390 kumpf            1.7      for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
391                           {
392                               if (currentConnection == _rep->connections[i])
393                               {
394 denise.eckstein  1.56             index = i;
395                                   break;
396                               }
397                            }
398                       
399                           PEGASUS_ASSERT(index != PEG_NOT_FOUND);
400 tony             1.34 
401 mike             1.66     SocketHandle socket = currentConnection->getSocket();
402 denise.eckstein  1.56     _monitor->unsolicitSocketMessages(socket);
403                           _rep->connections.remove(index);
404                           delete currentConnection;
405 kumpf            1.7  }
406 kumpf            1.9  
407                       void HTTPConnector::_deleteConnection(HTTPConnection* httpConnection)
408 dj.gorey         1.45 {
409 mike             1.66     SocketHandle socket = httpConnection->getSocket();
410 dj.gorey         1.45 
411                           // Unsolicit SocketMessages:
412                       
413                           _monitor->unsolicitSocketMessages(socket);
414                       
415                           // Destroy the connection (causing it to close):
416                       
417                           delete httpConnection;
418                       }
419                       
420 mike             1.2  PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2