reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
HttpBase.cxx
Go to the documentation of this file.
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include "rutil/ResipAssert.h"
6
7#include "rutil/Data.hxx"
8#include "rutil/Socket.hxx"
11#include "rutil/Logger.hxx"
12#include "resip/stack/Tuple.hxx"
13#include "rutil/DnsUtil.hxx"
14#include "rutil/ParseBuffer.hxx"
16
17#include "repro/HttpBase.hxx"
19#include "repro/WebAdmin.hxx"
21
22
23using namespace resip;
24using namespace repro;
25using namespace std;
26
27#define RESIPROCATE_SUBSYSTEM Subsystem::REPRO
28
29
31{
32#if defined(WIN32)
33 closesocket(mFd);
34#else
35 close(mFd);
36#endif
37 mFd=0;
38 for( int i=0; i<MaxConnections; i++)
39 {
40 if ( mConnection[i] )
41 {
42 delete mConnection[i] ; mConnection[i]=0;
43 }
44 }
45}
46
47
48HttpBase::HttpBase( int port, IpVersion ipVer, const Data& realm, const resip::Data& ipAddr ):
49 mRealm(realm),
50 nextConnection(0),
51 mTuple(ipAddr,port,ipVer,TCP,Data::Empty)
52{
53 // !rwm! [TODO] check that this works for IPv6
54 //assert( ipVer == V4 );
55
56 sane = true;
57
58 for ( int i=0 ; i<MaxConnections; i++)
59 {
60 mConnection[i]=0;
61 }
62
63#ifdef USE_IPV6
64 mFd = ::socket(ipVer == V4 ? PF_INET : PF_INET6, SOCK_STREAM, 0);
65#else
66 mFd = ::socket(PF_INET, SOCK_STREAM, 0);
67#endif
68
69 if ( mFd == INVALID_SOCKET )
70 {
71 int e = getErrno();
72 ErrLog (<< "Failed to create socket: " << strError(e));
73 sane = false;
74 return;
75 }
76
77 DebugLog (<< "Creating fd=" << (int)mFd
78 << (ipVer == V4 ? " V4/" : " V6/") );
79
80 int on = 1;
81#if !defined(WIN32)
82 if ( ::setsockopt ( mFd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) )
83#else
84 if ( ::setsockopt ( mFd, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) )
85#endif
86 {
87 int e = getErrno();
88 ErrLog (<< "Couldn't set sockoptions SO_REUSEPORT | SO_REUSEADDR: " << strError(e));
89 sane = false;
90 return;
91 }
92
93#ifdef USE_IPV6
94#ifdef __linux__
95 if (ipVer == V6)
96 {
97 if ( ::setsockopt(mFd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) )
98 {
99 int e = getErrno();
100 ErrLog(<< "HttpBase::HttpBase: Couldn't set sockoptions IPV6_V6ONLY: " << strError(e));
101 sane = false;
102 return;
103 }
104 }
105#endif
106#endif
107
108 DebugLog (<< "Binding to " << Tuple::inet_ntop(mTuple));
109
110 if ( ::bind( mFd, &mTuple.getMutableSockaddr(), mTuple.length()) == SOCKET_ERROR )
111 {
112 int e = getErrno();
113 if ( e == EADDRINUSE )
114 {
115 ErrLog (<< mTuple << " already in use ");
116 }
117 else
118 {
119 ErrLog (<< "Could not bind to " << mTuple);
120 }
121 sane = false;
122 return;
123 }
124
125 bool ok = makeSocketNonBlocking(mFd);
126 if ( !ok )
127 {
128 ErrLog (<< "Could not make HTTP socket non-blocking " << port );
129 sane = false;
130 return;
131 }
132
133 // do the listen, seting the maximum queue size for compeletly established
134 // sockets -- on linux, tcp_max_syn_backlog should be used for the incomplete
135 // queue size(see man listen)
136 int e = listen(mFd,5 );
137
138 if (e != 0 )
139 {
140 int e = getErrno();
141 InfoLog (<< "Failed listen " << strError(e));
142 sane = false;
143 return;
144 }
145}
146
147
148void
150{
151 fdset.setRead( mFd );
152
153 for( int i=0; i<MaxConnections; i++)
154 {
155 if ( mConnection[i] )
156 {
157 mConnection[i]->buildFdSet(fdset);
158 }
159 }
160}
161
162
163void
165{
166 if (fdset.readyToRead(mFd))
167 {
168 Tuple tuple(mTuple);
169 struct sockaddr& peer = tuple.getMutableSockaddr();
170 socklen_t peerLen = tuple.length();
171 Socket sock = accept( mFd, &peer, &peerLen);
172 if ( sock == SOCKET_ERROR )
173 {
174 int e = getErrno();
175 switch (e)
176 {
177 case EAGAIN:
178#if EAGAIN != EWOULDBLOCK
179 case EWOULDBLOCK: // Treat EGAIN and EWOULDBLOCK as the same: http://stackoverflow.com/questions/7003234/which-systems-define-eagain-and-ewouldblock-as-different-values
180#endif
181 // !jf! this can not be ready in some cases
182 return;
183 default:
184 ErrLog(<< "Some error reading from socket: " << e);
185 // .bwc. This is almost certainly a bad assert that a nefarious
186 // endpoint could hit.
187 // assert(0); // Transport::error(e);
188 }
189 return;
190 }
192
193 int c = nextConnection;
194 nextConnection = ( nextConnection+1 ) % MaxConnections;
195
196 if ( mConnection[c] )
197 {
198 delete mConnection[c]; mConnection[c] = 0;
199 }
200
201 mConnection[c] = new HttpConnection(*this,sock);
202
203 DebugLog (<< "Received TCP connection as connection=" << c << " fd=" << (int)sock);
204 }
205
206 for( int i=0; i<MaxConnections; i++)
207 {
208 if ( mConnection[i] )
209 {
210 bool ok = mConnection[i]->process(fdset);
211 if ( !ok )
212 {
213 delete mConnection[i]; mConnection[i]=0;
214 }
215 }
216 }
217}
218
219
220void HttpBase::setPage( const Data& page, int pageNumber, int response, const Mime& type )
221{
222 if(pageNumber < 0)
223 {
224 return;
225 }
226
227 for ( int i=0 ; i<MaxConnections; i++)
228 {
229 if ( mConnection[i] )
230 {
231 if ( mConnection[i]->mPageNumber == pageNumber )
232 {
233 mConnection[i]->setPage( page,response,type );
234 }
235 }
236 }
237}
238
240{
241 return sane;
242}
243
244/* ====================================================================
245 * The Vovida Software License, Version 1.0
246 *
247 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
248 *
249 * Redistribution and use in source and binary forms, with or without
250 * modification, are permitted provided that the following conditions
251 * are met:
252 *
253 * 1. Redistributions of source code must retain the above copyright
254 * notice, this list of conditions and the following disclaimer.
255 *
256 * 2. Redistributions in binary form must reproduce the above copyright
257 * notice, this list of conditions and the following disclaimer in
258 * the documentation and/or other materials provided with the
259 * distribution.
260 *
261 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
262 * and "Vovida Open Communication Application Library (VOCAL)" must
263 * not be used to endorse or promote products derived from this
264 * software without prior written permission. For written
265 * permission, please contact vocal@vovida.org.
266 *
267 * 4. Products derived from this software may not be called "VOCAL", nor
268 * may "VOCAL" appear in their name, without prior written
269 * permission of Vovida Networks, Inc.
270 *
271 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
272 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
273 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
274 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
275 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
276 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
277 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
278 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
279 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
280 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
281 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
282 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
283 * DAMAGE.
284 *
285 * ====================================================================
286 *
287 * This software consists of voluntary contributions made by Vovida
288 * Networks, Inc. and many individuals on behalf of Vovida Networks,
289 * Inc. For more information on Vovida Networks, Inc., please see
290 * <http://www.vovida.org/>.
291 *
292 */
#define DebugLog(args_)
Definition Logger.hxx:128
#define InfoLog(args_)
Definition Logger.hxx:131
#define ErrLog(args_)
Definition Logger.hxx:137
Handles cross-platform sockets compatibility.
#define INVALID_SOCKET
Definition Socket.hxx:95
#define SOCKET_ERROR
Definition Socket.hxx:96
static int getErrno()
int Socket
void setPage(const resip::Data &page, int pageNumber, int response=200, const resip::Mime &pType=resip::Mime("text","html"))
Definition HttpBase.cxx:220
HttpBase(int port, resip::IpVersion version, const resip::Data &realm, const resip::Data &ipAddr=resip::Data::Empty)
Definition HttpBase.cxx:48
void buildFdSet(resip::FdSet &fdset)
Definition HttpBase.cxx:149
friend class HttpConnection
Definition HttpBase.hxx:16
virtual ~HttpBase()
Definition HttpBase.cxx:30
void process(resip::FdSet &fdset)
Definition HttpBase.cxx:164
bool process(resip::FdSet &fdset)
void buildFdSet(resip::FdSet &fdset)
void setPage(const resip::Data &page, int response, const resip::Mime &pType)
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
Object-oriented wrapper for your platform's file-descriptor set.
Definition Socket.hxx:162
bool readyToRead(Socket fd)
Definition Socket.hxx:189
void setRead(Socket fd)
Definition Socket.hxx:204
Represents the "media-type" element in the RFC 3261 grammar.
Definition Mime.hxx:20
Represents a network address.
Definition Tuple.hxx:59
sockaddr & getMutableSockaddr()
Retrieve the binary representation of the socket address for this tuple.
Definition Tuple.hxx:113
socklen_t length() const
Definition Tuple.cxx:655
static Data inet_ntop(const Tuple &tuple)
Converts the binary socket address to presentation format, via the DnsUtil::inet_ntop() method.
Definition Tuple.cxx:939
This Class is used to implement a primitive form of RPC using loose XML formatting.
dcm! – add UnusedChecking(_enum) below;
std::string strError(int err)
Definition compat.hxx:274
IpVersion
An enumeration of IP versions.
bool makeSocketNonBlocking(Socket fd)
Definition Socket.cxx:21