reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
HttpConnection.cxx
Go to the documentation of this file.
1#include "rutil/ResipAssert.h"
2
3#include <rutil/Data.hxx>
4#include <rutil/Socket.hxx>
7#include <rutil/Logger.hxx>
9#include <rutil/DnsUtil.hxx>
10#include <rutil/ParseBuffer.hxx>
11
12#include "AppSubsystem.hxx"
13#include "HttpBase.hxx"
14#include "HttpConnection.hxx"
15
16using namespace resip;
17using namespace mohparkserver;
18using namespace std;
19
20#define RESIPROCATE_SUBSYSTEM AppSubsystem::MOHPARKSERVER
21
22int HttpConnection::nextPageNumber=1;
23
24
26 mHttpBase( base ),
27 mPageNumber(nextPageNumber++),
28 mSock(pSock),
29 mParsedRequest(false)
30{
31 resip_assert( mSock > 0 );
32}
33
34
36{
37 resip_assert( mSock > 0 );
38#ifdef WIN32
39 closesocket(mSock); mSock=0;
40#else
41 close(mSock); mSock=0;
42#endif
43}
44
45
46void
48{
49 if ( !mTxBuffer.empty() )
50 {
51 fdset.setWrite(mSock);
52 }
53 fdset.setRead(mSock);
54}
55
56
57bool
59{
60 if ( fdset.hasException(mSock) )
61 {
62 int errNum = 0;
63 int errNumSize = sizeof(errNum);
64 getsockopt(mSock,SOL_SOCKET,SO_ERROR,(char *)&errNum,(socklen_t *)&errNumSize);
65 InfoLog (<< "Exception reading from socket "
66 << (int)mSock << " code: " << errNum << "; closing connection");
67 return false;
68 }
69
70 if ( fdset.readyToRead( mSock ) )
71 {
72 bool ok = processSomeReads();
73 if ( !ok )
74 {
75 return false;
76 }
77 }
78 if ( (!mTxBuffer.empty()) && fdset.readyToWrite( mSock ) )
79 {
80 bool ok = processSomeWrites();
81 if ( !ok )
82 {
83 return false;
84 }
85 }
86
87 return true;
88}
89
90
91void
92HttpConnection::setPage(const Data& pPage,int response,const Mime& pType)
93{
94 Data page(pPage);
95
96 switch (response)
97 {
98 case 401:
99 {
100 mTxBuffer += "HTTP/1.0 401 Unauthorized"; mTxBuffer += Symbols::CRLF;
101
102 page = ("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">"
103 "<html><head>"
104 "<title>401 Unauthorized</title>"
105 "</head><body>"
106 "<h1>Unauthorized</h1>"
107 "</body></html>" );
108 }
109 break;
110
111 case 404:
112 {
113 mTxBuffer += "HTTP/1.0 404 Not Found"; mTxBuffer += Symbols::CRLF;
114
115 page = ("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">"
116 "<html><head>"
117 "<title>404 Not Found</title>"
118 "</head><body>"
119 "<h1>Unauthorized</h1>"
120 "</body></html>" );
121 }
122 break;
123
124 case 301:
125 {
126 mTxBuffer += "HTTP/1.0 301 Moved Permanently"; mTxBuffer += Symbols::CRLF;
127 mTxBuffer += "Location: http:/activecalls.html"; mTxBuffer += Symbols::CRLF;
128
129 page = ("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">"
130 "<html><head>"
131 "<title>301 Moved Permanently</title>"
132 "</head><body>"
133 "<h1>Moved</h1>"
134 "</body></html>" );
135 }
136 break;
137
138 case 200:
139 {
140 mTxBuffer += "HTTP/1.0 200 OK" ; mTxBuffer += Symbols::CRLF;
141 }
142 break;
143
144 default:
145 {
146 resip_assert(0);
147
148 Data resp;
149 {
150 DataStream s(resp);
151 s << response;
152 s.flush();
153 }
154
155 mTxBuffer += "HTTP/1.0 ";
156 mTxBuffer += resp;
157 mTxBuffer += "OK" ; mTxBuffer += Symbols::CRLF;
158 }
159 break;
160 }
161
162 Data len;
163 {
164 DataStream s(len);
165 s << page.size();
166 s.flush();
167 }
168
169 mTxBuffer += "WWW-Authenticate: Basic realm=\"";
170 if ( mHttpBase.mRealm.empty() )
171 {
173 }
174 else
175 {
176 mTxBuffer += mHttpBase.mRealm;
177 }
178 mTxBuffer += "\" ";
179 mTxBuffer += Symbols::CRLF;
180
181 mTxBuffer += "Server: Console RFSS " ;
182// mTxBuffer += Data(VersionUtils::instance().displayVersion());
183 mTxBuffer += Symbols::CRLF;
184 mTxBuffer += "Mime-version: 1.0 " ; mTxBuffer += Symbols::CRLF;
185 mTxBuffer += "Pragma: no-cache " ; mTxBuffer += Symbols::CRLF;
186 mTxBuffer += "Content-Length: "; mTxBuffer += len; mTxBuffer += Symbols::CRLF;
187
188 mTxBuffer += "Content-Type: " ;
189 mTxBuffer += pType.type() ;
190 mTxBuffer +="/" ;
191 mTxBuffer += pType.subType() ; mTxBuffer += Symbols::CRLF;
192
193 mTxBuffer += Symbols::CRLF;
194
195 mTxBuffer += page;
196}
197
198
199bool
200HttpConnection::processSomeReads()
201{
202 const int bufSize = 8000;
203 char buf[bufSize];
204
205
206#if defined(WIN32)
207 int bytesRead = ::recv(mSock, buf, bufSize, 0);
208#else
209 int bytesRead = ::read(mSock, buf, bufSize);
210#endif
211
212 if (bytesRead == INVALID_SOCKET)
213 {
214 int e = getErrno();
215 switch (e)
216 {
217 case EAGAIN:
218 InfoLog (<< "No data ready to read");
219 return true;
220 case EINTR:
221 InfoLog (<< "The call was interrupted by a signal before any data was read.");
222 break;
223 case EIO:
224 InfoLog (<< "I/O error");
225 break;
226 case EBADF:
227 InfoLog (<< "fd is not a valid file descriptor or is not open for reading.");
228 break;
229 case EINVAL:
230 InfoLog (<< "fd is attached to an object which is unsuitable for reading.");
231 break;
232 case EFAULT:
233 InfoLog (<< "buf is outside your accessible address space.");
234 break;
235 default:
236 InfoLog (<< "Some other error");
237 break;
238 }
239 InfoLog (<< "Failed read on " << (int)mSock << " " << strerror(e));
240 return false;
241 }
242 else if (bytesRead == 0)
243 {
244 InfoLog (<< "Connection closed by remote " );
245 return false;
246 }
247
248 //DebugLog (<< "HttpConnection::processSomeReads() "
249 // << " read=" << bytesRead);
250
251 mRxBuffer += Data( buf, bytesRead );
252
253 tryParse();
254
255 return true;
256}
257
258
259void
260HttpConnection::tryParse()
261{
262 //DebugLog (<< "parse " << mRxBuffer );
263
264 ParseBuffer pb(mRxBuffer);
265
266 pb.skipToChar(Symbols::SPACE[0]);
267 const char* start = pb.skipWhitespace();
268 pb.skipToChar(Symbols::SPACE[0]);
269
270 if (pb.eof())
271 {
272 // parse failed - just return
273 return;
274 }
275
276 Data uri;
277 pb.data( uri, start );
278
279 DebugLog (<< "parse found URI " << uri );
280 mParsedRequest = true;
281
282
283 Data user;
284 Data password;
285
286 try
287 {
288 pb.skipToChars( "Authorization" );
289 if ( !pb.eof() )
290 {
291 if ( pb.eof() ) DebugLog( << "Did not find Authorization header" );
292 pb.skipToChars( "Basic" ); pb.skipN(6);
293 if ( pb.eof() ) DebugLog( << "Did not find Authorization basic " );
294 pb.skipWhitespace();
295 if ( pb.eof() ) DebugLog( << "Something weird in Auhtorization header " );
296 if ( !pb.eof() )
297 {
298 const char* a = pb.position();
299 pb.skipNonWhitespace();
300 Data buf = pb.data(a);
301
302 DebugLog (<< "parse found basic base64 auth data of " << buf );
303 Data auth = buf.base64decode();
304
305 //DebugLog (<< "parse found basic auth data of " << auth );
306
307 ParseBuffer p(auth);
308 const char* a1 = p.position();
309 p.skipToChar(':');
310 user = p.data(a1);
311 const char* a2 = p.skipChar(':');
312 p.skipToEnd();
313 password = p.data(a2);
314
315 //DebugLog (<< "parse found basic auth data with user=" << user
316 // << " password=" << password );
317 }
318 }
319 }
320 catch ( ... )
321 {
322 ErrLog (<< "Some problem finding Authorization header in HTTP request" );
323 }
324
325 mHttpBase.buildPage(uri,mPageNumber,user,password);
326}
327
328
329bool
330HttpConnection::processSomeWrites()
331{
332 if ( mTxBuffer.empty() )
333 {
334 return true;
335 }
336
337 //DebugLog (<< "Writing " << mTxBuffer );
338
339#if defined(WIN32)
340 int bytesWritten = ::send( mSock, mTxBuffer.data(), (int)mTxBuffer.size(), 0);
341#else
342 int bytesWritten = ::write(mSock, mTxBuffer.data(), mTxBuffer.size() );
343#endif
344
345 if (bytesWritten == INVALID_SOCKET)
346 {
347 int e = getErrno();
348 InfoLog (<< "HttpConnection failed write on " << mSock << " " << strerror(e));
349
350 return false;
351 }
352
353 if (bytesWritten == (int)mTxBuffer.size() )
354 {
355 DebugLog (<< "Wrote it all" );
356 mTxBuffer = Data::Empty;
357
358 return false; // return false causes connection to close and clean up
359 }
360 else
361 {
362 Data rest = mTxBuffer.substr(bytesWritten);
363 mTxBuffer = rest;
364 DebugLog( << "Wrote " << bytesWritten << " bytes - still need to do " << mTxBuffer );
365 }
366
367 return true;
368}
369
370
371/* ====================================================================
372 * The Vovida Software License, Version 1.0
373 *
374 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
375 *
376 * Redistribution and use in source and binary forms, with or without
377 * modification, are permitted provided that the following conditions
378 * are met:
379 *
380 * 1. Redistributions of source code must retain the above copyright
381 * notice, this list of conditions and the following disclaimer.
382 *
383 * 2. Redistributions in binary form must reproduce the above copyright
384 * notice, this list of conditions and the following disclaimer in
385 * the documentation and/or other materials provided with the
386 * distribution.
387 *
388 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
389 * and "Vovida Open Communication Application Library (VOCAL)" must
390 * not be used to endorse or promote products derived from this
391 * software without prior written permission. For written
392 * permission, please contact vocal@vovida.org.
393 *
394 * 4. Products derived from this software may not be called "VOCAL", nor
395 * may "VOCAL" appear in their name, without prior written
396 * permission of Vovida Networks, Inc.
397 *
398 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
399 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
400 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
401 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
402 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
403 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
404 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
405 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
406 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
407 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
408 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
409 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
410 * DAMAGE.
411 *
412 * ====================================================================
413 *
414 * This software consists of voluntary contributions made by Vovida
415 * Networks, Inc. and many individuals on behalf of Vovida Networks,
416 * Inc. For more information on Vovida Networks, Inc., please see
417 * <http://www.vovida.org/>.
418 *
419 */
#define DebugLog(args_)
Definition Logger.hxx:128
#define InfoLog(args_)
Definition Logger.hxx:131
#define ErrLog(args_)
Definition Logger.hxx:137
#define resip_assert(x)
This file needs to work for both C and C++ code.
Handles cross-platform sockets compatibility.
#define INVALID_SOCKET
Definition Socket.hxx:95
static int getErrno()
int Socket
virtual void buildPage(const resip::Data &uri, int pageNumber, const resip::Data &user, const resip::Data &password)=0
const resip::Data mRealm
Definition HttpBase.hxx:37
bool process(resip::FdSet &fdset)
void buildFdSet(resip::FdSet &fdset)
HttpConnection(HttpBase &webAdmin, resip::Socket pSock)
void setPage(const resip::Data &page, int response, const resip::Mime &pType)
An iostream that operates on an existing Data.
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
Data base64decode() const
Performs RFC 3548 Base 64 decoding of the contents of this data.
Definition Data.cxx:2607
static const Data Empty
Constant that represents a zero-length data.
Definition Data.hxx:882
Data substr(size_type first, size_type count=Data::npos) const
Copies a portion of this Data into a new Data.
Definition Data.cxx:1932
bool empty() const noexcept
Checks whether the Data is empty.
Definition Data.hxx:591
size_type size() const noexcept
Returns the number of bytes in this Data.
Definition Data.hxx:599
const char * data() const noexcept
Returns a pointer to the contents of this Data.
Definition Data.hxx:608
static const Data & getLocalHostName()
Definition DnsUtil.cxx:118
Object-oriented wrapper for your platform's file-descriptor set.
Definition Socket.hxx:162
bool readyToWrite(Socket fd)
Definition Socket.hxx:194
bool readyToRead(Socket fd)
Definition Socket.hxx:189
void setRead(Socket fd)
Definition Socket.hxx:204
bool hasException(Socket fd)
Definition Socket.hxx:199
void setWrite(Socket fd)
Definition Socket.hxx:216
Represents the "media-type" element in the RFC 3261 grammar.
Definition Mime.hxx:20
const Data & subType() const
Definition Mime.cxx:100
const Data & type() const
Definition Mime.cxx:94
Provides string-parsing functionality with protection from buffer overflow.
static const char * SPACE
Definition Symbols.hxx:34
static const char * CRLF
Definition Symbols.hxx:21
dcm! – add UnusedChecking(_enum) below;