SocketHTTPProxy.cc

Go to the documentation of this file.
00001 // ----------------------------------------------------------------------------
00002 // CERTI - HLA RunTime Infrastructure
00003 // Copyright (C) 2002-2005  ONERA
00004 //
00005 // This program is free software ; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public License
00007 // as published by the Free Software Foundation ; either version 2 of
00008 // the License, or (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful, but
00011 // WITHOUT ANY WARRANTY ; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00013 // Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this program ; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00018 // USA
00019 //
00020 // $Id: SocketHTTPProxy.cc,v 3.3 2008/10/27 10:26:49 erk Exp $
00021 // ----------------------------------------------------------------------------
00022 
00023 #include "SocketHTTPProxy.hh"
00024 #include "PrettyDebug.hh"
00025 
00026 #include <cstdlib>
00027 #include <cstring>
00028 #include <cerrno>
00029 
00030 namespace certi {
00031 
00032 static PrettyDebug D("SOCKHTTP", "(SocketHTTPProxy) - ");
00033 static PrettyDebug G("GENDOC",__FILE__);
00034 
00094 // ----------------------------------------------------------------------------
00095 SocketHTTPProxy::SocketHTTPProxy() : SocketTCP()
00096 {
00097 }
00098 
00099 // ----------------------------------------------------------------------------
00100 SocketHTTPProxy::~SocketHTTPProxy()
00101 {
00102 }
00103 
00104 // ----------------------------------------------------------------------------
00105 void
00106 SocketHTTPProxy::createConnection(const char *server_name, unsigned int port)
00107     throw (NetworkError)
00108 {
00109     const char *http_proxy;
00110     // check if proxy is requested
00111     http_proxy = getenv("CERTI_HTTP_PROXY");
00112     if (http_proxy == NULL)
00113         http_proxy = getenv("http_proxy"); // global settings
00114 
00115     if (http_proxy != NULL) {
00116         std::string proxy_address;
00117         in_port_t proxy_port;
00118 
00119         const char *strpport = strchr(http_proxy, ':');
00120         if (strpport) {
00121             proxy_address.assign(http_proxy, strpport-http_proxy);
00122             proxy_port = atoi(strpport+1);
00123         }
00124         else {
00125             proxy_address.assign(http_proxy);
00126             proxy_port = 3128;
00127         }
00128 
00129         D.Out(pdTrace, "Connect to '%s:%d' via 'http://%s:%d'.",
00130             server_name, port, proxy_address.c_str(), proxy_port);
00131         SocketTCP::createConnection(proxy_address.c_str(), proxy_port);
00132         sendHTTPConnect(server_name, port);
00133     }
00134     else {
00135         D.Out(pdTrace, "Connect to '%s:%d'.", server_name, port);
00136         SocketTCP::createConnection(server_name, port);
00137     }
00138 }
00139 
00140 // ----------------------------------------------------------------------------
00141 int SocketHTTPProxy::sendHTTPConnect(const char* addr, in_port_t port)
00142 {
00143     std::stringstream request;
00144     // build the HTTP request
00145     request
00146         << "CONNECT " << addr << ":" << port << " HTTP/1.0\x0D\x0A"
00147         << "Host: " << addr << ":" << port << "\x0D\x0A"
00148         << "\x0D\x0A";
00149 
00150     D.Out(pdTrace, "HTTP proxy connection request\n%s<",
00151         request.str().c_str());
00152     // send the HTTP reuqest
00153     send((const unsigned char*)request.str().c_str(), request.str().length());
00154 
00155     size_t received;
00156     static const size_t maxLineLength = 1024;
00157     char response[maxLineLength];
00158 
00159     // wait for the HTTP response
00160     timeoutTCP(5,0);
00161     // receive the HTTP response line
00162     received = receiveLine(response, maxLineLength);
00163     D.Out(pdTrace, "<HTTP PROXY> %s", response);
00164 
00165     char* sCode;
00166     // the response line must be "HTTP/<version> <code> <reason>"
00167     if (received < 5 || strncmp(response,"HTTP/",5) != 0 ||
00168         (sCode = strchr(response, ' ')) == NULL) {
00169         D.Out(pdDebug, "Unexpected HTTP response.");
00170         throw NetworkError("Unexpected HTTP response.");
00171     }
00172 
00173     int iCode = atoi(sCode);
00174     // the response code must be 2xx
00175     if (iCode < 200 || iCode >= 300) {
00176         std::stringstream msg;
00177         msg << "Proxy connection refused: " << response;
00178         D.Out(pdDebug, "%s", msg.str().c_str());
00179         throw NetworkError(msg.str().c_str());
00180     }
00181 
00182     // receive the rest of the HTTP response
00183     // we wait for an empty line
00184     do {
00185         timeoutTCP(5,0);
00186         // receive the HTTP header
00187         received = receiveLine(response, maxLineLength);
00188         D.Out(pdTrace, "<HTTP PROXY> %s", response);
00189     }
00190     while (received > 0);
00191 
00192     return 1;
00193 }
00194 
00195 // ----------------------------------------------------------------------------
00196 size_t
00197 SocketHTTPProxy::receiveLine(char *buffer, size_t max_size)
00198     throw (NetworkError, NetworkSignal)
00199 {
00200     size_t nReceived = 0;
00201     while (nReceived < max_size-1)
00202     {
00203         int result = ::recv(SocketTCP::returnSocket(), buffer+nReceived, 1, 0);
00204         if (result < 0)
00205         {
00206             D.Out(pdExcept, "Error while receiving on TCP socket.");
00207 #ifdef _WIN32
00208             if (WSAGetLastError() == WSAEINTR)
00209 #else
00210             if (errno == EINTR)
00211 #endif
00212                 throw NetworkSignal("");
00213             else {
00214                 perror("TCP Socket(RecevoirTCP) ");
00215                 throw NetworkError("Error while receiving TCP message.");
00216             }
00217         }
00218         else if (result == 0)   {
00219             D.Out(pdExcept, "TCP connection has been closed by peer.");
00220             throw NetworkError("Connection closed by client.");
00221         }
00222 
00223         nReceived += result;
00224         // update statistics
00225         RcvdBytesCount += result;
00226 
00227         if (buffer[nReceived-1] == '\x0A') {
00228             // strip trailing CRLF and terminate the received string
00229             if(nReceived > 1 && buffer[nReceived-2] == '\x0D') {
00230                 buffer[nReceived-2] = 0;
00231                 return nReceived-2;
00232             }
00233             else {
00234                 buffer[nReceived-1] = 0;
00235                 return nReceived-1;
00236             }
00237         }
00238     }
00239 
00240     throw NetworkError("Too large HTTP response received.");
00241 }
00242 
00243 } // namespace
00244 
00245 // $Id: SocketHTTPProxy.cc,v 3.3 2008/10/27 10:26:49 erk Exp $

Generated on Thu Apr 30 15:53:50 2009 for CERTIDeveloperDocumentation by doxygen 1.5.5