|
reSIProcate/repro
9694
|
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 */
1.7.5.1