# 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 $