(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            // Author: Mike Brasher (mbrasher@bmc.com)
 33            //
 34 kumpf 1.24 // Modified By: Carol Ann Krug Graves, Hewlett-Packard Company
 35            //                (carolann_graves@hp.com)
 36 kumpf 1.30 // Modified By: Sushma Fernandes, Hewlett-Packard Company
 37            //                (sushma_fernandes@hp.com)
 38 dj.gorey 1.45 // Modified By: Dan Gorey, IBM (djgorey@us.ibm.com)
 39 a.arora  1.46 // Modified By: Amit Arora (amita@in.ibm.com) for Bug#1170
 40 dave.sudlik 1.49 //              Dave Sudlik, IBM (dsudlik@us.ibm.com) for Bug#1462
 41 a.arora     1.51 //              Amit Arora, IBM (amita@in.ibm.com) for Bug#2541
 42 kumpf       1.52 //              Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
 43 david.dillard 1.59 //              David Dillard, Symantec Corp (david_dillard@symantec.com)
 44 mike          1.2  //
 45                    //%/////////////////////////////////////////////////////////////////////////////
 46                    
 47                    #include "Config.h"
 48                    #include <iostream>
 49 kumpf         1.12 #include "Constants.h"
 50 mike          1.2  #include "Socket.h"
 51 humberto      1.33 #include <Pegasus/Common/MessageLoader.h> //l10n
 52 mike          1.2  
 53                    #ifdef PEGASUS_OS_TYPE_WINDOWS
 54 mday          1.8  # include <windows.h>
 55 mike          1.2  #else
 56                    # include <cctype>
 57                    # include <cstdlib>
 58                    # include <errno.h>
 59                    # include <fcntl.h>
 60                    # include <netdb.h>
 61                    # include <netinet/in.h>
 62                    # include <arpa/inet.h>
 63                    # include <sys/socket.h>
 64 h.sterling    1.55 # ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
 65 kumpf         1.29 # include <unistd.h>
 66 kumpf         1.10 #  include <sys/un.h>
 67                    # endif
 68 mike          1.2  #endif
 69                    
 70                    #include "Socket.h"
 71                    #include "TLS.h"
 72                    #include "HTTPConnector.h"
 73                    #include "HTTPConnection.h"
 74                    
 75 david         1.38 #ifdef PEGASUS_OS_OS400
 76                    #  include "OS400ConvertChar.h"
 77                    #endif
 78                    
 79 marek         1.44 #ifdef PEGASUS_OS_ZOS
 80                    #  include <resolv.h>  // MAXHOSTNAMELEN
 81                    #endif
 82                    
 83 mike          1.2  PEGASUS_USING_STD;
 84                    
 85                    PEGASUS_NAMESPACE_BEGIN
 86                    
 87 a.arora       1.46 class bsd_socket_rep;
 88                    
 89 mike          1.2  ////////////////////////////////////////////////////////////////////////////////
 90                    //
 91                    // Local routines:
 92                    //
 93                    ////////////////////////////////////////////////////////////////////////////////
 94                    
 95                    static Boolean _MakeAddress(
 96 mday          1.4     const char* hostname, 
 97                       int port, 
 98                       sockaddr_in& address)
 99 mike          1.2  {
100 keith.petley  1.36    if (!hostname)
101 mday          1.4        return false;
102 david         1.38 
103                    #ifdef PEGASUS_OS_OS400
104                        char ebcdicHost[256];
105                        if (strlen(hostname) < 256)
106 h.sterling    1.55     strcpy(ebcdicHost, hostname);
107 david         1.38     else
108 h.sterling    1.55     return false;
109 david         1.38     AtoE(ebcdicHost);
110                    #endif
111 h.sterling    1.55     
112 dave.sudlik   1.49 ////////////////////////////////////////////////////////////////////////////////
113                    // This code used to check if the first character of "hostname" was alphabetic
114                    // to indicate hostname instead of IP address. But RFC 1123, section 2.1, relaxed
115                    // this requirement to alphabetic character *or* digit. So bug 1462 changed the
116                    // flow here to call inet_addr first to check for a valid IP address in dotted
117                    // decimal notation. If it's not a valid IP address, then try to validate
118                    // it as a hostname.
119                    // RFC 1123 states: The host SHOULD check the string syntactically for a 
120                    // dotted-decimal number before looking it up in the Domain Name System. 
121                    // Hence the call to inet_addr() first.
122                    ////////////////////////////////////////////////////////////////////////////////
123                    
124                    #ifdef PEGASUS_OS_OS400
125                       unsigned long tmp_addr = inet_addr(ebcdicHost);
126                    #else
127                       unsigned long tmp_addr = inet_addr((char *)hostname);
128 kumpf         1.62 #endif
129 dave.sudlik   1.49 
130 kumpf         1.62    struct hostent* hostEntry;
131 dave.sudlik   1.49 
132                    // Note: 0xFFFFFFFF is actually a valid IP address (255.255.255.255).
133                    //       A better solution would be to use inet_aton() or equivalent, as
134                    //       inet_addr() is now considered "obsolete".
135                    
136                       if (tmp_addr == 0xFFFFFFFF)  // if hostname is not an IP address
137 keith.petley  1.36    {
138 kumpf         1.62 #if defined(PEGASUS_OS_LINUX)
139                          char hostEntryBuffer[8192];
140                          struct hostent hostEntryStruct;
141                          int hostEntryErrno;
142                    
143                          gethostbyname_r(
144                              hostname,
145                              &hostEntryStruct,
146                              hostEntryBuffer,
147                              sizeof(hostEntryBuffer),
148                              &hostEntry,
149                              &hostEntryErrno);
150                    #elif defined(PEGASUS_OS_SOLARIS)
151                          char hostEntryBuffer[8192];
152                          struct hostent hostEntryStruct;
153                          int hostEntryErrno;
154                    
155                          hostEntry = gethostbyname_r(
156                              (char *)hostname,
157                              &hostEntryStruct,
158                              hostEntryBuffer,
159 kumpf         1.62           sizeof(hostEntryBuffer),
160                              &hostEntryErrno);
161 david         1.38 #elif defined(PEGASUS_OS_OS400)
162 kumpf         1.62       hostEntry = gethostbyname(ebcdicHost);
163 marek         1.44 #elif defined(PEGASUS_OS_ZOS)
164 h.sterling    1.55       if (String::equalNoCase("localhost",String(hostname)))
165                          {
166 kumpf         1.62           char hostName[PEGASUS_MAXHOSTNAMELEN + 1];
167 h.sterling    1.55           gethostname( hostName, sizeof( hostName ) );
168 kumpf         1.60           hostName[sizeof(hostName)-1] = 0;
169 kumpf         1.62           hostEntry = gethostbyname(hostName);
170 h.sterling    1.55       } else {
171 kumpf         1.62           hostEntry = gethostbyname((char *)hostname);
172 h.sterling    1.55       }
173 keith.petley  1.36 #else
174 kumpf         1.62       hostEntry = gethostbyname((char *)hostname);
175 keith.petley  1.36 #endif
176 kumpf         1.62       if (!hostEntry)
177 keith.petley  1.36       {
178 kumpf         1.62           return false;
179 keith.petley  1.36       }
180                    
181                          memset(&address, 0, sizeof(address));
182 kumpf         1.62       memcpy(&address.sin_addr, hostEntry->h_addr, hostEntry->h_length);
183                          address.sin_family = hostEntry->h_addrtype;
184 keith.petley  1.36       address.sin_port = htons(port);
185                       }     
186 dave.sudlik   1.49    else    // else hostname *is* a dotted-decimal IP address
187 mday          1.4     {
188 karl          1.25       memset(&address, 0, sizeof(address));
189                          address.sin_family = AF_INET;
190 keith.petley  1.36       address.sin_addr.s_addr = tmp_addr;
191 karl          1.25       address.sin_port = htons(port);
192 mday          1.4     }
193 mike          1.2  
194 mday          1.4     return true;
195 mike          1.2  }
196                    
197                    ////////////////////////////////////////////////////////////////////////////////
198                    //
199                    // HTTPConnectorRep
200                    //
201                    ////////////////////////////////////////////////////////////////////////////////
202                    
203                    struct HTTPConnectorRep
204                    {
205 mday          1.4        Array<HTTPConnection*> connections;
206 mike          1.2  };
207                    
208                    ////////////////////////////////////////////////////////////////////////////////
209                    //
210                    // HTTPConnector
211                    //
212                    ////////////////////////////////////////////////////////////////////////////////
213                    
214                    HTTPConnector::HTTPConnector(Monitor* monitor)
215 kumpf         1.12    : Base(PEGASUS_QUEUENAME_HTTPCONNECTOR),
216 mday          1.19      _monitor(monitor), _entry_index(-1)
217 mike          1.2  {
218 mday          1.3     _rep = new HTTPConnectorRep;
219                       Socket::initializeInterface();
220 mike          1.2  }
221                    
222                    HTTPConnector::~HTTPConnector()
223                    {
224 mday          1.4     delete _rep;
225                       Socket::uninitializeInterface();
226 mike          1.2  }
227                    
228 mday          1.4  void HTTPConnector::handleEnqueue(Message *message)
229 mike          1.2  {
230                    
231 mday          1.4     if (!message)
232                          return;
233 mike          1.2  
234 mday          1.4     switch (message->getType())
235                       {
236                          // It might be useful to catch socket messages later to implement
237                          // asynchronous establishment of connections.
238 mike          1.2  
239 mday          1.4        case SOCKET_MESSAGE:
240 h.sterling    1.55      break;
241 mike          1.2  
242 mday          1.4        case CLOSE_CONNECTION_MESSAGE:
243                          {
244 h.sterling    1.55      CloseConnectionMessage* closeConnectionMessage 
245                            = (CloseConnectionMessage*)message;
246 mike          1.2  
247 h.sterling    1.55      for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
248                         {
249                            HTTPConnection* connection = _rep->connections[i];  
250 david.dillard 1.59         PEGASUS_SOCKET socket = connection->getSocket();
251 h.sterling    1.55 
252                            if (socket == closeConnectionMessage->socket)
253                            {
254                               _monitor->unsolicitSocketMessages(socket);
255                               _rep->connections.remove(i);
256                               delete connection;
257                               break;
258                            }
259                         }
260 mday          1.4        }
261                    
262                          default:
263 h.sterling    1.55      // ATTN: need unexpected message error!
264                         break;
265 mday          1.4     };
266                    
267                       delete message;
268                    }
269 mike          1.2  
270                    
271 mday          1.4  void HTTPConnector::handleEnqueue()
272                    {
273                    
274                       Message* message = dequeue();
275                    
276                       if (!message)
277                          return;
278 mike          1.2  
279 mday          1.4     handleEnqueue(message);
280 mike          1.2  }
281                    
282                    HTTPConnection* HTTPConnector::connect(
283 kumpf         1.24    const String& host, 
284                       const Uint32 portNumber,
285 kumpf         1.11    SSLContext * sslContext,
286 mday          1.4     MessageQueue* outputMessageQueue)
287 mike          1.2  {
288 david.dillard 1.58    PEGASUS_SOCKET socket;
289 kumpf         1.10 
290 h.sterling    1.55 #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
291 kumpf         1.24    if (host == String::EMPTY)
292 kumpf         1.10    {
293                          // Set up the domain socket for a local connection
294                    
295                          sockaddr_un address;
296                          address.sun_family = AF_UNIX;
297 kumpf         1.28       strcpy(address.sun_path, PEGASUS_LOCAL_DOMAIN_SOCKET_PATH);
298 chuck         1.41 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
299                          AtoE(address.sun_path);
300                    #endif
301 kumpf         1.10 
302                          socket = ::socket(AF_UNIX, SOCK_STREAM, 0);
303 david.dillard 1.58       if (socket == PEGASUS_INVALID_SOCKET)
304 kumpf         1.20          throw CannotCreateSocketException();
305 kumpf         1.10 
306                          // Connect the socket to the address:
307                    
308                          if (::connect(socket,
309                                        reinterpret_cast<sockaddr*>(&address),
310                                        sizeof(address)) < 0)
311                          {
312 h.sterling    1.55      
313                            //l10n
314 humberto      1.33          //throw CannotConnectException("Cannot connect to local CIM server. Connection failed.");
315                             MessageLoaderParms parms("Common.HTTPConnector.CONNECTION_FAILED_LOCAL_CIM_SERVER",
316 h.sterling    1.55                                   "Cannot connect to local CIM server. Connection failed.");
317 nag.boranna   1.54          Socket::close(socket);
318 humberto      1.33          throw CannotConnectException(parms);
319 kumpf         1.10       }
320                       }
321                       else
322                       {
323                    #endif
324                    
325 mday          1.4     // Make the internet address:
326 mike          1.2  
327 mday          1.4     sockaddr_in address;
328 mike          1.2  
329 kumpf         1.24    if (!_MakeAddress((const char*)host.getCString(), portNumber, address))
330 mday          1.4     {
331 kumpf         1.24       char portStr [32];
332                          sprintf (portStr, "%u", portNumber);
333 kumpf         1.27       throw InvalidLocatorException(host + ":" + portStr);
334 mday          1.4     }
335 mike          1.2  
336                    
337 mday          1.4     // Create the socket:
338 kumpf         1.10    socket = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
339 david.dillard 1.58    if (socket == PEGASUS_INVALID_SOCKET)
340 kumpf         1.20       throw CannotCreateSocketException();
341 mike          1.2  
342 mday          1.4     // Conect the socket to the address:
343 kumpf         1.10    if (::connect(socket,
344                                     reinterpret_cast<sockaddr*>(&address),
345                                     sizeof(address)) < 0)
346                       {
347 kumpf         1.24       char portStr [32];
348                          sprintf (portStr, "%u", portNumber);
349 humberto      1.33       //l10n
350                          //throw CannotConnectException("Cannot connect to " + host + ":" + portStr +". Connection failed.");
351                          MessageLoaderParms parms("Common.HTTPConnector.CONNECTION_FAILED_TO",
352 h.sterling    1.55                                "Cannot connect to $0:$1. Connection failed.",
353                                                   host,
354                                                   portStr);
355 nag.boranna   1.54       Socket::close(socket);
356 humberto      1.33       throw CannotConnectException(parms);
357 kumpf         1.10    }
358                    
359 h.sterling    1.55 #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
360 kumpf         1.10    }
361                    #endif
362 mike          1.2  
363 mday          1.4     // Create HTTPConnection object:
364 mike          1.2  
365 kumpf         1.57    AutoPtr<MP_Socket> mp_socket(new MP_Socket(socket, sslContext, 0, false));
366 mday          1.4     if (mp_socket->connect() < 0) {
367 kumpf         1.24       char portStr [32];
368                          sprintf (portStr, "%u", portNumber);
369 humberto      1.33       //l10n
370                          //throw CannotConnectException("Cannot connect to " + host + ":" + portStr +". Connection failed.");
371                          MessageLoaderParms parms("Common.HTTPConnector.CONNECTION_FAILED_TO",
372 h.sterling    1.55                                "Cannot connect to $0:$1. Connection failed.",
373                                                   host,
374                                                   portStr);
375 nag.boranna   1.54       mp_socket->close();
376 humberto      1.33       throw CannotConnectException(parms);
377 mday          1.4     }
378 mike          1.2      
379 mday          1.4     HTTPConnection* connection = new HTTPConnection(_monitor, mp_socket,
380 kumpf         1.48         this, static_cast<MessageQueueService *>(outputMessageQueue), false);
381 mike          1.2  
382 mday          1.4     // Solicit events on this new connection's socket:
383 mike          1.2  
384 mday          1.31    if (-1 == (_entry_index = _monitor->solicitSocketMessages(
385 h.sterling    1.55       connection->getSocket(),
386                          SocketMessage::READ | SocketMessage::EXCEPTION,
387                          connection->getQueueId(), Monitor::CONNECTOR)))
388 mday          1.31    {
389 a.arora       1.51       (connection->getMPSocket()).close();
390 mday          1.31    }
391 mike          1.2  
392 mday          1.4     // Save the socket for cleanup later:
393 a.arora       1.47 
394 mday          1.4     _rep->connections.append(connection);
395 mike          1.2  
396 mday          1.4     return connection;
397 mike          1.2  }
398                    
399                    void HTTPConnector::destroyConnections()
400                    {
401 mday          1.4     // For each connection created by this object:
402 mike          1.2  
403 mday          1.4     for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
404                       {
405 kumpf         1.9        _deleteConnection(_rep->connections[i]);
406 mday          1.4     }
407 mike          1.2  
408 mday          1.4     _rep->connections.clear();
409 mike          1.2  }
410                    
411 mday          1.32 
412 kumpf         1.7  void HTTPConnector::disconnect(HTTPConnection* currentConnection)
413                    {
414                        //
415                        // find and delete the specified connection
416                        //
417 denise.eckstein 1.56 
418                          Uint32 index = PEG_NOT_FOUND;
419 kumpf           1.7      for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++)
420                          {
421                              if (currentConnection == _rep->connections[i])
422                              {
423 denise.eckstein 1.56             index = i;
424                                  break;
425                              }
426                           }
427                      
428                          PEGASUS_ASSERT(index != PEG_NOT_FOUND);
429 tony            1.34 
430 david.dillard   1.59     PEGASUS_SOCKET socket = currentConnection->getSocket();
431 denise.eckstein 1.56     _monitor->unsolicitSocketMessages(socket);
432                          _rep->connections.remove(index);
433                          delete currentConnection;
434 kumpf           1.7  }
435 kumpf           1.9  
436                      void HTTPConnector::_deleteConnection(HTTPConnection* httpConnection)
437 dj.gorey        1.45 {
438 david.dillard   1.59     PEGASUS_SOCKET socket = httpConnection->getSocket();
439 dj.gorey        1.45 
440                          // Unsolicit SocketMessages:
441                      
442                          _monitor->unsolicitSocketMessages(socket);
443                      
444                          // Destroy the connection (causing it to close):
445                      
446                          delete httpConnection;
447                      }
448                      
449 mike            1.2  PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2