reSIProcate/repro  9694
HttpBase.cxx
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include "config.h"
00003 #endif
00004 
00005 #include <cassert>
00006 
00007 #include "rutil/Data.hxx"
00008 #include "rutil/Socket.hxx"
00009 #include "resip/stack/Symbols.hxx"
00010 #include "rutil/TransportType.hxx"
00011 #include "rutil/Logger.hxx"
00012 #include "resip/stack/Tuple.hxx"
00013 #include "rutil/DnsUtil.hxx"
00014 #include "rutil/ParseBuffer.hxx"
00015 #include "resip/stack/Transport.hxx"
00016 
00017 #include "repro/HttpBase.hxx"
00018 #include "repro/HttpConnection.hxx"
00019 #include "repro/WebAdmin.hxx"
00020 #include "rutil/WinLeakCheck.hxx"
00021 
00022 
00023 using namespace resip;
00024 using namespace repro;
00025 using namespace std;
00026 
00027 #define RESIPROCATE_SUBSYSTEM Subsystem::REPRO
00028 
00029 
00030 HttpBase::~HttpBase()
00031 {
00032 #if defined(WIN32)
00033    closesocket(mFd);
00034 #else
00035    close(mFd); 
00036 #endif
00037    mFd=0;
00038    for( int i=0; i<MaxConnections; i++)
00039    {
00040       if ( mConnection[i] )
00041       {
00042          delete mConnection[i] ; mConnection[i]=0;
00043       }
00044    }
00045 }
00046 
00047 
00048 HttpBase::HttpBase( int port, IpVersion ipVer, const Data& realm ):
00049    mRealm(realm),
00050    nextConnection(0),
00051    mTuple(Data::Empty,port,ipVer,TCP,Data::Empty)
00052 {
00053    // !rwm! [TODO] check that this works for IPv6   
00054    //assert( ipVer == V4 );
00055 
00056    sane = true;
00057    
00058    for ( int i=0 ; i<MaxConnections; i++)
00059    {
00060       mConnection[i]=0;
00061    }
00062    
00063 #ifdef USE_IPV6
00064    mFd = ::socket(ipVer == V4 ? PF_INET : PF_INET6, SOCK_STREAM, 0);
00065 #else
00066    mFd = ::socket(PF_INET, SOCK_STREAM, 0);
00067 #endif
00068    
00069    if ( mFd == INVALID_SOCKET )
00070    {
00071       int e = getErrno();
00072       ErrLog (<< "Failed to create socket: " << strerror(e));
00073       sane = false;
00074       return;
00075    }
00076 
00077    DebugLog (<< "Creating fd=" << (int)mFd 
00078              << (ipVer == V4 ? " V4/" : " V6/") );
00079       
00080    int on = 1;
00081 #if !defined(WIN32)
00082    if ( ::setsockopt ( mFd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) )
00083 #else
00084    if ( ::setsockopt ( mFd, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) )
00085 #endif
00086    {
00087       int e = getErrno();
00088       ErrLog (<< "Couldn't set sockoptions SO_REUSEPORT | SO_REUSEADDR: " << strerror(e));
00089       sane = false;
00090       return;
00091    }
00092    
00093    DebugLog (<< "Binding to " << Tuple::inet_ntop(mTuple));
00094    
00095    if ( ::bind( mFd, &mTuple.getMutableSockaddr(), mTuple.length()) == SOCKET_ERROR )
00096    {
00097       int e = getErrno();
00098       if ( e == EADDRINUSE )
00099       {
00100          ErrLog (<< mTuple << " already in use ");
00101       }
00102       else
00103       {
00104          ErrLog (<< "Could not bind to " << mTuple);
00105       }
00106       sane = false;
00107       return;
00108    }
00109    
00110    bool ok = makeSocketNonBlocking(mFd);
00111    if ( !ok )
00112    {
00113       ErrLog (<< "Could not make HTTP socket non-blocking " << port );
00114       sane = false;
00115       return;
00116    }
00117    
00118    // do the listen, seting the maximum queue size for compeletly established
00119    // sockets -- on linux, tcp_max_syn_backlog should be used for the incomplete
00120    // queue size(see man listen)
00121    int e = listen(mFd,5 );
00122 
00123    if (e != 0 )
00124    {
00125       int e = getErrno();
00126       InfoLog (<< "Failed listen " << strerror(e));
00127       sane = false;
00128       return;
00129    }
00130 }
00131 
00132 
00133 void 
00134 HttpBase::buildFdSet(FdSet& fdset)
00135 { 
00136    fdset.setRead( mFd );
00137    
00138    for( int i=0; i<MaxConnections; i++)
00139    {
00140       if ( mConnection[i] )
00141       {
00142          mConnection[i]->buildFdSet(fdset);
00143       }
00144    }
00145 }
00146 
00147 
00148 void 
00149 HttpBase::process(FdSet& fdset)
00150 {
00151    if (fdset.readyToRead(mFd))
00152    {
00153       Tuple tuple(mTuple);
00154       struct sockaddr& peer = tuple.getMutableSockaddr();
00155       socklen_t peerLen = tuple.length();
00156       Socket sock = accept( mFd, &peer, &peerLen);
00157       if ( sock == SOCKET_ERROR )
00158       {
00159          int e = getErrno();
00160          switch (e)
00161          {
00162             case EWOULDBLOCK:
00163                // !jf! this can not be ready in some cases 
00164                return;
00165             default:
00166                ErrLog(<< "Some error reading from socket: " << e);
00167                // .bwc. This is almost certainly a bad assert that a nefarious
00168                // endpoint could hit.
00169                // assert(0); // Transport::error(e);
00170          }
00171          return;
00172       }
00173       makeSocketNonBlocking(sock);
00174       
00175       int c = nextConnection;
00176       nextConnection = ( nextConnection+1 ) % MaxConnections;
00177       
00178       if ( mConnection[c] )
00179       {
00180          delete mConnection[c]; mConnection[c] = 0;
00181       }
00182       
00183       mConnection[c] = new HttpConnection(*this,sock);
00184       
00185       DebugLog (<< "Received TCP connection as connection=" << c << " fd=" << (int)sock);
00186    }
00187     
00188    for( int i=0; i<MaxConnections; i++)
00189    {
00190       if ( mConnection[i] )
00191       {
00192          bool ok = mConnection[i]->process(fdset);
00193          if ( !ok )
00194          {
00195             delete mConnection[i]; mConnection[i]=0;
00196          }
00197       }
00198    }
00199 }
00200 
00201 
00202 void HttpBase::setPage( const Data& page, int pageNumber, int response, const Mime& type )
00203 {
00204    for ( int i=0 ; i<MaxConnections; i++)
00205    {
00206       if ( mConnection[i] )
00207       {
00208          if ( mConnection[i]->mPageNumber == pageNumber )
00209          {
00210             mConnection[i]->setPage( page,response,type );
00211          }
00212       }
00213    }
00214 }
00215 
00216 bool HttpBase::isSane()
00217 {
00218   return sane;
00219 }
00220 
00221 /* ====================================================================
00222  * The Vovida Software License, Version 1.0 
00223  * 
00224  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00225  * 
00226  * Redistribution and use in source and binary forms, with or without
00227  * modification, are permitted provided that the following conditions
00228  * are met:
00229  * 
00230  * 1. Redistributions of source code must retain the above copyright
00231  *    notice, this list of conditions and the following disclaimer.
00232  * 
00233  * 2. Redistributions in binary form must reproduce the above copyright
00234  *    notice, this list of conditions and the following disclaimer in
00235  *    the documentation and/or other materials provided with the
00236  *    distribution.
00237  * 
00238  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00239  *    and "Vovida Open Communication Application Library (VOCAL)" must
00240  *    not be used to endorse or promote products derived from this
00241  *    software without prior written permission. For written
00242  *    permission, please contact vocal@vovida.org.
00243  *
00244  * 4. Products derived from this software may not be called "VOCAL", nor
00245  *    may "VOCAL" appear in their name, without prior written
00246  *    permission of Vovida Networks, Inc.
00247  * 
00248  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00249  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00250  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00251  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00252  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00253  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00254  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00255  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00256  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00257  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00258  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00259  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00260  * DAMAGE.
00261  * 
00262  * ====================================================================
00263  * 
00264  * This software consists of voluntary contributions made by Vovida
00265  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00266  * Inc.  For more information on Vovida Networks, Inc., please see
00267  * <http://www.vovida.org/>.
00268  *
00269  */