delete files with GPL License + modify build scripts

This commit is contained in:
Rohit Gupta
2016-10-07 18:19:43 +02:00
parent 73aa265793
commit 4787c975ec
177 changed files with 28 additions and 44955 deletions
+1 -2
View File
@@ -880,6 +880,7 @@ set(UTIL_SRC
${OPENAIR2_DIR}/UTIL/OMG/omg_hashtable.c
${OPENAIR2_DIR}/UTIL/OMG/rwalk.c
${OPENAIR2_DIR}/UTIL/OMG/rwp.c
${OPENAIR2_DIR}/UTIL/OMG/sumo.c
${OPENAIR2_DIR}/UTIL/OMG/socket_traci_OMG.c
${OPENAIR2_DIR}/UTIL/OMG/static.c
${OPENAIR2_DIR}/UTIL/OMG/steadystaterwp.c
@@ -1797,7 +1798,6 @@ add_executable(oaisim_nos1
${OPENAIR_TARGETS}/SIMU/USER/oaisim.c
${OPENAIR2_DIR}/RRC/NAS/nas_config.c
${OPENAIR2_DIR}/RRC/NAS/rb_config.c
${OPENAIR2_DIR}/UTIL/OMG/sumo.c
${OPENAIR_TARGETS}/COMMON/create_tasks.c
${HW_SOURCE}
${TRANSPORT_SOURCE}
@@ -1882,7 +1882,6 @@ foreach(myExe s1ap
aes128_cmac_encrypt
secu_knas_encrypt_eia2)
add_executable(test_${myExe}
${OPENAIR3_DIR}/TEST/test_util.c
${OPENAIR3_DIR}/TEST/test_${myExe}.c
)
target_link_libraries (test_${myExe}
-14
View File
@@ -6,20 +6,6 @@
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This header file may also be distributed under
* the terms of the BSD Licence as follows:
*
@@ -25,7 +25,6 @@
* \date 2009
* \version 0.1
* \company Eurecom
* \note This conde is under GNU GENERAL PUBLIC LICENSE, version 2, June 1991
* \email: navid.nikaein@eurecom.fr
* \warning
*/
@@ -1,414 +0,0 @@
/**
** \file Ajp13Socket.cpp
** \date 2007-10-05
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#include "Ajp13Socket.h"
#include "ajp13.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
#ifdef _DEBUG
#define DEB(x) x
#else
#define DEB(x)
#endif
// --------------------------------------------------------------------------------------
Ajp13Socket::Ajp13Socket(ISocketHandler& h) : AjpBaseSocket(h)
, m_body_size_left(0)
{
}
// --------------------------------------------------------------------------------------
void Ajp13Socket::OnHeader( short id, short len )
{
if (id != 0x1234)
{
DEB( fprintf(stderr, "ABORT: bad packet id: %x\n", id);)
SetCloseAndDelete();
}
else
{
DEB(fprintf(stderr, "Packet size: %d bytes\n", len);)
}
}
// --------------------------------------------------------------------------------------
void Ajp13Socket::ReceiveBody(const char *buf, size_t sz)
{
if (sz - 2 > m_body_size_left)
{
DEB( fprintf(stderr, "More body data received than expected\n");)
SetCloseAndDelete();
return;
}
m_req.Write( buf + 2, sz - 2 );
m_body_size_left -= sz - 2;
// request more body data
if (m_body_size_left)
{
int ptr = 4;
char msg[100];
msg[0] = 'A';
msg[1] = 'B';
// reply codes
// 0x3 Send Body Chunk
// 0x4 Send Headers
// 0x5 End Response
// 0x6 Get Body Chunk <------
// 0x9 CPong Reply
put_byte(msg, ptr, 0x06); // GET_BODY_CHUNK;
put_integer(msg, ptr, 1000); // request 1000 bytes
short len = htons( ptr - 4 );
memcpy( msg + 2, &len, 2 );
SendBuf( msg, ptr );
return;
}
// Close
m_req.CloseBody();
// no more body data left to read - execute
Execute();
}
// --------------------------------------------------------------------------------------
void Ajp13Socket::ReceiveForwardRequest( const char *buf, size_t sz )
{
//
int ptr = 0;
get_byte(buf, ptr); // skip first byte: prefix_code
unsigned char method = get_byte(buf, ptr);
std::string protocol = get_string(buf, ptr);
std::string req_uri = get_string(buf, ptr);
std::string remote_addr = get_string(buf, ptr);
std::string remote_host = get_string(buf, ptr);
std::string server_name = get_string(buf, ptr);
short server_port = get_integer(buf, ptr);
bool is_ssl = get_boolean(buf, ptr);
std::string method_str = Utility::l2string( method );
std::map<int, std::string>::const_iterator it = Init.Method.find( method );
if (it != Init.Method.end())
{
method_str = it -> second;
}
m_req.SetHttpMethod( method_str );
m_req.SetHttpVersion( protocol );
m_req.SetUri( req_uri );
m_req.SetRemoteAddr( remote_addr );
m_req.SetRemoteHost( remote_host );
m_req.SetServerName( server_name );
m_req.SetServerPort( server_port );
m_req.SetIsSsl( is_ssl );
// Get Headers
short num_headers = get_integer(buf, ptr);
for (int i = 0; i < num_headers; i++)
{
std::string key;
switch ( (unsigned char)buf[ptr]) // 0xa0
{
case 0xa0:
{
unsigned short x = (unsigned short)get_integer(buf, ptr);
std::map<int, std::string>::const_iterator it;
if ( (it = Init.Header.find(x)) != Init.Header.end())
{
key = it -> second;
}
else
{
DEB( fprintf(stderr, "Unknown header key value: %x\n", x);)
SetCloseAndDelete();
}
}
break;
default: // string
key = get_string(buf, ptr);
}
if (Utility::ToLower(key) == "cookie" || Utility::ToLower(key) == "cookie2")
m_req.AddCookie(get_string(buf, ptr));
else
m_req.SetHeader(key, get_string(buf, ptr));
} // for
// size left to read from web server
m_body_size_left = m_req.ContentLength();
// Get Attributes
while ( (unsigned char)buf[ptr] != 0xff)
{
std::string key;
unsigned char code = buf[ptr++];
switch ( code)
{
case 10: // req_attribute, attribute name follow
key = get_string(buf, ptr);
break;
default:
{
std::map<int, std::string>::const_iterator it = Init.Attribute.find( code );
if (it != Init.Attribute.end())
{
key = it -> second;
}
else
{
DEB( fprintf(stderr, "Unknown attribute key: 0x%02x\n", buf[ptr]);)
SetCloseAndDelete();
}
}
}
m_req.SetAttribute(key, get_string(buf, ptr));
} // while
// execute at once if no body data
if (!m_body_size_left)
{
Execute();
}
else
{
// open temporary file for body data
m_req.InitBody( m_body_size_left );
}
}
// --------------------------------------------------------------------------------------
void Ajp13Socket::ReceiveShutdown( const char *buf, size_t sz )
{
}
// --------------------------------------------------------------------------------------
void Ajp13Socket::ReceivePing( const char *buf, size_t sz )
{
}
// --------------------------------------------------------------------------------------
void Ajp13Socket::ReceiveCPing( const char *buf, size_t sz )
{
}
// --------------------------------------------------------------------------------------
void Ajp13Socket::Execute()
{
// parse form data / query_string and cookie header if available
m_req.ParseBody();
// prepare page
OnExec( m_req );
}
// --------------------------------------------------------------------------------------
void Ajp13Socket::Respond(const HttpResponse& res)
{
char msg[8192];
msg[0] = 'A';
msg[1] = 'B';
m_res = res;
// reply codes
// 0x3 Send Body Chunk
// 0x4 Send Headers
// 0x5 End Response
// 0x6 Get Body Chunk
// 0x9 CPong Reply
// check content length
if (!m_res.ContentLength() && m_res.GetFile().size())
{
// m_res.SetContentLength( m_res.GetFile().size() );
}
// Send Headers
{
int ptr = 4;
put_byte(msg, ptr, 0x04); // send headers
put_integer(msg, ptr, m_res.HttpStatusCode() );
put_string(msg, ptr, m_res.HttpStatusMsg() );
put_integer(msg, ptr, (short)m_res.Headers().size() );
for (Utility::ncmap<std::string>::const_iterator it = m_res.Headers().begin(); it != m_res.Headers().end(); ++it)
{
Utility::ncmap<int>::const_iterator it2 = Init.ResponseHeader.find( it -> first );
if (it2 != Init.ResponseHeader.end())
{
put_integer(msg, ptr, it2 -> second);
}
else
{
put_string(msg, ptr, it -> first);
}
put_string(msg, ptr, it -> second);
}
std::list<std::string> vec = m_res.CookieNames();
{
for (std::list<std::string>::iterator it = vec.begin(); it != vec.end(); ++it)
{
Utility::ncmap<int>::const_iterator it2 = Init.ResponseHeader.find( "set-cookie" );
if (it2 != Init.ResponseHeader.end())
{
put_integer(msg, ptr, it2 -> second);
}
else
{
put_string(msg, ptr, "set-cookie");
}
put_string(msg, ptr, m_res.Cookie(*it) );
}
}
short len = htons( ptr - 4 );
memcpy( msg + 2, &len, 2 );
SendBuf( msg, ptr );
}
// Send Body Chunk
OnTransferLimit();
}
// --------------------------------------------------------------------------------------
void Ajp13Socket::OnTransferLimit()
{
char msg[8192];
msg[0] = 'A';
msg[1] = 'B';
// Send Body Chunk
size_t n = m_res.GetFile().fread(msg + 7, 1, 8100);
while (n > 0)
{
int ptr = 4;
put_byte(msg, ptr, 0x03); // send body chunk
put_integer(msg, ptr, (short)n);
ptr += (int)n;
short len = htons( ptr - 4 );
memcpy( msg + 2, &len, 2 );
SendBuf( msg, ptr );
if (GetOutputLength() > 1)
{
SetTransferLimit( 1 );
break;
}
//
n = m_res.GetFile().fread(msg + 7, 1, 8100);
}
if (!GetOutputLength()) // all body data sent and no data in output buffer - send end response
{
// End Response
int ptr = 4;
put_byte(msg, ptr, 0x05); // end response
put_boolean(msg, ptr, false); // reuse
/*
don't reuse
- but with m_req.Reset() and m_res.Reset() it should be possible
- also reset any AjpBaseSocket/Ajp13Socket specific states
*/
short len = htons( ptr - 4 );
memcpy( msg + 2, &len, 2 );
SendBuf( msg, ptr );
SetTransferLimit(0);
m_res.GetFile().fclose();
OnResponseComplete();
}
}
// --------------------------------------------------------------------------------------
void Ajp13Socket::OnPacket( const char *buf, size_t sz )
{
DEB(fprintf(stderr, "OnPacket: %d bytes, code 0x%02x %02x %02x %02x\n", sz, *buf, buf[1], buf[2], buf[3]);)
// check body size left to read, if non-zero packet is body data
if (m_body_size_left) // must be a body packet
{
ReceiveBody(buf, sz);
return;
}
switch (*buf)
{
case 0x2: // Forward Request
ReceiveForwardRequest(buf, sz);
break;
case 0x7: // Shutdown
ReceiveShutdown(buf, sz);
break;
case 0x8: // Ping
ReceivePing(buf, sz);
break;
case 0xa: // CPing
ReceiveCPing(buf, sz);
break;
default:
DEB( fprintf(stderr, "Unknown packet type: 0x%02x\n", *buf);)
SetCloseAndDelete();
}
}
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
@@ -1,81 +0,0 @@
/**
** \file Ajp13Socket.h
** \date 2007-10-05
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_Ajp13Socket_H
#define _SOCKETS_Ajp13Socket_H
#include "AjpBaseSocket.h"
#include "HttpRequest.h"
#include "IHttpServer.h"
#include "HttpResponse.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class HttpResponse;
class Ajp13Socket : public AjpBaseSocket, public IHttpServer
{
public:
Ajp13Socket(ISocketHandler& h);
void OnHeader( short id, short len );
void OnPacket( const char *buf, size_t sz );
// implements IHttpServer::Respond
void Respond(const HttpResponse& res);
void OnTransferLimit();
private:
void ReceiveBody( const char *buf, size_t sz );
void ReceiveForwardRequest( const char *buf, size_t sz );
void ReceiveShutdown( const char *buf, size_t sz );
void ReceivePing( const char *buf, size_t sz );
void ReceiveCPing( const char *buf, size_t sz );
void Execute();
//
size_t m_body_size_left;
HttpRequest m_req;
HttpResponse m_res;
};
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // _SOCKETS_Ajp13Socket_H
@@ -1,268 +0,0 @@
/**
** \file AjpBaseSocket.cpp
** \date 2007-10-05
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#include "AjpBaseSocket.h"
#include "ajp13.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
#ifdef _DEBUG
#define DEB(x) x
#else
#define DEB(x)
#endif
// ---------------------------------------------------------------------------
AjpBaseSocket::Initializer AjpBaseSocket::Init;
// ---------------------------------------------------------------------------
AjpBaseSocket::Initializer::Initializer()
{
Header[HTTP_REQUEST_ACCEPT] = "accept";
Header[HTTP_REQUEST_ACCEPT_CHARSET] = "accept-charset";
Header[HTTP_REQUEST_ACCEPT_ENCODING] = "accept-encoding";
Header[HTTP_REQUEST_ACCEPT_LANGUAGE] = "accept-language";
Header[HTTP_REQUEST_AUTHORIZATION] = "authorization";
Header[HTTP_REQUEST_CONNECTION] = "connection";
Header[HTTP_REQUEST_CONTENT_TYPE] = "content-type";
Header[HTTP_REQUEST_CONTENT_LENGTH] = "content-length";
Header[HTTP_REQUEST_COOKIE] = "cookie";
Header[HTTP_REQUEST_COOKIE2] = "cookie2";
Header[HTTP_REQUEST_HOST] = "host";
Header[HTTP_REQUEST_PRAGMA] = "pragma";
Header[HTTP_REQUEST_REFERER] = "referer";
Header[HTTP_REQUEST_USER_AGENT] = "user-agent";
Method[HTTP_METHOD_OPTIONS] = "OPTIONS";
Method[HTTP_METHOD_GET] = "GET";
Method[HTTP_METHOD_HEAD] = "HEAD";
Method[HTTP_METHOD_POST] = "POST";
Method[HTTP_METHOD_PUT] = "PUT";
Method[HTTP_METHOD_DELETE] = "DELETE";
Method[HTTP_METHOD_TRACE] = "TRACE";
Method[HTTP_METHOD_PROPFIND] = "PROPFIND";
Method[HTTP_METHOD_PROPPATCH] = "PROPPATCH";
Method[HTTP_METHOD_MKCOL] = "MKCOL";
Method[HTTP_METHOD_COPY] = "COPY";
Method[HTTP_METHOD_MOVE] = "MOVE";
Method[HTTP_METHOD_LOCK] = "LOCK";
Method[HTTP_METHOD_UNLOCK] = "UNLOCK";
Method[HTTP_METHOD_ACL] = "ACL";
Method[HTTP_METHOD_REPORT] = "REPORT";
Method[HTTP_METHOD_VERSION_CONTROL] = "VERSION_CONTROL"; // with a dash "VERSION-CONTROL"
Method[HTTP_METHOD_CHECKIN] = "CHECKIN";
Method[HTTP_METHOD_CHECKOUT] = "CHECKOUT";
Method[HTTP_METHOD_UNCHECKOUT] = "UNCHECKOUT";
Method[HTTP_METHOD_SEARCH] = "SEARCH";
Method[HTTP_METHOD_MKWORKSPACE] = "MKWORKSPACE";
Method[HTTP_METHOD_UPDATE] = "UPDATE";
Method[HTTP_METHOD_LABEL] = "LABEL";
Method[HTTP_METHOD_MERGE] = "MERGE";
Method[HTTP_METHOD_BASELINE_CONTROL] = "BASELINE_CONTROL";
Method[HTTP_METHOD_MKACTIVITY] = "MKACTIVITY";
Attribute[ATTR_CONTEXT] = "context";
Attribute[ATTR_SERVLET_PATH] = "servlet_path";
Attribute[ATTR_REMOTE_USER] = "remote_user";
Attribute[ATTR_AUTH_TYPE] = "auth_type";
Attribute[ATTR_QUERY_STRING] = "query_string";
Attribute[ATTR_ROUTE] = "route";
Attribute[ATTR_SSL_CERT] = "ssl_cert";
Attribute[ATTR_SSL_CIPHER] = "ssl_cipher";
Attribute[ATTR_SSL_SESSION] = "ssl_session";
Attribute[ATTR_SSL_KEY_SIZE] = "ssl_key_size";
Attribute[ATTR_SECRET] = "secret";
Attribute[ATTR_STORED_METHOD] = "stored_method";
ResponseHeader["content-type"] = 0xa001;
ResponseHeader["content-language"] = 0xa002;
ResponseHeader["content-length"] = 0xa003;
ResponseHeader["date"] = 0xa004;
ResponseHeader["last-modified"] = 0xa005;
ResponseHeader["location"] = 0xa006;
ResponseHeader["set-cookie"] = 0xa007;
ResponseHeader["set-cookie2"] = 0xa008;
ResponseHeader["servlet-engine"] = 0xa009;
ResponseHeader["status"] = 0xa00a;
ResponseHeader["www-authenticate"] = 0xa00b;
}
// ---------------------------------------------------------------------------
AjpBaseSocket::AjpBaseSocket(ISocketHandler& h) : TcpSocket(h)
, m_state(0)
, m_length(4)
, m_ptr(0)
{
}
// ---------------------------------------------------------------------------
void AjpBaseSocket::OnRawData(const char *buf, size_t sz)
{
DEB(fprintf(stderr, "OnRawData: %d bytes\n", sz);)
size_t ptr = 0;
while (true)
{
size_t left = sz - ptr;
DEB(fprintf(stderr, " left: %d bytes\n", left);
fprintf(stderr, " state: %d\n", m_state);)
switch (m_state)
{
case 0:
{
size_t missing = m_length - m_ptr;
short len = (short)(missing < left ? missing : left);
memcpy(m_message + m_ptr, buf + ptr, len);
m_ptr += len;
ptr += len;
if (m_ptr < m_length)
{
return; // read more
}
int p = 0;
short id = get_integer(m_message, p);
short length = get_integer(m_message, p);
OnHeader(id, length);
m_state = 1;
m_length = length;
m_ptr = 0; // bytes in m_message
}
break;
case 1:
{
size_t missing = m_length - m_ptr;
short len = (short)(missing < left ? missing : left);
memcpy(m_message + m_ptr, buf + ptr, len);
m_ptr += len;
ptr += len;
if (m_ptr < m_length)
{
return; // read more
}
OnPacket(m_message, m_ptr);
m_state = 0;
m_length = 4;
m_ptr = 0;
}
break;
}
}
}
// ---------------------------------------------------------------------------
unsigned char AjpBaseSocket::get_byte(const char *buf, int& ptr)
{
return (unsigned char)buf[ptr++];
}
// ---------------------------------------------------------------------------
bool AjpBaseSocket::get_boolean(const char *buf, int& ptr)
{
return ( (unsigned char)buf[ptr++] & 1) == 1 ? true : false;
}
// ---------------------------------------------------------------------------
short AjpBaseSocket::get_integer(const char *buf, int& ptr)
{
short n;
memcpy(&n, buf + ptr, 2);
ptr += 2;
return ntohs(n);
}
// ---------------------------------------------------------------------------
std::string AjpBaseSocket::get_string(const char *buf, int& ptr)
{
short len = get_integer(buf, ptr);
if (len != -1)
{
std::string tmp = buf + ptr;
ptr += len;
ptr++; // skip trailing 0x0
tmp.resize(len);
return tmp;
}
return "";
}
// ---------------------------------------------------------------------------
void AjpBaseSocket::put_byte(char *buf, int& ptr, unsigned char zz)
{
buf[ptr++] = zz;
}
// ---------------------------------------------------------------------------
void AjpBaseSocket::put_boolean(char *buf, int& ptr, bool zz)
{
buf[ptr++] = zz ? 1 : 0;
}
// ---------------------------------------------------------------------------
void AjpBaseSocket::put_integer(char *buf, int& ptr, short zz)
{
short tmp = htons(zz);
memcpy(buf + ptr, &tmp, 2);
ptr += 2;
}
// ---------------------------------------------------------------------------
void AjpBaseSocket::put_string(char *buf, int& ptr, const std::string& zz)
{
put_integer(buf, ptr, (short)zz.size() );
memcpy(buf + ptr, zz.c_str(), zz.size());
ptr += (int)zz.size();
put_byte(buf, ptr, 0);
}
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
@@ -1,96 +0,0 @@
/**
** \file AjpBaseSocket.h
** \date 2007-10-05
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_AjpBaseSocket_H
#define _SOCKETS_AjpBaseSocket_H
#include "TcpSocket.h"
#include <map>
#include "Utility.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class AjpBaseSocket : public TcpSocket
{
class Initializer
{
public:
Initializer();
virtual ~Initializer() {}
std::map<int, std::string> Method;
std::map<int, std::string> Header;
std::map<int, std::string> Attribute;
Utility::ncmap<int> ResponseHeader;
};
public:
AjpBaseSocket(ISocketHandler& h);
void OnRawData(const char *buf, size_t sz);
virtual void OnHeader( short id, short len ) = 0;
virtual void OnPacket( const char *buf, size_t sz ) = 0;
protected:
unsigned char get_byte(const char *buf, int& ptr);
bool get_boolean(const char *buf, int& ptr);
short get_integer(const char *buf, int& ptr);
std::string get_string(const char *buf, int& ptr);
void put_byte(char *buf, int& ptr, unsigned char zz);
void put_boolean(char *buf, int& ptr, bool zz);
void put_integer(char *buf, int& ptr, short zz);
void put_string(char *buf, int& ptr, const std::string& zz);
static Initializer Init;
private:
int m_state;
int m_length;
int m_ptr;
char m_message[8192];
};
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // _SOCKETS_AjpBaseSocket_H
@@ -1,314 +0,0 @@
/** \file Base64.cpp
** \date 2004-02-13
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "Base64.h"
#include "IFile.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
const char *Base64::bstr =
"ABCDEFGHIJKLMNOPQ"
"RSTUVWXYZabcdefgh"
"ijklmnopqrstuvwxy"
"z0123456789+/";
const char Base64::rstr[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0,
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0};
Base64::Base64()
{
}
void Base64::encode(IFile *fil, std::string& output, bool add_crlf)
{
size_t remain;
size_t i = 0;
size_t o = 0;
char input[4];
output = "";
remain = fil -> fread(input,1,3);
while (remain > 0)
{
if (add_crlf && o && o % 76 == 0)
output += "\n";
switch (remain)
{
case 1:
output += bstr[ ((input[i] >> 2) & 0x3f) ];
output += bstr[ ((input[i] << 4) & 0x30) ];
output += "==";
break;
case 2:
output += bstr[ ((input[i] >> 2) & 0x3f) ];
output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ];
output += bstr[ ((input[i + 1] << 2) & 0x3c) ];
output += "=";
break;
default:
output += bstr[ ((input[i] >> 2) & 0x3f) ];
output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ];
output += bstr[ ((input[i + 1] << 2) & 0x3c) + ((input[i + 2] >> 6) & 0x03) ];
output += bstr[ (input[i + 2] & 0x3f) ];
}
o += 4;
//
remain = fil -> fread(input,1,3);
}
}
void Base64::encode(FILE *fil, std::string& output, bool add_crlf)
{
size_t remain;
size_t i = 0;
size_t o = 0;
char input[4];
output = "";
remain = fread(input,1,3,fil);
while (remain > 0)
{
if (add_crlf && o && o % 76 == 0)
output += "\n";
switch (remain)
{
case 1:
output += bstr[ ((input[i] >> 2) & 0x3f) ];
output += bstr[ ((input[i] << 4) & 0x30) ];
output += "==";
break;
case 2:
output += bstr[ ((input[i] >> 2) & 0x3f) ];
output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ];
output += bstr[ ((input[i + 1] << 2) & 0x3c) ];
output += "=";
break;
default:
output += bstr[ ((input[i] >> 2) & 0x3f) ];
output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ];
output += bstr[ ((input[i + 1] << 2) & 0x3c) + ((input[i + 2] >> 6) & 0x03) ];
output += bstr[ (input[i + 2] & 0x3f) ];
}
o += 4;
//
remain = fread(input,1,3,fil);
}
}
void Base64::encode(const std::string& str_in, std::string& str_out, bool add_crlf)
{
encode(str_in.c_str(), str_in.size(), str_out, add_crlf);
}
void Base64::encode(const char* input,size_t l,std::string& output, bool add_crlf)
{
size_t i = 0;
size_t o = 0;
output = "";
while (i < l)
{
size_t remain = l - i;
if (add_crlf && o && o % 76 == 0)
output += "\n";
switch (remain)
{
case 1:
output += bstr[ ((input[i] >> 2) & 0x3f) ];
output += bstr[ ((input[i] << 4) & 0x30) ];
output += "==";
break;
case 2:
output += bstr[ ((input[i] >> 2) & 0x3f) ];
output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ];
output += bstr[ ((input[i + 1] << 2) & 0x3c) ];
output += "=";
break;
default:
output += bstr[ ((input[i] >> 2) & 0x3f) ];
output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ];
output += bstr[ ((input[i + 1] << 2) & 0x3c) + ((input[i + 2] >> 6) & 0x03) ];
output += bstr[ (input[i + 2] & 0x3f) ];
}
o += 4;
i += 3;
}
}
void Base64::encode(const unsigned char* input,size_t l,std::string& output,bool add_crlf)
{
size_t i = 0;
size_t o = 0;
output = "";
while (i < l)
{
size_t remain = l - i;
if (add_crlf && o && o % 76 == 0)
output += "\n";
switch (remain)
{
case 1:
output += bstr[ ((input[i] >> 2) & 0x3f) ];
output += bstr[ ((input[i] << 4) & 0x30) ];
output += "==";
break;
case 2:
output += bstr[ ((input[i] >> 2) & 0x3f) ];
output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ];
output += bstr[ ((input[i + 1] << 2) & 0x3c) ];
output += "=";
break;
default:
output += bstr[ ((input[i] >> 2) & 0x3f) ];
output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ];
output += bstr[ ((input[i + 1] << 2) & 0x3c) + ((input[i + 2] >> 6) & 0x03) ];
output += bstr[ (input[i + 2] & 0x3f) ];
}
o += 4;
i += 3;
}
}
void Base64::decode(const std::string& input,std::string& output)
{
size_t i = 0;
size_t l = input.size();
output = "";
while (i < l)
{
while (i < l && (input[i] == 13 || input[i] == 10))
i++;
if (i < l)
{
char b1 = (char)((rstr[(int)input[i]] << 2 & 0xfc) +
(rstr[(int)input[i + 1]] >> 4 & 0x03));
output += b1;
if (input[i + 2] != '=')
{
char b2 = (char)((rstr[(int)input[i + 1]] << 4 & 0xf0) +
(rstr[(int)input[i + 2]] >> 2 & 0x0f));
output += b2;
}
if (input[i + 3] != '=')
{
char b3 = (char)((rstr[(int)input[i + 2]] << 6 & 0xc0) +
rstr[(int)input[i + 3]]);
output += b3;
}
i += 4;
}
}
}
void Base64::decode(const std::string& input, unsigned char *output, size_t& sz)
{
size_t i = 0;
size_t l = input.size();
size_t j = 0;
while (i < l)
{
while (i < l && (input[i] == 13 || input[i] == 10))
i++;
if (i < l)
{
unsigned char b1 = (unsigned char)((rstr[(int)input[i]] << 2 & 0xfc) +
(rstr[(int)input[i + 1]] >> 4 & 0x03));
if (output)
{
output[j] = b1;
}
j++;
if (input[i + 2] != '=')
{
unsigned char b2 = (unsigned char)((rstr[(int)input[i + 1]] << 4 & 0xf0) +
(rstr[(int)input[i + 2]] >> 2 & 0x0f));
if (output)
{
output[j] = b2;
}
j++;
}
if (input[i + 3] != '=')
{
unsigned char b3 = (unsigned char)((rstr[(int)input[i + 2]] << 6 & 0xc0) +
rstr[(int)input[i + 3]]);
if (output)
{
output[j] = b3;
}
j++;
}
i += 4;
}
}
sz = j;
}
size_t Base64::decode_length(const std::string& str64)
{
if (!str64.size() || str64.size() % 4)
return 0;
size_t l = 3 * (str64.size() / 4 - 1) + 1;
if (str64[str64.size() - 2] != '=')
l++;
if (str64[str64.size() - 1] != '=')
l++;
return l;
}
#ifdef SOCKETS_NAMESPACE
}
#endif
@@ -1,85 +0,0 @@
/** \file Base64.h
** \date 2004-02-13
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_Base64_H
#define _SOCKETS_Base64_H
#include "sockets-config.h"
#ifdef _MSC_VER
#pragma warning(disable:4514)
#endif
#include <stdio.h>
#include <string>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class IFile;
/** \defgroup util Utilities */
/** Base64 encode/decode.
\ingroup util */
class Base64
{
public:
Base64();
void encode(FILE *, std::string& , bool add_crlf = true);
void encode(IFile *, std::string& , bool add_crlf = true);
void encode(const std::string&, std::string& , bool add_crlf = true);
void encode(const char *, size_t, std::string& , bool add_crlf = true);
void encode(const unsigned char *, size_t, std::string& , bool add_crlf = true);
void decode(const std::string&, std::string& );
void decode(const std::string&, unsigned char *, size_t&);
size_t decode_length(const std::string& );
private:
Base64(const Base64& ) {}
Base64& operator=(const Base64& ) {
return *this;
}
static const char *bstr;
static const char rstr[128];
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_Base64_H
@@ -1,855 +0,0 @@
diff for next release always available @ http://www.alhem.net/Sockets/latest_diff.html
next
--------
2.3.9.4
--------
File can be created using an existing FILE *. Fix bug in File using wrong
file ptr when writing.
Added HttpdForm constructor (FILE *) that detects cgi input using
environment variables.
Added HttpRequest constructor (FILE *) that can parse a cgi request.
Added missing sockets namespace in SocketThread class files.
Added new operator <<(int64_t) in StreamWriter. Might be ambigouos on some
architectures.
Fix expression evaluation in TcpSocket, causing access to null pointer.
Fix disable of both reconnect and detach functions.
Added Utility::bigint2string(int64_t).
Added Json support.
2.3.9.3
--------
Added multithread support in sockethandler. New method SetNumberOfThreads()
enables this.
New method in sockethandler: Release(). Make select() release before
specified timeout. Enable function with method EnableRelease().
EventHandler using new release functionality.
Thread startup controlled with semaphore instead of flag/sleep combo.
Default thread startup behaviour is run at once, optional is wait until
released by posting to semaphore (via method SetRelease(true)).
Adding a socket with closeanddelete flag set now works as expected.
Added platform independent method Utility::Sleep( milliseconds ).
Added missing win32 implementation in new sockethandler.
Added win32 implementation of Semaphore.
Repaired build for cygwin/mingw/devcpp.
2.3.9.2
--------
More internal restructuring of SocketHandler.
The Get() method has been removed. Set() has been split into three:
ISocketHandler_Add(), ISocketHandler_Mod(), and ISocketHandler_Del().
New methods defined in ISocketHandler interface to support different
models of socket io: ISocketHandler_Select(), MaxCount().
Removed Set() method from Socket class.
Implemented SocketHandlerEp using epoll for linux only.
reinterpret_cast<> added in ListenSocket for ipv6 address struct.
HttpPostSocket member variable holding http headers (m_fields) is now
protected (changed from private).
Repaired Reconnect function in sockethandler.
2.3.9.1
--------
Using thread- and memory safe clib/c runtime function when possible.
Restructured sockethandler internals.
Quicker tcp shutdown sequence when sockets lib initiates close.
Renamed Utility::GetCurrentDirectory to Utility::CurrentDirectory, and
added Utility::GetEnv().
Removed unused triggers code.
2.3.9
------
TcpSocket using std::vector<char> to receive incoming line (OnLine
callback). Configurable max limit for library available in sockets-config.h,
default 8192 bytes (TCP_LINE_SIZE). Override ISocketHandler::MaxTcpLineSize
to change this value without recompiling the library.
Added more operators in Debug class. Removed some leftover debug printouts.
HttpResponse returns non-const output file.
HTTPSocket aborts after receiving more than 200 (MAX_HTTP_HEADER_COUNT) http
headers. Use method HTTPSocket::SetMaxHeaderCount() to modify this value.
Reordered log level enum, added minlevel to StdoutLog.
2.3.8
------
SSL sockets now operate in nonblocking mode. A much better solution to the
"hang" problem mentioned in 2.3.7.
Added Path() method to IFile interface. Returns File path name or MemFile
virtual path name.
Added constructor in MemFile that takes a File as input. Will read the
entire File to memory. Added constructor in MemFile that copies another
memfile. Will use the source memfile when reading.
Added reference count when a MemFile object is source for another memfile.
Set OnTransferLimit back to 0 after a successful transfer of requested file
(in Ajp13Socket and HttpBaseSocket). Reset IFile auto_ptr to
decrease the reference count asap (by using fclose).
2.3.7
------
Moved some #include's outside the sockets namespace definition.
Fix code to avoid an increment on an stl iterator that has reached end.
Helping compilers deal with it++ when result is not used, changed all it++
to ++it where appropriate.
Doing an extra select on write readiness on file descriptor before calling
SSL_write. Prevents a hang situation when the remote end drops the
connection.
2.3.6
------
Added improved Valid() method using unique socket instance identifier. Using
this identifier internally for events and resolver. Added optional data
parameter in Event class, used by library to store socket instance
identifier.
No longer using SSL_MODE_AUTO_RETRY for ssl connections. If remote end
disconnects this would cause hangups.
Using SSL_MODE_ENABLE_PARTIAL_WRITE because the library supports this.
Renamed EventHandler() method in IEventOwner to GetEventHandler().
Added file system path abstraction methods to Utility.
Reset file descriptor after successful close of a ListenSocket.
2.3.5
------
Added method(s) in UdpSocket to set default interface to be used for multicast.
Added flag for position independent code for linux-x86-32 architecture (see
Makefile.Defines.linux-x86-32).
Added missing includes (on some distributions/gcc versions).
SetUri in HttpRequest no longer URLDecodes the entire url.
Fix for static variables in SSLInitializer.
Fix for new version of openssl (const SSLxx_method()).
Fix for getnameinfo.
Modified Utility::Uri parser class so it also splits the url in path /
querystring parts.
2.3.4
------
Some .cpp were missing namespace declarations - fixed. Some includes for
ipv6 was missing - fixed. Operators in StreamWriter class modified to work
on 64-bit as well as 32-bit systems.
2.3.3
------
Fix deadlock in SSLInitializer introduced in 2.3.2.
Added check when select() returns -1 indicating one of the file descriptors
have gone bad. The check rebuilds the fd_set used by select().
Bugfix in HttpGetSocket, one of the constructors had no support in
HttpClientSocket - added.
Corrected bad #include's in Utility.
Added IStream interface to read/write from socket and IFile (memfile, normal
file). New classes SocketStream, FileStream, StreamWriter.
Added ReadInput method in TcpSocket - read from input buffer.
Added GetLine method in TcpSocket - chars input on current line when using
SetLineProtocol mode.
2.3.2
------
Threadsafe list of ssl initializer, ssl contexts and openssl error text
retrieval.
Added interface for Mutex class, adding the possibility for others to
implement the mutex functionality using other approaches.
Moved FromUtf8 method from XmlNode to Utility.
2.3.1
------
Request: Remove() method in SocketHandler changed from private to protected.
Added Utility::Stack that returns a stack walk (currently linux only).
Request: Added $(DESTDIR) variable in Makefile for more flexible installation.
The timeout value is now reset before OnTimeout() is called, making it
possible to set a new timeout value in the OnTimeout() method.
2.3
------
Small change in ListenSocket<> to improve accepting of incoming
connections.
Added xml parsing classes: XmlDocument, XmlNode, and XmlException.
Added new OnDisconnect(flags, code) callback that provides reason
for the disconnect.
Fix crash bug if an event object gets deleted in its own OnEvent
method.
gcc 4.3 compability fixes.
2.2.9a
------
Added assignment operator on HttpRequest class.
HttpdForm sometimes got stuck in an infinite loop - fixed.
Lock using const Mutex, and Mutex modified to work when const.
Added Utility::Uri that can be used for parsing of an url.
2.2.9
-----
Fixed memory leak in TcpSocket.
Fixed potentially unsafe code in http form data parser (HttpdForm).
Fix memory and resource leak in HttpRequest.
Ajp13Socket/HttpBaseSocket now creates a copy of the HttpResponse
instance when sending a response, to avoid synchronization problems.
Added "lost" flag which is set when a tcpsocket has lost connection
unexpectedly (on read/write error). Earlier this function was only
present when the connection pool was enabled (ENABLE_POOL).
Removed unnecessary call to shutdown() when destroying a closed
tcp socket.
Added brief 'INSTALL' document.
2.2.8
-----
Added http client ability to receive a chunked response.
HTTP headers are now treated in a case insensitive manner.
MacOS leopard fixes.
Added callback "OnDataComplete" to HTTPSocket, which is called
when the full body of the request/response has been received.
New random generator (mersienne twister).
2.2.7
-----
Http header names no longer converted to lowercase.
"setsockopt()" wrapper methods returning int values has been fixed.
No longer sets query_string attribute of HttpRequest when there is no
query string present.
2.2.6
-----
Modified HttpRequest class to easier add support for pipelining.
Made the following classes work with the copy constructor: HttpRequest,
HttpTransaction, HttpdCookies.
Always adding http header names as lowercase in internal storage
(HTTPSocket). Added method to check if http header is set.
Changed IHttpServer interface to better separate request and response.
Added -mno-cygwin flag in Makefile defines for cygwin.
Added calls to OnDisconnect when socket operation caused socket to close.
2.2.5
-----
A basic_string exception thrown while trying to access the first
(non-existing) element in a zero-sized string was fixed in HTTPSocket.
Added separate http_version for HttpResponse. Improved reset of state
information in HTTPSocket and derivates (for keep-alive connections).
MemFile support reads and writes larger than internal blocksize.
2.2.4
-----
IFile (File/MemFile) added reset_read and reset_write.
Bugfix MemFile read.
UdpSocket timestamp small fix for win32.
Cookies reworked in Http framework (Transaction/Request/Response
and HttpBaseSocket/Ajp13Socket).
Compile issue when compiling without openssl solved.
2.2.3
-----
SSL Handshake was never initiated when using both client and server from the
library - fixed.
UdpSocket read timestamp added (SetTimestamp) as new OnRawData method. Use
when timestamps enabled with call to SetSoTimestamp. Not win32.
MacOSX project added. Big Thanks to Bruce for both of these.
2.2.2
-----
Close file descriptor in File destructor.
HttpClientSocket new access method Filename.
Added a few access methods to HttpdSocket.
Check if gethostbyname_r failed.
Async resolver fix.
Fix win32 build problem (uint64_t).
2.2.1
-----
Adding (optional) exceptions when Bind() or CreateSocket() fails.
Enable with ENABLE_EXCEPTIONS.
Added GetSock* methods in Socket, to retreive information about local
port and address in a connection.
Added InitializeContext in TcpSocket with separate certificate / key files.
Moved some #include's from .h to .cpp files.
Removed multiple calls to recvfrom() in UdpSocket OnRead.
HTTPSocket corrected.
2.2
-----
TcpSocket output buffer error fixed.
HTTPSocket HTTP/1.0 request (or HTTP/1.1 with connection: close) fixed.
IEventHandler now won't crash if the IEventOwner is deleted in OnEvent.
Added Ajp13Socket that understands the ajp/1.3 protocol. Each request received
by the class results in an "OnExec(HttpRequest, HttpResponse)" call.
Added "HttpBaseSocket" that also use the "OnExec" method to process a
http/https request.
2.1.9
-----
Added exception class.
Changed platform selection in Unix Makefile.
Cleaner compile on mingw.
HTTPSocket supports keepalive.
OnDisconnect moved out of ENABLE_RECONNECT scope.
2.1.8
-----
Added missing (optional) namespace in SmtpdSocket.
TcpSocket: Calling OnDisconnect when reading 0 bytes.
TcpSocket: Added OnTransferLimit() callback, called when output buffer
size drops below limit set by SetTransferLimit().
Boundary bug (writes over two blocks failed) in MemFile fixed.
Member variables in SSLInitializer no longer static since SSLInitializer
in itself is static in TcpSocket (avoid potential problem with
initialization order of static's).
2.1.7
-----
Fatal bug in LineProtocol/Online found, when a crlf happens over a read
buffer boundary. FIXED.
New output buffer logic. OnWriteComplete callback added, which fires after
the output buffer has been transferred.
2.1.6
-----
No more random number generator in Socket. Random number generator used in
Utility changed to static.
ISocketHandler is now a pure virtual definition of the SocketHandler.
Added general purpose timeout to Socket class (SetTimeout, OnTimeout), and
used it to implement the connection timeout logic in TcpSocket/SctpSocket.
Also added OnConnectTimeout which is called instead of OnTimeout, if the
socket is in Connecting mode.
New StreamSocket class defines variables used for sock_stream stuff (such
as connecting, the line protocol).
2.1.5
-----
Changed socket and ip option calls to directly manipulate the socket. They
should be used in the OnOptions callback, to set up the connection before
it is used. OnOptions is only called on client sockets. It is not called on
incoming connections accepted with accept()).
Removed Set methods from ResolvSocket and replaced them with one
constructor for each of the different resolves it can do.
Added DNS cache in ResolvSocket.
Made CircularBuffer an internal class of TcpSocket.
Moved these classes to a separate download:
ICrypt NullCrypt CTcpSocket MinionSocket MinderSocket MinderHandler Uid
ListenSocket now sets SO_REUSEADDR in its OnOptions method.
Small fixes to SmtpSocket to support the new configuration stuff.
Added socket to socket trigger framework (sockets-config.h: ENABLE_TRIGGERS).
Small bugfix in TcpSocket::Open when trying to connect to an ipv6 host
with numeric ip address.
2.1.4
-----
Added traffic monitor function.
EventHandler/IEventOwner bugfix (pure virtual method called on takedown).
Added outstanding events counter to IEventOwner, to avoid calling
ClearEvents in destructor of an IEventOwner with no events to clear.
Modified GetTimeUntilNextEvent to not return a negative time.
Added SmtpdSocket serverside implementation.
Crash bug fix if trying to add a socket that already exists in
sockethandler queue.
Made a few classes internal (PoolSocket, EventSocket, SocketThread).
2.1.3
-----
Added optional Ipv6 and Detach functionality to sockets-config.h.
(ENABLE_IPV6, ENABLE_DETACH)
Crash bug fix: if socket that asked a resolve question is destroyed
before answer arrives.
HTTPS (openssl) session support on server side.
Safer ssl read/write - tnx Peters!
All debug output now to stderr.
GetClientRemoteAddress and XXX now returns a copy of the address in
question, to avoid NULLing the source address when using std::auto_ptr.
SSL initialization code separated from TcpSocket and put in a new
SSLInitializer class.
2.1.2
-----
Fix for broken http framework.
Http and httpd tests added.
Configurable options moved to new 'sockets-config.h' file.
Restored code for dns resolve when getaddrinfo/getnameinfo isn't available.
(See sockets-config.h symbol NO_GETADDRINFO)
2.1.1
-----
Semaphore added.
Utility::GetTime() fixed on win32.
2.1
---
* Added Utility::GetTime.
* Created socket handler base class ISocketHandler. It will now be possible
to write really customized sockethandlers. One effect of this is that
the first parameter of the Socket class constructor changes from
SocketHandler& to ISocketHandler& - this will affect all current
software using the library.
* StdLog constructor first parameter changed from SocketHandler*
to ISocketHandler*
* Modified list handling in Socket/SocketHandler.
* Added possibility to clear tcp socket byte counters by passing
'true' as input parameter to GetBytesReceived() and GetBytesSent().
* Improved CircularBuffer performance when used as output buffer by
TcpSocket.
* Removed unused and confusing method ISocketHandler::GetSocket.
* SocketAddress will replace direct use of ipv4/ipv6 addresses in the code.
* Removed virtual supporting method Socket::ReadLine. If anyone was using
that method, it used to be called directly after the OnRead callback,
if SetLineProtocol was enabled. Repairing the functionality means
adding a call of your own in the OnRead callback.
* Optimized code for OnLine and HTTP header parsing.
* Found and fixed a timing bug in thread code that could cause
a segmentation fault.
* 'echoserver.cpp' and 'stressclient.cpp' added, for test. Supports
normal echo operation, http "echo" server and ssl server/client.
2.0.9
-----
Added a way to disable input buffering on tcp sockets.
The method TcpSocket::DisableInputBuffer() will prevent all writing
to the input buffer. After that, the only way to receive data is to
implement an OnRawData method. TcpSocket derived classes that
already only use OnRawData as a means of receiving data should
call DisableInputBuffer() to improve performance (and turn off those
annoying warning messages).
OnOptions will now be called by UdpSocket. OnOptions is now a pure
virtual method in the Socket class. Moved default implementation of
OnOptions from Socket to TcpSocket. Added empty implementations of
OnOptions in ListenSocket<>, UdpSocket and PoolSocket.
Made Sockets-config compile on mingw systems.
2.0.8
-----
gethostbyname_r only used if the symbol LINUX is defined.
Sctp protocol by default disabled. Enable by defining USE_SCTP.
Fixed warnings about GetSocket/handler in connect and disconnect
situations.
2.0.7
-----
Added Resolve(ipaddr_t) and Resolve(const std::string&) in Socket class
for reverse lookup. Added OnResolveFailed() callback to Socket when a
Resolve call failed.
Moved definition of SOCKETS_DYNAMIC_TEMP to socket_include.h to avoid
breaking windows application not using Sockets-config to retrieve
compile time flags.
Added "fd XX" to StdoutLog debug printout whenever a socket instance
generates an event, where XX is the file descriptor of the socket or
-1 if the file descriptor isn't valid.
Reset connected flag when read returns 0 - avoids using shutdown on
Close() and the following warning.
SCTP support added - see SctpSocket class.
2.0.6
-----
"gethostbyname()" calls are replaced with "gethostbyname_r()", to ensure
threadsafe operation.
If the flag SOCKETS_DYNAMIC_TEMP is defined at compile time of the library,
all application using the library must also define the same flag. In unix/
linux Makefiles this is easiest done by adding `Sockets-config` to the
CPPFLAGS variable.
Optimized SocketHandler by removing the SocketHandler::GetSocket method
and adding better code in each place where it was used - Thanks Samuel.
CircularBuffer now has a ReadString method.
Added method to remove a specific event to the EventHandler class.
Added methods to the IEventOwner interface to remove all events or
one specific events. - Thanks Thomas
2.0.5
-----
Added missing call to OnRawData when using ssl.
Bugfix in HttpPostSocket, where the boundary variable was never set.
Reset connecting flag in TcpSocket when a connection attempt fails.
Define SOCKETS_DYNAMIC_TEMP to use dynamically allocated temporary
buffers in read operations - helps on ECOS.
Compile with -O0 if you are using gcc 2.9.x.
2.0.4
-----
Improved Http client classes, now they're all able to receive a response.
Use methods SetFilename() / SetDataPtr() to write response to a file
or to memory respectively.
Small fix for uuid.h include for mac os x.
Removed debug printout in SSLInitializer.
2.0.3
-----
Url parsing modified for Http Get/Put/Post classes to enable ssl if the
url protocol is https.
TcpSocket/SSL random file modified, see tutorial page at
http://www.alhem.net/Sockets/tutorial/using6d.html
Removed a lot of old debug printouts.
2.0.2b
------
Replaced direct read access to sockets map with a method looping through
the map, to avoid adding null pointers to non-existing file descriptors.
2.0.2a
------
The new add control logic broke tcp reconnect, so this is a fix for that.
2.0.2
-----
Fixed infinite loop that could lock the main process when a socket attempts
to connect, gets data to send, and then the connection fails.
Added control so the same file descriptor can't be added to the socket
handler twice.
Utility::rfc1738_encode buffer overflow (read only) fixed.
Moved local hostname resolution stuff from SocketHandler to Utility
- see http://www.alhem.net/Sockets/tutorial/using6c.html
Project files for visual studio 6 slightly modified (missing dependency,
FD_SETSIZE define removed).
2.0.1
-----
Moved Errno declaration outside sockets namespace when compiling for unix.
This was already done for the win32 implementation.
Made typedef for socket_m in SocketHandler protected, since its use are
already protected.
Fixed problem with reconnect.
2.0
---
Optimizing SocketHandler.
Fixed SSL socket reconnect.
HttpGetSocket url parsing fixed. Really.
Increased char buffer size in HttpdSocket for large query_string's.
Added timer events, implemented in EventHandler.
Using _beginthreadex()/_endthreadex() to create/end thread in _win32.
Using GetTempPathA() explicitly when getting _win32 temporary path.
* Removed (almost) all sprintf's.
Visual studio .net project now build multithreaded library.
Removed redundant classes SSLSocket, HttpsGetSocket, and HttpsSocket
(all SSL functionality now in TcpSocket).
Using dummy ssl types in TcpSocket if HAVE_OPENSSL is not defined.
Moved a few typedef's outside the optional sockets namespace in the file
socket_include.h.
Fixed Thread/SocketThread to avoid using method on deleted pointer.
Added CXX in Makefile.
Bugfix in SocketThread so the correct sockethandler will be used by the
detached socket object.
Added full mutex threadsafe operations. The old _THREADSAFE_SOCKETS
Makefile option is no longer in use.
Improved graceful shutdown of tcp connections when possible.
Moved address resolution methods from class Socket to Utility. The methods
are isip, u2ip, l2ip.
Added fix for unassigned names in httpdform parser.
1.9.9
-----
Trying to remove all dynamic_cast's. They are used in ListenSocket to
check that the Create method returns correct type, and in the socket
handler to give extra functionality to tcp sockets.
New callback OnDisconnect is called only when a connected tcp socket
is set for reconnect, and has lost connection.
Memory leak in TcpSocket output buffering fixed.
HttpGetSocket.url_this fixed.
Replaced HttpGetSocket.m_content string with an allocated byte buffer.
Fix bug in Utility::rfc1738_decode.
SocketHandler.Select can be called without parameters, which means it
will not return until an event has been received by a socket.
Automatic purging of tcp sockets that hang around too long with data
still left to send.
Added virtual destructor for ICrypt pure virtual.
1.9.8
-----
Nasty bug fixed on macosx that caused OnConnect to be called even if
the connection failed.
SSL client functionality restored. Cached data was not sent on connect
because the connected flag was not set.
Two new callbacks added for TcpSocket, to indicate that ssl negotiation
failed: OnSSLConnectFailed and OnSSLAcceptFailed.
HttpGetSocket: getting a https: address enables ssl....
Added fatal error if trying to use a ssl server without implementing
the initialization method (InitSSLServer).
1.9.7
-----
SocketHandler.OkToAccept now takes a socket class pointer as input
parameter, which can be used to identify which ListenSocket is
calling OkToAccept.
Treating socket exception as connection failed on win32
(if trying to connect).
Reset "flush before close" flag on write/read error.
Moved sockethandler Add logic once again, this time outside loop
checking for fd_set events..
Check if fd_set is getting full (trying to add more than FD_SETSIZE
sockets to the socket handler). Incoming connections are immediately
disconnected if the fd_set is full. TcpSocket::Open calls will
fail instantly if there is no more space in the fd_set.
Remember that FD_SETSIZE can be defined in socket_handler.h if there
is a need for larger fd_set's. The default on win32 is 64 slots which
is a bit thin. Linux and probably most unixes has 1024 slots...
On MacOsX the macro FD_COPY is used to copy the fd_set's before select().
More debug logging on exactly how a connection was established.
1.9.6
-----
Bugfix protecting the sockethandler from using deleted sockets.
(Socket class destructor calls SocketHandler.Remove in case the socket
is deleted before it is removed from the sockethandler).
Removed a lot of warnings for visual studio .net / 2005 beta.
Fix for bsd sockets sigpipe disable, using SO_NOSIGPIPE.
Solaris use putenv in HttpdSocket.
Added flag flush before close, telling a (tcp) socket to send all data
before closing even while the SetCloseAndDelete flag is set.
Default value: flush before close = true.
1.9.5
-----
Visual studio 6 and .net project files updated.
DevCpp project files updated.
Using openssl win32 installer from www.slproweb.com,
with installation location c:\OpenSSL.
Merged Sockets and SocketsEx projects in all windows projects.
Added winsock error texts.
ListenSocket.Bind slightly modified - if port 0 random assigned is
needed, 0 has to be specified in the Bind call (before this release
a Bind call with no parameters had the same effect).
Ipv6 support has been improved, with many of the ipv4/ipv6 methods
overall merged into one. Ipv6 support for reconnect and connection retry.
The connection pool now also support ipv6 connections.
Added SocketHandler.ResolverReady that indicates the resolverthread
is ready for queries.
UdpSocket constructor modified to also include an ipv6 boolean
parameter, because the socket file descriptor is created in the
constructor.
Change: UdpSocket.Bind returns 0 on success, -1 on failure, just like
ListenSocket<>.Bind.
Connection pool disabled by default. Use SocketHandler.EnablePool to
turn it back on.
HttpDebugSocket: Added first line of request (method url httpversion) to
page echoing the request.
TcpSocket ssl private key callback function no longer uses a static
member variable to store the password. This enables the use of any number
of private key files, each with a different password.
1.9.4
-----
Changed udp sockets to nonblocking.
1.9.3
-----
New define while compiling: _THREADSAFE_SOCKETS
This "thread safe" compile mode only protects OnWrite / SendBuf in
TcpSocket, but will probably include more sections of the code later on.
Mutex and Lock classes added.
HttpdCookies now excludes domain from the Set-Cookie http header
(if COOKIE_DOMAIN is defined as a blank string "").
Incoming connections should now respond quicker even when using a long
Select() timeout.
Documentation: All classes and Socket class members at least briefly described.
Tcp and Udp socket now shares a common virtual description of the Send
and SendBuf methods.
Fixed bug that caused too long connection timeouts.
UDP sockets reads up to 10 messages in one read event.
1.9.2
-----
Support for HttpdSocket http/1.1 keep-alive operation added.
Fiddling with the connection / reconnect code. Not perfect by a long shot.
If a connection timeout is set, and the socket is supposed to reconnect,
the socket will wait the defined connection timeout until a connection
retry is made even if the connection fails immediately.
OnConnectFailed() will only be called after all connection retries has
been attempted.
OnConnectRetry() will be called before each connection retry. Return
false from this callback method to abort connection retries and kill the
socket permanently.
Data sent before / between connection is preserved, whatever that's worth.
Added optional namespace for the entire library.
1.9.1
-----
Added SetConnected() in ListenSocket.h for TcpSocket's on accept.
If not, all incoming tcp connections refused to send their data.
1.9
---
Added reconnect and connection retry for TcpSocket's.
New callbacks:
OnConnectRetry() can return false to abort connection retries.
OnReconnect() when a connection has resumed.
1.8.7
-----
Added methods GetSsl() and GetSslContext() to access openssl structures
SSL resp. SSL_CTX in TcpSocket and SSLSocket.
HttpGetSocket no longer reports an error when initialized with an empty
filename.
SocketHandler::GetCount now returns actual number of active socket plus
number of sockets to be added to active sockets list.
1.8.6
-----
Socket::DisableRead - use this when creating a socket only for output
(the file descriptor will not be added to the read fd_set on select).
Added check to make sure no more than FD_SETSIZE sockets are added to
the socket handler.
1.8.5
-----
ReadLine fixed.
1.8.4
-----
Fixed a buffer problem that lost a byte for each read when doing large
http transfers (HTTPSocket, HttpsSocket, TcpSocket).
Added classes mentioned in v1.8.3...
Thread class implemented for win32 (not tested)
1.8.3
-----
(OnWriteComplete - pending)
(IFile - File - MemFile)
(HttpdSocket - HttpdForm - HttpdCookies)
Incoming sockets are no longer blocking
OnWrite no longer disconnect on EAGAIN error code
SSLSocket has been integrated with TcpSocket (still experimental)
1.8.2
-----
Removed warning about read after shutdown.
Socket does not try to do shutdown/close if the file descriptor is invalid.
1.8
---
ListenSocketBase functionality moved to ListenSocket template class.
The important addition is the Create() method in Socket - use that to
create a socket instance with an alternative constructor if needed.
TcpSocket::Open bugfix - sometimes returned false (connection failed)
although the connection was perfectly fine.
Socks4 client functionality added for outgoing connections. See new
SetSocks4Host, SetSocks4Port, SetSocks4Userid and SetSocks4TryDirect
methods in SocketHandler.
HttpGetSocket stores retrieved document in a private string member
variable, reducing the need for disk access.
Asynchronous DNS functionality added. Use the new SocketHandler method
EnableResolver() to enable this for resolving of all outgoing connections.
1.7.6
-----
Small changes in UdpSocket
New class ListenSocketBase as an alternative to ListenSocket<> template
class
New callback in Socket: Create - used by ListenSocketBase
1.7.5
-----
New callback on socket class: OnOptions, called when a new socket has
been created, to set options like SetReuse and SetKeepalive.
New get methods on MinionSocket.
Socket::Close now does a recv() after shutdown().
New logging level: Info
1.7.2
-----
HttpsGetSocket::url_this default port changed to 443 (was 80).
TcpSocket buffer sizes adjusted.
Switch off LineProtocol when reading the http body in HTTPSocket and
HttpsSocket.
1.7
---
HttpPostSocket added functionality, able to switch between url-encoded
form-data or multipart/form-data.
Connection pooling on TcpSocket's; When SetRetain() is called on a client
socket (that use Open / OnConnect), that sockets connection will be left
open and reused by the next TcpSocket the tries to open a new connection to
the same host / port.
This construction gives HTTPSocket HTTP/1.1 support for keep-alive
connections.
Pooled connections are stored as PoolSocket objects in the SocketHandler
socket list, and supervised like any other socket - if a pooled connection
is closed by the remote end, it's removed by the SocketHandler.
1.6.4
-----
Socket::SetParent / ::GetParent added, as a way to find out which
ListenSocket created the Socket. GetParent returns the pointer to the
ListenSocket object, or NULL if the Socket was created by the
programmer.
Win32: WSA startup code is wrapped in a class, which is created as a
static instance in Socket. This should automatically initialize
winsock when the first Socket is created.
1.6.3
-----
"errno" and "strerror" has been replaced by Errno and StrError,
and is defined for each operating system environment.
New classes for HTTP: HttpPutSocket, HttpPostSocket, HttpDebugSocket.
1.6.2
-----
Bugfix in ListenSocket, when opening a random port GetPort() returned
wrong port number - this is now fixed.
Defining methods depending on ipv4 or ipv6 was removed, and all ipv4 methods
renamed to their original names - without the '4'.
1.6.1
-----
Dummy copy constructor / assignment operator added to classes that can't be
copied by default.
Minor improvements to HTTPSocket.
Removed typedef string_v - collision with other projects that use same name
for std::vector<std::string> instead of internal use std::list<std::vector>
1.6
---
Improvements on win32 compile and linking. Remember to turn on rtti
information (/GR in visual studio), because I tend to use dynamic_cast a lot.
It is now possible to exclude openssl specific code, by not having
HAVE_OPENSSL defined at compile time.
Define HAVE_OPENSSL in Makefile or project file if openssl is installed
on your machine.
Bugfix in CircularBuffer. It finally works.
Renamed CircularBuffer method GetCount to "ByteCounter" - the method returns
the total number of bytes to have ever gone through the buffer.
Improved logging, and cleaned up old debug printouts.
Fixed a number of memory leaks that would occur in an application that
creates and recreates a lot of SocketHandler's, and also in the threading
part of the library.
Some optimizations for speed.
1.5.4
-----
UdpSocket: Broadcast flag, Multicast stuff
1.5.3
-----
SocketHandler no longer resolves local hostname on startup.
On hosts with unresolvable hostname this would cause a delay on startup.
Changed unix socket i/o from read/write to recv/send with MSG_NOSIGNAL
flag, to avoid sigpipe
- see readsocket/writesocket macros in socket_include.h.
1.5
---
New callback: OnConnectFailed
new / modified methods to support ipv6:
Socket::CreateSocket6
Socket::u2ip
Socket::l2ip
Socket::GetRemoteIP6
Socket::IsIpv6
04-04-12
--------
void TcpSocket::OnRawData(const char *,size_t)
called when new data is read
bool SocketHandler::OkToAccept()
called by ListenSocket - default implementation returns true
@@ -1,103 +0,0 @@
#include "Debug.h"
#include <stdarg.h>
#include <cstring>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
std::map<unsigned long, int> Debug::m_level;
const char *Debug::colors[] = {
"\x1B[0;0m", // &n */
"\x1B[0;0m\x1B[31m", // &r */
"\x1B[0;0m\x1B[32m", // &g */
"\x1B[0;0m\x1B[33m", // &y */
"\x1B[0;0m\x1B[34m", // &b */
"\x1B[0;0m\x1B[35m", // &m */
"\x1B[0;0m\x1B[36m", // &c */
"\x1B[0;0m\x1B[37m", // &w */
"\x1B[1;31m", // &R */
"\x1B[1;32m", // &G */
"\x1B[1;33m", // &Y */
"\x1B[1;34m", // &B */
"\x1B[1;35m", // &M */
"\x1B[1;36m", // &C */
"\x1B[1;37m" }; // &W */
void Debug::Print(const char *format, ...)
{
char slask[5000]; // temporary for vsprintf / vsnprintf
va_list ap;
va_start(ap, format);
vsnprintf(slask, sizeof(slask), format, ap);
va_end(ap);
fprintf(stderr, "%s", colors[Utility::ThreadID() % 14 + 1]);
for (int i = 0; i < m_level[Utility::ThreadID()]; i++)
fprintf(stderr, " ");
if (slask[strlen(slask) - 1] == '\n')
slask[strlen(slask) - 1] = 0;
fprintf(stderr, "%s%s\n", slask, colors[0]);
}
Debug& Debug::operator<<(const char * str)
{
m_line += str;
return *this;
}
Debug& Debug::operator<<(const std::string& str)
{
m_line += str;
return *this;
}
Debug& Debug::operator<<(short l)
{
m_line += Utility::l2string(l);
return *this;
}
Debug& Debug::operator<<(int l)
{
m_line += Utility::l2string(l);
return *this;
}
Debug& Debug::operator<<(long l)
{
m_line += Utility::l2string(l);
return *this;
}
Debug& Debug::operator<<(double d)
{
char slask[100];
snprintf(slask, sizeof(slask), "%f", d);
m_line += slask;
return *this;
}
Debug& Debug::operator<<(endl)
{
Print("%s", m_line.c_str());
m_line = "";
return *this;
}
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
@@ -1,87 +0,0 @@
#ifndef _SOCKETS_Debug_H
#define _SOCKETS_Debug_H
#include "sockets-config.h"
#include "Utility.h"
#include <stdio.h>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class Debug
{
static const char *colors[];
public:
class endl
{
public:
endl() {}
virtual ~endl() {}
};
public:
Debug() {}
Debug(const std::string& x) : m_id(0), m_text(x) {
fprintf(stderr, "%s", colors[Utility::ThreadID() % 14 + 1]);
for (int i = 0; i < m_level[Utility::ThreadID()]; i++)
fprintf(stderr, " ");
fprintf(stderr, "%s%s\n", x.c_str(), colors[0]);
m_level[Utility::ThreadID()]++;
}
Debug(int id, const std::string& x) : m_id(id), m_text(x) {
fprintf(stderr, "%s", colors[Utility::ThreadID() % 14 + 1]);
for (int i = 0; i < m_level[Utility::ThreadID()]; i++)
fprintf(stderr, " ");
fprintf(stderr, "%d> %s%s\n", m_id, x.c_str(), colors[0]);
m_level[Utility::ThreadID()]++;
}
~Debug() {
if (!m_text.empty()) {
if (m_level[Utility::ThreadID()])
m_level[Utility::ThreadID()]--;
fprintf(stderr, "%s", colors[Utility::ThreadID() % 14 + 1]);
for (int i = 0; i < m_level[Utility::ThreadID()]; i++)
fprintf(stderr, " ");
if (m_id)
fprintf(stderr, "%d> /%s%s\n", m_id, m_text.c_str(), colors[0]);
else
fprintf(stderr, "/%s%s\n", m_text.c_str(), colors[0]);
fflush(stderr);
}
}
static void Print(const char *format, ...);
Debug& operator<<(const char *);
Debug& operator<<(const std::string& );
Debug& operator<<(short);
Debug& operator<<(int);
Debug& operator<<(long);
Debug& operator<<(double);
Debug& operator<<(endl);
private:
int m_id;
std::string m_text;
static std::map<unsigned long, int> m_level;
std::string m_line;
};
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // _SOCKETS_Debug_H
@@ -1,93 +0,0 @@
/** \file Event.cpp
** \date 2005-12-07
** \author grymse@alhem.net
**/
/*
Copyright (C) 2005-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "Event.h"
#ifdef _WIN32
#else
#include <sys/time.h>
#endif
//#include "IEventOwner.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
// statics
long Event::m_unique_id = 0;
Event::Event(IEventOwner *from,long sec,long usec,unsigned long data) : m_from(from), m_data(data), m_time(sec, usec), m_id(++m_unique_id)
{
}
Event::~Event()
{
}
bool Event::operator<(Event& e)
{
return m_time < e.m_time;
}
long Event::GetID() const
{
return m_id;
}
const EventTime& Event::GetTime() const
{
return m_time;
}
IEventOwner *Event::GetFrom() const
{
return m_from;
}
unsigned long Event::Data() const
{
return m_data;
}
#ifdef SOCKETS_NAMESPACE
}
#endif
@@ -1,83 +0,0 @@
/** \file Event.h
** \date 2005-12-07
** \author grymse@alhem.net
**/
/*
Copyright (C) 2005-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_Event_H
#define _SOCKETS_Event_H
#include "sockets-config.h"
#ifdef _WIN32
#else
#include <sys/select.h>
#endif
#include "EventTime.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class IEventOwner;
/** Store information about a timer event.
\ingroup timer */
class Event
{
public:
Event(IEventOwner *,long sec,long usec,unsigned long data = 0);
~Event();
bool operator<(Event&);
long GetID() const;
const EventTime& GetTime() const;
IEventOwner *GetFrom() const;
unsigned long Data() const;
private:
Event(const Event& ) {} // copy constructor
Event& operator=(const Event& ) {
return *this; // assignment operator
}
IEventOwner *m_from;
unsigned long m_data;
EventTime m_time;
static long m_unique_id;
long m_id;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_Event_H
@@ -1,209 +0,0 @@
/** \file EventHandler.cpp
** \date 2005-12-07
** \author grymse@alhem.net
**/
/*
Copyright (C) 2005-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#include "EventHandler.h"
#include "IEventOwner.h"
#include "Event.h"
#include "TcpSocket.h"
#include "ListenSocket.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
EventHandler::EventHandler(StdLog *p) : SocketHandler(p), m_quit(false)
{
EnableRelease();
}
EventHandler::EventHandler(IMutex& m,StdLog *p) : SocketHandler(m, p), m_quit(false)
{
EnableRelease();
}
EventHandler::~EventHandler()
{
while (m_events.size())
{
std::list<Event *>::iterator it = m_events.begin();
Event *e = *it;
e -> GetFrom() -> SetHandlerInvalid();
delete e;
m_events.erase(it);
}
}
bool EventHandler::GetTimeUntilNextEvent(struct timeval *tv)
{
if (!m_events.size())
return false;
std::list<Event *>::iterator it = m_events.begin();
if (it != m_events.end())
{
EventTime now;
mytime_t diff = (*it) -> GetTime() - now;
if (diff < 1)
{
diff = 1;
}
tv -> tv_sec = static_cast<long>(diff / 1000000);
tv -> tv_usec = static_cast<long>(diff % 1000000);
return true;
}
return false;
}
void EventHandler::CheckEvents()
{
EventTime now;
std::list<Event *>::iterator it = m_events.begin();
while (it != m_events.end() && (*it) -> GetTime() < now)
{
Event *e = *it;
Socket *s = dynamic_cast<Socket *>(e -> GetFrom());
/*
s == NULL This is another object implementing 'IEventOwner' and not a socket.
s != NULL This is a Socket implementing IEventOwner, and we can check that the
object instance still is valid using SocketHandler::Valid.
*/
if (!s || (s && Valid( e -> Data() )))
{
e -> GetFrom() -> OnEvent(e -> GetID());
}
for (it = m_events.begin(); it != m_events.end(); ++it)
if (*it == e)
{
delete e;
break;
}
if (it != m_events.end())
m_events.erase(it);
it = m_events.begin();
}
}
long EventHandler::AddEvent(IEventOwner *from,long sec,long usec)
{
Socket *s = dynamic_cast<Socket *>(from);
Event *e = new Event(from, sec, usec, s ? s -> UniqueIdentifier() : 0);
std::list<Event *>::iterator it = m_events.begin();
while (it != m_events.end() && *(*it) < *e)
{
++it;
}
m_events.insert(it, e);
Release();
return e -> GetID();
}
void EventHandler::ClearEvents(IEventOwner *from)
{
bool repeat;
do
{
repeat = false;
for (std::list<Event *>::iterator it = m_events.begin(); it != m_events.end(); ++it)
{
Event *e = *it;
if (e -> GetFrom() == from)
{
delete e;
m_events.erase(it);
repeat = true;
break;
}
}
} while (repeat);
}
void EventHandler::EventLoop()
{
while (!m_quit)
{
struct timeval tv;
if (GetTimeUntilNextEvent(&tv))
{
Select(&tv);
CheckEvents();
}
else
{
Select();
}
}
}
void EventHandler::SetQuit(bool x)
{
m_quit = x;
}
void EventHandler::RemoveEvent(IEventOwner *from, long eid)
{
for (std::list<Event *>::iterator it = m_events.begin(); it != m_events.end(); ++it)
{
Event *e = *it;
if (from == e -> GetFrom() && eid == e -> GetID())
{
delete e;
m_events.erase(it);
break;
}
}
}
void EventHandler::Add(Socket *p)
{
SocketHandler::Add( p );
}
#ifdef SOCKETS_NAMESPACE
}
#endif
@@ -1,88 +0,0 @@
/** \file EventHandler.h
** \date 2005-12-07
** \author grymse@alhem.net
**/
/*
Copyright (C) 2005-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_EventHandler_H
#define _SOCKETS_EventHandler_H
#include "sockets-config.h"
#include "SocketHandler.h"
#include "IEventHandler.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class StdLog;
class IEventOwner;
class Event;
class TcpSocket;
/** SocketHandler implementing the IEventHandler interface.
\ingroup timer */
class EventHandler : public SocketHandler,public IEventHandler
{
public:
EventHandler(StdLog * = NULL);
EventHandler(IMutex&,StdLog * = NULL);
~EventHandler();
bool GetTimeUntilNextEvent(struct timeval *tv);
void CheckEvents();
long AddEvent(IEventOwner *from,long sec,long usec);
void ClearEvents(IEventOwner *from);
void RemoveEvent(IEventOwner *from,long eid);
/** SocketHandler while() loop implemented with event functionality. */
void EventLoop();
/** Stop event loop. */
void SetQuit(bool = true);
void Add(Socket *);
private:
EventHandler(const EventHandler& ) {} // copy constructor
EventHandler& operator=(const EventHandler& ) {
return *this; // assignment operator
}
std::list<Event *> m_events;
bool m_quit;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_EventHandler_H
@@ -1,107 +0,0 @@
/** \file EventTime.cpp
** \date 2005-12-07
** \author grymse@alhem.net
**/
/*
Copyright (C) 2005-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef MACOSX
#include <stdint.h>
#include <sys/types.h>
#include <signal.h>
#endif
#include "EventTime.h"
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/select.h>
#include <sys/time.h>
#endif
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
EventTime::EventTime() : m_time(Tick())
{
}
EventTime::EventTime(mytime_t sec,long usec) : m_time(Tick())
{
m_time += sec * 1000000 + usec;
}
EventTime::~EventTime()
{
}
mytime_t EventTime::Tick()
{
mytime_t t;
#ifdef _WIN32
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
t = ft.dwHighDateTime;
t = t << 32;
t += ft.dwLowDateTime;
t /= 10; // us
#else
struct timeval tv;
struct timezone tz;
gettimeofday(&tv, &tz);
t = tv.tv_sec;
t *= 1000000;
t += tv.tv_usec;
#endif
return t;
}
EventTime EventTime::operator - (const EventTime& x) const
{
EventTime t;
t.m_time = m_time - x.m_time;
return t;
}
bool EventTime::operator < (const EventTime& x) const
{
return m_time < x.m_time;
}
#ifdef SOCKETS_NAMESPACE
}
#endif
@@ -1,84 +0,0 @@
/** \file EventTime.h
** \date 2005-12-07
** \author grymse@alhem.net
**/
/*
Copyright (C) 2005-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_EventTime_H
#define _SOCKETS_EventTime_H
#include "sockets-config.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
#if defined( _WIN32) && !defined(__CYGWIN__)
typedef __int64 mytime_t;
#else
#include <inttypes.h> // int64_t
typedef int64_t mytime_t;
#endif
/** \defgroup timer EventTimer event handling */
/** EventTime primitive, returns current time as a 64-bit number.
\ingroup timer */
class EventTime
{
public:
EventTime();
EventTime(mytime_t sec,long usec);
~EventTime();
static mytime_t Tick();
operator mytime_t () {
return m_time;
}
EventTime operator - (const EventTime& x) const;
bool operator < (const EventTime& x) const;
private:
EventTime(const EventTime& ) {} // copy constructor
EventTime& operator=(const EventTime& ) {
return *this; // assignment operator
}
mytime_t m_time;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_EventTime_H
@@ -1,66 +0,0 @@
/**
** \file Exception.cpp
** \date 2007-09-28
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#include "Exception.h"
#include "Utility.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
Exception::Exception(const std::string& description) : m_description(description)
, m_stack(Utility::Stack())
{
}
const std::string Exception::ToString() const
{
return m_description;
}
const std::string Exception::Stack() const
{
return m_stack;
}
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
@@ -1,74 +0,0 @@
/**
** \file Exception.h
** \date 2007-09-28
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _Sockets_Exception_H
#define _Sockets_Exception_H
#include "sockets-config.h"
#include <string>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class Exception
{
public:
Exception(const std::string& description);
virtual ~Exception() {}
virtual const std::string ToString() const;
virtual const std::string Stack() const;
Exception(const Exception& ) {} // copy constructor
Exception& operator=(const Exception& ) {
return *this; // assignment operator
}
private:
std::string m_description;
std::string m_stack;
};
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // _Sockets_Exception_H
@@ -1,203 +0,0 @@
/** \file File.cpp
** \date 2005-04-25
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "File.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
File::File()
:m_fil(NULL)
,m_b_close(true)
,m_rptr(0)
,m_wptr(0)
{
}
File::File(FILE *fil)
:m_fil(fil)
,m_b_close(false)
,m_rptr(0)
,m_wptr(0)
{
}
File::File(const std::string& path, const std::string& mode)
:m_fil(NULL)
,m_b_close(true)
,m_rptr(0)
,m_wptr(0)
{
fopen(path, mode);
}
File::~File()
{
if (m_b_close)
{
fclose();
}
}
bool File::fopen(const std::string& path, const std::string& mode)
{
m_path = path;
m_mode = mode;
#if defined( _WIN32) && !defined(__CYGWIN__)
if (fopen_s(&m_fil, path.c_str(), mode.c_str()))
m_fil = NULL;
#else
m_fil = ::fopen(path.c_str(), mode.c_str());
#endif
return m_fil ? true : false;
}
void File::fclose() const
{
if (m_fil)
{
::fclose(m_fil);
m_fil = NULL;
}
}
size_t File::fread(char *ptr, size_t size, size_t nmemb) const
{
size_t r = 0;
if (m_fil)
{
fseek(m_fil, m_rptr, SEEK_SET);
r = ::fread(ptr, size, nmemb, m_fil);
m_rptr = ftell(m_fil);
}
return r;
}
size_t File::fwrite(const char *ptr, size_t size, size_t nmemb)
{
size_t r = 0;
if (m_fil)
{
fseek(m_fil, m_wptr, SEEK_SET);
r = ::fwrite(ptr, size, nmemb, m_fil);
m_wptr = ftell(m_fil);
}
return r;
}
char *File::fgets(char *s, int size) const
{
char *r = NULL;
if (m_fil)
{
fseek(m_fil, m_rptr, SEEK_SET);
r = ::fgets(s, size, m_fil);
m_rptr = ftell(m_fil);
}
return r;
}
void File::fprintf(const char *format, ...)
{
if (!m_fil)
return;
va_list ap;
va_start(ap, format);
fseek(m_fil, m_wptr, SEEK_SET);
vfprintf(m_fil, format, ap);
m_wptr = ftell(m_fil);
va_end(ap);
}
off_t File::size() const
{
struct stat st;
if (stat(m_path.c_str(), &st) == -1)
{
return 0;
}
return st.st_size;
}
bool File::eof() const
{
if (m_fil)
{
if (feof(m_fil))
return true;
}
return false;
}
void File::reset_read() const
{
m_rptr = 0;
}
void File::reset_write()
{
m_wptr = 0;
}
const std::string& File::Path() const
{
return m_path;
}
#ifdef SOCKETS_NAMESPACE
}
#endif
@@ -1,95 +0,0 @@
/** \file File.h
** \date 2005-04-25
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_File_H
#define _SOCKETS_File_H
#include "sockets-config.h"
#include "IFile.h"
#include <stdio.h>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
/** IFile implementation of a disk file.
\ingroup file */
class File : public IFile
{
public:
File();
File(FILE *);
/** convenience: calls fopen() */
File(const std::string& path, const std::string& mode);
~File();
bool fopen(const std::string& path, const std::string& mode);
void fclose() const;
size_t fread(char *, size_t, size_t) const;
size_t fwrite(const char *, size_t, size_t);
char *fgets(char *, int) const;
void fprintf(const char *format, ...);
off_t size() const;
bool eof() const;
void reset_read() const;
void reset_write();
const std::string& Path() const;
private:
File(const File& ) {} // copy constructor
File& operator=(const File& ) {
return *this; // assignment operator
}
std::string m_path;
std::string m_mode;
mutable FILE *m_fil;
bool m_b_close;
mutable long m_rptr;
long m_wptr;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_File_H
@@ -1,60 +0,0 @@
/**
** \file FileStream.cpp
** \date 2008-12-20
** \author grymse@alhem.net
**/
/*
Copyright (C) 2008-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "FileStream.h"
#include "IFile.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
FileStream::FileStream(IFile& file) : m_file(file)
{
}
size_t FileStream::IStreamRead(char *buf, size_t max_sz)
{
return m_file.fread(buf, 1, max_sz);
}
void FileStream::IStreamWrite(const char *buf, size_t sz)
{
m_file.fwrite(buf, 1, sz);
}
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
@@ -1,62 +0,0 @@
/**
** \file FileStream.h
** \date 2008-12-20
** \author grymse@alhem.net
**/
/*
Copyright (C) 2008-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_FileStream_H
#define _SOCKETS_FileStream_H
#include "IStream.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class IFile;
class FileStream : public IStream
{
public:
FileStream(IFile& file);
size_t IStreamRead(char *buf, size_t max_sz);
void IStreamWrite(const char *buf, size_t sz);
private:
IFile& m_file;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_FileStream_H
@@ -1,519 +0,0 @@
/** \file HTTPSocket.cpp
** \date 2004-04-06
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#include "HTTPSocket.h"
#include "Parse.h"
#include "ISocketHandler.h"
#include <stdarg.h>
#include <stdio.h>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
HTTPSocket::HTTPSocket(ISocketHandler& h)
:TcpSocket(h)
,m_first(true)
,m_header(true)
,m_http_version("HTTP/1.0")
,m_request(false)
,m_response(false)
,m_body_size_left(0)
,m_b_http_1_1(false)
,m_b_keepalive(false)
,m_b_chunked(false)
,m_chunk_size(0)
,m_chunk_state(0)
,m_header_count(0)
,m_max_header_count(MAX_HTTP_HEADER_COUNT)
{
SetLineProtocol();
DisableInputBuffer();
}
HTTPSocket::~HTTPSocket()
{
}
void HTTPSocket::OnRawData(const char *buf,size_t len)
{
if (!m_header)
{
if (m_b_chunked)
{
size_t ptr = 0;
while (ptr < len)
{
switch (m_chunk_state)
{
case 4:
while (ptr < len && (m_chunk_line.size() < 2 || m_chunk_line.substr(m_chunk_line.size() - 2) != "\r\n"))
m_chunk_line += buf[ptr++];
if (m_chunk_line.size() > 1 && m_chunk_line.substr(m_chunk_line.size() - 2) == "\r\n")
{
OnDataComplete();
// prepare for next request(or response)
m_b_chunked = false;
SetLineProtocol( true );
m_first = true;
m_header = true;
m_body_size_left = 0;
if (len - ptr > 0)
{
char tmp[TCP_BUFSIZE_READ];
memcpy(tmp, buf + ptr, len - ptr);
tmp[len - ptr] = 0;
OnRead( tmp, len - ptr );
ptr = len;
}
}
break;
case 0:
while (ptr < len && (m_chunk_line.size() < 2 || m_chunk_line.substr(m_chunk_line.size() - 2) != "\r\n"))
m_chunk_line += buf[ptr++];
if (m_chunk_line.size() > 1 && m_chunk_line.substr(m_chunk_line.size() - 2) == "\r\n")
{
m_chunk_line.resize(m_chunk_line.size() - 2);
Parse pa(m_chunk_line, ";");
std::string size_str = pa.getword();
m_chunk_size = Utility::hex2unsigned(size_str);
if (!m_chunk_size)
{
m_chunk_state = 4;
m_chunk_line = "";
}
else
{
m_chunk_state = 1;
m_chunk_line = "";
}
}
break;
case 1:
{
size_t left = len - ptr;
size_t sz = m_chunk_size < left ? m_chunk_size : left;
OnData(buf + ptr, sz);
m_chunk_size -= sz;
ptr += sz;
if (!m_chunk_size)
{
m_chunk_state = 2;
}
}
break;
case 2: // skip CR
ptr++;
m_chunk_state = 3;
break;
case 3: // skip LF
ptr++;
m_chunk_state = 0;
break;
}
}
}
else
if (!m_b_http_1_1 || !m_b_keepalive)
{
OnData(buf, len);
/*
request is HTTP/1.0 _or_ HTTP/1.1 and not keep-alive
This means we destroy the connection after the response has been delivered,
hence no need to reset all internal state variables for a new incoming
request.
*/
m_body_size_left -= len;
if (!m_body_size_left)
{
OnDataComplete();
}
}
else
{
size_t sz = m_body_size_left < len ? m_body_size_left : len;
OnData(buf, sz);
m_body_size_left -= sz;
if (!m_body_size_left)
{
OnDataComplete();
// prepare for next request(or response)
SetLineProtocol( true );
m_first = true;
m_header = true;
m_body_size_left = 0;
if (len - sz > 0)
{
char tmp[TCP_BUFSIZE_READ];
memcpy(tmp, buf + sz, len - sz);
tmp[len - sz] = 0;
OnRead( tmp, len - sz );
}
}
}
}
}
void HTTPSocket::OnLine(const std::string& line)
{
if (m_first)
{
Parse pa(line);
std::string str = pa.getword();
if (str.size() > 4 && Utility::ToLower(str.substr(0,5)) == "http/") // response
{
m_http_version = str;
m_status = pa.getword();
m_status_text = pa.getrest();
m_response = true;
}
else // request
{
m_method = str;
m_url = pa.getword();
size_t spl = m_url.find("?");
if (spl != std::string::npos)
{
m_uri = m_url.substr(0,spl);
m_query_string = m_url.substr(spl + 1);
}
else
{
m_uri = m_url;
m_query_string = "";
}
m_http_version = pa.getword();
m_b_http_1_1 = m_http_version.size() > 4 && m_http_version.substr(4) == "/1.1";
m_b_keepalive = m_b_http_1_1;
m_request = true;
}
m_first = false;
OnFirst();
return;
}
if (!line.size())
{
if (m_body_size_left || !m_b_http_1_1 || !m_b_keepalive || m_b_chunked)
{
SetLineProtocol(false);
m_header = false;
}
OnHeaderComplete();
if (!m_body_size_left && !m_b_chunked)
{
OnDataComplete();
}
return;
}
Parse pa(line,":");
std::string key = pa.getword();
std::string value = pa.getrest();
OnHeader(key,value);
if (Utility::ToLower(key) == "content-length")
{
m_body_size_left = atol(value.c_str());
}
if (m_b_http_1_1 && Utility::ToLower(key) == "connection")
{
m_b_keepalive = Utility::ToLower(value) != "close";
}
if (Utility::ToLower(key) == "transfer-encoding" && Utility::ToLower(value) == "chunked")
{
m_b_chunked = true;
}
/* If remote end tells us to keep connection alive, and we're operating
in http/1.1 mode (not http/1.0 mode), then we mark the socket to be
retained. */
#ifdef ENABLE_POOL
if (m_b_http_1_1 && m_b_keepalive)
{
SetRetain();
}
#endif
if (m_header_count++ > m_max_header_count)
{
SetCloseAndDelete();
Handler().LogError(this, "OnLine", m_header_count, "http header count exceeds builtin limit of (" + Utility::l2string(m_max_header_count) + ")", LOG_LEVEL_FATAL);
}
}
void HTTPSocket::SendResponse()
{
std::string msg;
msg = m_http_version + " " + m_status + " " + m_status_text + "\r\n";
for (string_m::iterator it = m_response_header.begin(); it != m_response_header.end(); ++it)
{
std::string key = (*it).first;
std::string val = (*it).second;
msg += key + ": " + val + "\r\n";
}
for (std::list<std::pair<std::string, std::string> >::iterator it2 = m_response_header_append.begin(); it2 != m_response_header_append.end(); ++it2)
{
msg += it2 -> first + ": " + it2 -> second + "\r\n";
}
msg += "\r\n";
Send( msg );
}
void HTTPSocket::AddResponseHeader(const std::string& header, const char *format, ...)
{
char slask[8192]; // temporary for vsprintf / vsnprintf
va_list ap;
va_start(ap, format);
vsnprintf(slask, sizeof(slask), format, ap);
va_end(ap);
m_response_header[header] = slask;
}
void HTTPSocket::SendRequest()
{
std::string msg;
msg = m_method + " " + m_url + " " + m_http_version + "\r\n";
for (string_m::iterator it = m_response_header.begin(); it != m_response_header.end(); ++it)
{
std::string key = (*it).first;
std::string val = (*it).second;
msg += key + ": " + val + "\r\n";
}
msg += "\r\n";
Send( msg );
}
std::string HTTPSocket::MyUseragent()
{
std::string version = "C++Sockets/";
#ifdef _VERSION
version += _VERSION;
#endif
return version;
}
void HTTPSocket::Reset()
{
m_first = true;
m_header = true;
m_request = false;
m_response = false;
SetLineProtocol(true);
while (m_response_header.size())
{
string_m::iterator it = m_response_header.begin();
m_response_header.erase(it);
}
while (m_response_header_append.size())
{
std::list<std::pair<std::string, std::string> >::iterator it = m_response_header_append.begin();
m_response_header_append.erase(it);
}
m_header_count = 0;
}
const std::string& HTTPSocket::GetMethod()
{
return m_method;
}
void HTTPSocket::SetMethod(const std::string& x)
{
m_method = x;
}
const std::string& HTTPSocket::GetUrl()
{
return m_url;
}
void HTTPSocket::SetUrl(const std::string& x)
{
m_url = x;
}
const std::string& HTTPSocket::GetUri()
{
return m_uri;
}
const std::string& HTTPSocket::GetQueryString()
{
return m_query_string;
}
const std::string& HTTPSocket::GetHttpVersion()
{
return m_http_version;
}
const std::string& HTTPSocket::GetStatus()
{
return m_status;
}
const std::string& HTTPSocket::GetStatusText()
{
return m_status_text;
}
bool HTTPSocket::IsRequest()
{
return m_request;
}
bool HTTPSocket::IsResponse()
{
return m_response;
}
void HTTPSocket::SetHttpVersion(const std::string& x)
{
m_http_version = x;
}
void HTTPSocket::SetStatus(const std::string& x)
{
m_status = x;
}
void HTTPSocket::SetStatusText(const std::string& x)
{
m_status_text = x;
}
void HTTPSocket::AddResponseHeader(const std::string& x,const std::string& y)
{
m_response_header[x] = y;
}
void HTTPSocket::AppendResponseHeader(const std::string& x,const std::string& y)
{
m_response_header_append.push_back(std::pair<std::string, std::string>(x,y));
}
void HTTPSocket::SetUri(const std::string& x)
{
m_uri = x;
}
void HTTPSocket::url_this(const std::string& url_in,std::string& protocol,std::string& host,port_t& port,std::string& url,std::string& file)
{
Parse pa(url_in,"/");
protocol = pa.getword(); // http
if (!strcasecmp(protocol.c_str(), "https:"))
{
#ifdef HAVE_OPENSSL
EnableSSL();
#else
Handler().LogError(this, "url_this", -1, "SSL not available", LOG_LEVEL_WARNING);
#endif
port = 443;
}
else
{
port = 80;
}
host = pa.getword();
if (strstr(host.c_str(),":"))
{
Parse pa(host,":");
pa.getword(host);
port = static_cast<port_t>(pa.getvalue());
}
url = "/" + pa.getrest();
{
Parse pa(url,"/");
std::string tmp = pa.getword();
while (tmp.size())
{
file = tmp;
tmp = pa.getword();
}
}
} // url_this
bool HTTPSocket::ResponseHeaderIsSet(const std::string& name)
{
string_m::iterator it = m_response_header.find( name );
if (it != m_response_header.end())
{
return true;
}
std::list<std::pair<std::string, std::string> >::iterator it2;
for (it2 = m_response_header_append.begin(); it2 != m_response_header_append.end(); ++it2)
{
std::pair<std::string, std::string>& ref = *it2;
if (!strcasecmp(ref.first.c_str(), name.c_str()) )
{
return true;
}
}
return false;
}
#ifdef SOCKETS_NAMESPACE
}
#endif
@@ -1,175 +0,0 @@
/** \file HTTPSocket.h Class HTTPSocket definition.
** \date 2004-04-06
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_HTTPSocket_H
#define _SOCKETS_HTTPSocket_H
#include "sockets-config.h"
#include "TcpSocket.h"
#include "Utility.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
/** \defgroup http HTTP Sockets */
/** HTTP request/response base class.
\ingroup http */
class HTTPSocket : public TcpSocket
{
/** map to hold http header values. */
typedef Utility::ncmap<std::string> string_m;
public:
HTTPSocket(ISocketHandler& );
~HTTPSocket();
void OnRawData(const char *buf,size_t len);
void OnLine(const std::string& line);
/** Callback executes when first line has been received.
GetMethod, GetUrl/GetUri, and GetHttpVersion are valid when this callback is executed. */
virtual void OnFirst() = 0;
/** For each header line this callback is executed.
\param key Http header name
\param value Http header value */
virtual void OnHeader(const std::string& key,const std::string& value) = 0;
/** Callback fires when all http headers have been received. */
virtual void OnHeaderComplete() = 0;
/** Chunk of http body data recevied. */
virtual void OnData(const char *,size_t) = 0;
/** The full request/response body has been received. */
virtual void OnDataComplete() {}
/** Get http method from incoming request, ie GET/POST/PUT etc */
const std::string& GetMethod();
/** Set http method to be used in request. */
void SetMethod(const std::string& x);
/** Get url from request. */
const std::string& GetUrl();
/** Set url to be used in outgoing request. */
void SetUrl(const std::string& x);
/** Get part of url before '?' character. */
const std::string& GetUri();
/** Now why would I need this when there is a SetUrl method? */
void SetUri(const std::string& x);
/** Get part of url after '?' character. */
const std::string& GetQueryString();
/** Get http version from incoming request/response. */
const std::string& GetHttpVersion();
/** Get http status from incoming response. */
const std::string& GetStatus();
/** Get http statustext from incoming response. */
const std::string& GetStatusText();
/** Incoming header has been identified as a request (method url http_version\r\n). */
bool IsRequest();
/** Incoming header has been identified as a response (http_version status status_text\r\n). */
bool IsResponse();
/** Set http version to be used in outgoing request/response. */
void SetHttpVersion(const std::string& x);
/** Set http status for outgoing response. */
void SetStatus(const std::string& x);
/** Set http statustext for outgoing response. */
void SetStatusText(const std::string& x);
/** Add (and replace if exists) http header. */
void AddResponseHeader(const std::string& x,const std::string& y);
/** Add (and replace if exists) http header. */
void AddResponseHeader(const std::string& x,const char *format, ...);
/** Add http header. */
void AppendResponseHeader(const std::string& x,const std::string& y);
/** See if http header 'name' has been set. */
bool ResponseHeaderIsSet(const std::string& name);
/** Send response prepared with calls to methods SetHttpVersion, SetStatus, SetStatusText,
and AddResponseHeader. */
void SendResponse();
/** Send request prepared with calls to methods SetMethod, SetUrl, SetHttpVersion,
and AddResponseHeader. */
void SendRequest();
/** Implement this to return your own User-agent string. */
virtual std::string MyUseragent();
/** Parse url. If protocol is https, EnableSSL() will be called. */
void url_this(const std::string& url_in,std::string& protocol,std::string& host,port_t& port,std::string& url,std::string& file);
/** Transfer coding 'chunked' */
bool IsChunked() {
return m_b_chunked;
}
protected:
HTTPSocket(const HTTPSocket& s) : TcpSocket(s) {}
/** Reset state of socket to sucessfully implement keep-alive. */
virtual void Reset();
void SetMaxHeaderCount(int x) {
m_max_header_count = x;
}
private:
HTTPSocket& operator=(const HTTPSocket& ) {
return *this;
}
bool m_first;
bool m_header;
std::string m_line;
std::string m_method;
std::string m_url;
std::string m_uri;
std::string m_query_string;
std::string m_http_version;
std::string m_status;
std::string m_status_text;
bool m_request;
bool m_response;
string_m m_response_header;
size_t m_body_size_left;
bool m_b_http_1_1;
bool m_b_keepalive;
std::list<std::pair<std::string, std::string> > m_response_header_append;
bool m_b_chunked;
size_t m_chunk_size;
int m_chunk_state;
std::string m_chunk_line;
int m_header_count;
int m_max_header_count;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_HTTPSocket_H
@@ -1,215 +0,0 @@
/**
** \file AjpBaseSocket.cpp
** \date 2007-10-05
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#include "HttpBaseSocket.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
#ifdef _DEBUG
#define DEB(x) x
#else
#define DEB(x)
#endif
HttpBaseSocket::HttpBaseSocket(ISocketHandler& h)
:HTTPSocket(h)
,m_b_keepalive(false)
{
}
HttpBaseSocket::~HttpBaseSocket()
{
}
void HttpBaseSocket::OnFirst()
{
DEB(fprintf(stderr, " %s %s %s\n", GetMethod().c_str(), GetUri().c_str(), GetHttpVersion().c_str());)
m_req.SetHttpMethod( GetMethod() );
m_req.SetUri( GetUri() );
m_req.SetHttpVersion( GetHttpVersion() );
if (Utility::ToLower(GetMethod()) == "get" && !GetQueryString().empty())
{
m_req.SetAttribute("query_string", GetQueryString() );
}
m_req.SetRemoteAddr( GetRemoteAddress() );
m_req.SetRemoteHost( "" ); // %!
m_req.SetServerName( GetSockAddress() );
m_req.SetServerPort( GetSockPort() );
}
void HttpBaseSocket::OnHeader(const std::string& key,const std::string& value)
{
DEB(fprintf(stderr, " (request)OnHeader %s: %s\n", key.c_str(), value.c_str());)
if (Utility::ToLower(key) == "cookie")
m_req.AddCookie(value);
else
m_req.SetHeader(key, value);
}
void HttpBaseSocket::OnHeaderComplete()
{
m_body_size_left = atol( m_req.Header("content-length").c_str() );
if (m_body_size_left > 0)
{
m_req.InitBody( m_body_size_left );
}
else
{
// execute
Execute();
}
}
void HttpBaseSocket::OnData(const char *buf,size_t sz)
{
m_req.Write( buf, sz );
m_body_size_left -= sz;
if (!m_body_size_left)
{
m_req.CloseBody();
// execute
Execute();
}
}
// --------------------------------------------------------------------------------------
void HttpBaseSocket::Execute()
{
// parse form data / query_string and cookie header if available
m_req.ParseBody();
DEB(printf(" *** http version: %s\n", m_req.HttpVersion().c_str());
printf(" *** connection: %s\n", m_req.Header("connection").c_str());)
if ( !(m_req.HttpVersion().size() > 4 && m_req.HttpVersion().substr(m_req.HttpVersion().size() - 4) == "/1.1") ||
m_req.Header("connection") == "close")
{
m_b_keepalive = false;
DEB(printf(" *** keepalive: false\n");)
}
else
{
m_b_keepalive = true;
DEB(printf(" *** keepalive: true\n");)
}
// prepare page
OnExec( m_req );
m_req.Reset();
Reset();
}
// --------------------------------------------------------------------------------------
void HttpBaseSocket::Respond(const HttpResponse& res)
{
m_res = res;
SetHttpVersion( m_res.HttpVersion() );
SetStatus( Utility::l2string(m_res.HttpStatusCode()) );
SetStatusText( m_res.HttpStatusMsg() );
if (!ResponseHeaderIsSet("content-length"))
{
AddResponseHeader( "content-length", Utility::l2string( m_res.GetFile().size() ) );
}
for (Utility::ncmap<std::string>::const_iterator it = m_res.Headers().begin(); it != m_res.Headers().end(); ++it)
{
AddResponseHeader( it -> first, it -> second );
}
std::list<std::string> vec = m_res.CookieNames();
for (std::list<std::string>::iterator it2 = vec.begin(); it2 != vec.end(); ++it2)
{
AppendResponseHeader( "set-cookie", m_res.Cookie(*it2) );
}
SendResponse();
OnTransferLimit();
}
// --------------------------------------------------------------------------------------
void HttpBaseSocket::OnTransferLimit()
{
char msg[32768];
size_t n = m_res.GetFile().fread(msg, 1, 32768);
while (n > 0)
{
SendBuf( msg, n );
if (GetOutputLength() > 1)
{
SetTransferLimit( 1 );
break;
}
n = m_res.GetFile().fread(msg, 1, 32768);
}
if (!GetOutputLength())
{
SetTransferLimit(0);
m_res.GetFile().fclose();
OnResponseComplete();
if (!m_b_keepalive)
{
SetCloseAndDelete();
}
}
}
// --------------------------------------------------------------------------------------
void HttpBaseSocket::Reset()
{
HTTPSocket::Reset();
m_body_size_left = 0;
}
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
@@ -1,90 +0,0 @@
/**
** \file HttpBaseSocket.h
** \date 2007-10-05
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _HttpBaseSocket_H
#define _HttpBaseSocket_H
#include "HTTPSocket.h"
#include "HttpRequest.h"
#include "IHttpServer.h"
#include "HttpResponse.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class HttpResponse;
class HttpBaseSocket : public HTTPSocket, public IHttpServer
{
public:
HttpBaseSocket(ISocketHandler& h);
~HttpBaseSocket();
void OnFirst();
void OnHeader(const std::string& key,const std::string& value);
void OnHeaderComplete();
void OnData(const char *,size_t);
// implements IHttpServer::Respond
void Respond(const HttpResponse& res);
void OnTransferLimit();
protected:
HttpBaseSocket(const HttpBaseSocket& s) : HTTPSocket(s) {} // copy constructor
//
HttpRequest m_req;
HttpResponse m_res;
void Reset();
private:
HttpBaseSocket& operator=(const HttpBaseSocket& ) {
return *this; // assignment operator
}
void Execute();
//
size_t m_body_size_left;
bool m_b_keepalive;
};
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // _HttpBaseSocket_H
@@ -1,312 +0,0 @@
/**
** \file HttpClientSocket.cpp
** \date 2006-04-20
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#include "HttpClientSocket.h"
#include "StdLog.h"
#include "ISocketHandler.h"
#include "File.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
HttpClientSocket::HttpClientSocket(ISocketHandler& h)
:HTTPSocket(h)
,m_data_ptr(NULL)
,m_data_size(0)
,m_content_length(0)
,m_data_ptr_set(false)
,m_fil(NULL)
,m_content_ptr(0)
,m_b_complete(false)
,m_b_close_when_complete(false)
{
}
HttpClientSocket::HttpClientSocket(ISocketHandler& h,const std::string& url_in)
:HTTPSocket(h)
,m_data_ptr(NULL)
,m_data_size(0)
,m_content_length(0)
,m_data_ptr_set(false)
,m_fil(NULL)
,m_content_ptr(0)
,m_b_complete(false)
,m_b_close_when_complete(false)
{
std::string url;
url_this(url_in, m_protocol, m_host, m_port, url, m_url_filename);
SetUrl( url );
}
HttpClientSocket::HttpClientSocket(ISocketHandler& h,const std::string& host, port_t port, const std::string& url_in)
:HTTPSocket(h)
,m_data_ptr(NULL)
,m_data_size(0)
,m_content_length(0)
,m_data_ptr_set(false)
,m_fil(NULL)
,m_content_ptr(0)
,m_b_complete(false)
,m_b_close_when_complete(false)
{
std::string url;
std::string tmp = "http://" + host + ":" + Utility::l2string(port) + url_in;
url_this(tmp, m_protocol, m_host, m_port, url, m_url_filename);
SetUrl( url );
}
HttpClientSocket::~HttpClientSocket()
{
if (m_data_ptr && !m_data_ptr_set)
{
delete[] m_data_ptr;
}
if (m_fil)
{
m_fil -> fclose();
}
}
void HttpClientSocket::OnFirst()
{
if (!IsResponse())
{
Handler().LogError(this, "OnFirst", 0, "Response expected but not received - aborting", LOG_LEVEL_FATAL);
SetCloseAndDelete();
}
m_content = GetHttpVersion() + " " + GetStatus() + " " + GetStatusText() + "\r\n";
}
void HttpClientSocket::OnHeader(const std::string& key,const std::string& value)
{
m_content += key + ": " + value + "\r\n";
if (!strcasecmp(key.c_str(), "content-length"))
{
m_content_length = atoi(value.c_str());
}
else
if (!strcasecmp(key.c_str(), "content-type"))
{
m_content_type = value;
}
}
void HttpClientSocket::OnHeaderComplete()
{
if (m_filename.size())
{
m_fil = new File;
if (!m_fil -> fopen(m_filename, "wb"))
{
delete m_fil;
m_fil = NULL;
}
}
else
if (!m_data_ptr && m_content_length)
{
m_data_ptr = new unsigned char[m_content_length];
m_data_size = m_content_length;
}
}
void HttpClientSocket::OnData(const char *buf,size_t len)
{
if (m_fil)
{
m_fil -> fwrite(buf, 1, len);
}
else
if (m_data_ptr)
{
if (m_content_ptr + len > m_data_size)
{
Handler().LogError(this, "OnData", -1, "content buffer overflow", LOG_LEVEL_ERROR);
}
else
{
memcpy(m_data_ptr + m_content_ptr, buf, len);
}
}
m_content_ptr += len;
if (m_content_ptr == m_content_length && m_content_length)
{
if (m_fil)
{
m_fil -> fclose();
delete m_fil;
m_fil = NULL;
}
m_b_complete = true;
OnContent();
if (m_b_close_when_complete)
{
SetCloseAndDelete();
}
}
}
void HttpClientSocket::OnDelete()
{
if (!m_b_complete)
{
if (m_fil)
{
m_fil -> fclose();
delete m_fil;
m_fil = NULL;
}
m_b_complete = true;
OnContent();
}
}
void HttpClientSocket::SetFilename(const std::string& x)
{
m_filename = x;
}
void HttpClientSocket::SetDataPtr(unsigned char *buf,size_t len)
{
m_data_ptr = buf;
m_data_size = len;
m_data_ptr_set = true;
}
const std::string& HttpClientSocket::GetContent()
{
return m_content;
}
size_t HttpClientSocket::GetContentLength()
{
return m_content_length;
}
size_t HttpClientSocket::GetContentPtr()
{
return m_content_ptr;
}
size_t HttpClientSocket::GetPos()
{
return m_content_ptr;
}
bool HttpClientSocket::Complete()
{
return m_b_complete;
}
const unsigned char *HttpClientSocket::GetDataPtr() const
{
return m_data_ptr;
}
void HttpClientSocket::OnContent()
{
}
void HttpClientSocket::SetCloseOnComplete(bool x)
{
m_b_close_when_complete = x;
}
const std::string& HttpClientSocket::GetUrlProtocol()
{
return m_protocol;
}
const std::string& HttpClientSocket::GetUrlHost()
{
return m_host;
}
port_t HttpClientSocket::GetUrlPort()
{
return m_port;
}
const std::string& HttpClientSocket::GetUrlFilename()
{
return m_url_filename;
}
const std::string& HttpClientSocket::GetContentType()
{
return m_content_type;
}
void HttpClientSocket::Url(const std::string& url_in,std::string& host,port_t& port)
{
std::string url;
url_this(url_in, m_protocol, m_host, m_port, url, m_url_filename);
SetUrl(url);
host = GetUrlHost();
port = GetUrlPort();
}
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
@@ -1,139 +0,0 @@
/**
** \file HttpClientSocket.h
** \date 2006-04-20
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_HttpClientSocket_H
#define _SOCKETS_HttpClientSocket_H
#include "sockets-config.h"
#include "HTTPSocket.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class IFile;
/** Get http response to file or memory.
\ingroup http */
class HttpClientSocket : public HTTPSocket
{
public:
HttpClientSocket(ISocketHandler&);
HttpClientSocket(ISocketHandler&,const std::string& url_in);
HttpClientSocket(ISocketHandler&,const std::string& host, port_t port, const std::string& url_in);
~HttpClientSocket();
/** Parse url to protocol,host,port,url and file. */
void Url(const std::string& url_in,std::string& host,port_t& port);
void OnFirst();
void OnHeader(const std::string&,const std::string&);
void OnHeaderComplete();
void OnData(const char *,size_t);
void OnDelete();
/** New callback method fires when all data is received. */
virtual void OnContent();
/** Write response to this file */
void SetFilename(const std::string& );
const std::string& Filename() const {
return m_filename;
}
/** Store response in this buffer. */
void SetDataPtr(unsigned char *,size_t);
/** Get response headers. */
const std::string& GetContent();
/** Get size of response body. */
size_t GetContentLength();
/** Get content type from response header. */
const std::string& GetContentType();
/** Get size of received response body. */
size_t GetContentPtr();
/** Get size of received response body. */
size_t GetPos();
/** Complete response has been received. */
bool Complete();
/** Get ptr to response data buffer. */
const unsigned char *GetDataPtr() const;
/** Close socket when response received. */
void SetCloseOnComplete(bool = true);
/** Get protocol used from url. */
const std::string& GetUrlProtocol();
/** Get hostname from url. */
const std::string& GetUrlHost();
/** Get port from url. */
port_t GetUrlPort();
/** Get filename part of url. */
const std::string& GetUrlFilename();
protected:
HttpClientSocket(const HttpClientSocket& s) : HTTPSocket(s) {} // copy constructor
HttpClientSocket& operator=(const HttpClientSocket& ) {
return *this; // assignment operator
}
private:
std::string m_filename; ///< Filename to write response to
unsigned char *m_data_ptr; ///< Ptr to buffer where to store response
size_t m_data_size; ///< Max size of data buffer
size_t m_content_length; ///< Content-length header received from remote
std::string m_content; ///< Received http headers
bool m_data_ptr_set; ///< Buffer set from outside, do not delete
IFile *m_fil; ///< Output file
size_t m_content_ptr; ///< Number of bytes received from body
bool m_b_complete; ///< The entire content-length number of bytes has been received
bool m_b_close_when_complete; ///< Close when the full response has been received
std::string m_protocol; ///< Protocol part of url_in
std::string m_host; ///< Hostname from url_in
port_t m_port; ///< Port from url_in
std::string m_url_filename; ///< Filename from url_in
std::string m_content_type; ///< Content-type: header from response
};
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // _SOCKETS_HttpClientSocket_H
@@ -1,144 +0,0 @@
/** \file HttpDebugSocket.cpp
** \date 2004-10-08
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom (grymse@alhem.net)
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#include "HttpDebugSocket.h"
#include "ISocketHandler.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
HttpDebugSocket::HttpDebugSocket(ISocketHandler& h) : HTTPSocket(h)
,m_content_length(0)
,m_read_ptr(0)
{
}
HttpDebugSocket::~HttpDebugSocket()
{
}
void HttpDebugSocket::Init()
{
if (GetParent() -> GetPort() == 443)
{
#ifdef HAVE_OPENSSL
EnableSSL();
#else
Handler().LogError(this, "url_this", -1, "SSL not available", LOG_LEVEL_WARNING);
#endif
}
}
void HttpDebugSocket::OnFirst()
{
Send(
"HTTP/1.1 200 OK\n"
"Content-type: text/html\n"
"Connection: close\n"
"Server: HttpDebugSocket/1.0\n"
"\n");
Send(
"<html><head><title>Echo Request</title></head>"
"<body><h3>Request Header</h3>");
Send( "<form method='post' action='/test_post'>"
"<input type='text' name='text' value='test text'><br>"
"<input type='submit' name='submit' value=' OK '></form>");
// enctype 'multipart/form-data'
Sendf("<form action='/test_post' method='post' enctype='multipart/form-data'>");
Sendf("<input type=file name=the_file><br>");
Sendf("<input type=text name=the_name><br>");
Sendf("<input type=submit name=submit value=' test form-data '>");
Sendf("</form>");
Send( "<pre style='background: #e0e0e0'>");
Send(GetMethod() + " " + GetUrl() + " " + GetHttpVersion() + "\n");
}
void HttpDebugSocket::OnHeader(const std::string& key,const std::string& value)
{
if (!strcasecmp(key.c_str(),"content-length"))
m_content_length = atoi(value.c_str());
Send(key + ": " + value + "\n");
}
void HttpDebugSocket::OnHeaderComplete()
{
if (m_content_length || IsChunked())
{
Send("</pre><h3>Request Body</h3><pre style='background: #e0e0e0'>");
}
else
{
Send("</pre><hr></body></html>");
SetCloseAndDelete();
}
}
void HttpDebugSocket::OnData(const char *p,size_t l)
{
SendBuf(p,l);
m_read_ptr += (int)l;
if (m_read_ptr >= m_content_length && m_content_length)
{
Send("</pre><hr></body></html>");
SetCloseAndDelete();
}
}
void HttpDebugSocket::OnDataComplete()
{
if (!CloseAndDelete())
{
Send("</pre><hr></body></html>");
SetCloseAndDelete();
}
}
#ifdef SOCKETS_NAMESPACE
}
#endif
@@ -1,76 +0,0 @@
/** \file HttpDebugSocket.h
** \date 2004-09-27
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom (grymse@alhem.net)
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_HttpDebugSocket_H
#define _SOCKETS_HttpDebugSocket_H
#include "sockets-config.h"
#include "HTTPSocket.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class ISocketHandler;
/** HTTP request "echo" class. This class echoes a http request/body
with a html formatted page.
\ingroup http */
class HttpDebugSocket : public HTTPSocket
{
public:
HttpDebugSocket(ISocketHandler&);
~HttpDebugSocket();
void Init();
void OnFirst();
void OnHeader(const std::string& key,const std::string& value);
void OnHeaderComplete();
void OnData(const char *,size_t);
void OnDataComplete();
private:
HttpDebugSocket(const HttpDebugSocket& s) : HTTPSocket(s) {} // copy constructor
HttpDebugSocket& operator=(const HttpDebugSocket& ) {
return *this; // assignment operator
}
int m_content_length;
int m_read_ptr;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_HttpDebugSocket_H
@@ -1,114 +0,0 @@
/** \file HttpGetSocket.cpp
** \date 2004-02-13
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _WIN32
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#else
#include <errno.h>
#endif
#include "ISocketHandler.h"
#include "HttpGetSocket.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
HttpGetSocket::HttpGetSocket(ISocketHandler& h) : HttpClientSocket(h)
{
}
HttpGetSocket::HttpGetSocket(ISocketHandler& h,const std::string& url_in,const std::string& to_file) : HttpClientSocket(h, url_in)
{
if (to_file.size())
{
SetFilename(to_file);
}
if (!Open(GetUrlHost(),GetUrlPort()))
{
if (!Connecting())
{
Handler().LogError(this, "HttpGetSocket", -1, "connect() failed miserably", LOG_LEVEL_FATAL);
SetCloseAndDelete();
}
}
}
HttpGetSocket::HttpGetSocket(ISocketHandler& h,const std::string& host,port_t port,const std::string& url,const std::string& to_file) : HttpClientSocket(h, host, port, url)
{
SetUrl(url);
if (to_file.size())
{
SetFilename(to_file);
}
if (!Open(host, port))
{
if (!Connecting())
{
Handler().LogError(this, "HttpGetSocket", -1, "connect() failed miserably", LOG_LEVEL_FATAL);
SetCloseAndDelete();
}
}
}
HttpGetSocket::~HttpGetSocket()
{
}
void HttpGetSocket::OnConnect()
{
SetMethod( "GET" );
AddResponseHeader( "Accept", "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1");
AddResponseHeader( "Accept-Language", "en-us,en;q=0.5");
AddResponseHeader( "Accept-Encoding", "gzip,deflate");
AddResponseHeader( "Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
AddResponseHeader( "User-agent", MyUseragent() );
if (GetUrlPort() != 80 && GetUrlPort() != 443)
AddResponseHeader( "Host", GetUrlHost() + ":" + Utility::l2string(GetUrlPort()) );
else
AddResponseHeader( "Host", GetUrlHost() );
SendRequest();
}
#ifdef SOCKETS_NAMESPACE
}
#endif
@@ -1,71 +0,0 @@
/** \file HttpGetSocket.h
** \date 2004-02-13
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_HttpGetSocket_H
#define _SOCKETS_HttpGetSocket_H
#include "sockets-config.h"
#include "HttpClientSocket.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
/** Get http page.
\ingroup http */
class HttpGetSocket : public HttpClientSocket
{
public:
HttpGetSocket(ISocketHandler&);
HttpGetSocket(ISocketHandler&,const std::string& url,const std::string& to_file = "");
HttpGetSocket(ISocketHandler&,const std::string& host,port_t port,const std::string& url,const std::string& to_file = "");
~HttpGetSocket();
void OnConnect();
protected:
HttpGetSocket& operator=(const HttpGetSocket& ) {
return *this;
}
HttpGetSocket(const HttpGetSocket& s) : HttpClientSocket(s) {}
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_HttpGetSocket_H
@@ -1,295 +0,0 @@
/** \file HttpPostSocket.cpp
** \date 2004-10-30
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _WIN32
#ifdef _MSC_VER
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif
#else
#include <errno.h>
#include <ctype.h>
#endif
#include "ISocketHandler.h"
#include <sys/types.h>
#include <sys/stat.h>
#include "Lock.h"
#include "File.h"
#include "HttpPostSocket.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
int HttpPostSocket::m_boundary_count = 0;
Mutex HttpPostSocket::m_boundary_mutex;
HttpPostSocket::HttpPostSocket(ISocketHandler& h) : HttpClientSocket(h)
,m_bMultipart(false)
{
}
HttpPostSocket::HttpPostSocket(ISocketHandler& h,const std::string& url_in) : HttpClientSocket(h, url_in)
,m_bMultipart(false)
{
Lock lock(m_boundary_mutex);
m_boundary = "----";
for (int i = 0; i < 12; i++)
{
char c = m_boundary_count++ % 128;
while (!isalnum(c))
c = m_boundary_count++ % 128;
m_boundary += c;
}
m_boundary += "__" + Utility::l2string(m_boundary_count++);
}
HttpPostSocket::~HttpPostSocket()
{
}
void HttpPostSocket::AddField(const std::string& name,const std::string& value)
{
std::list<std::string> vec;
vec.push_back(value);
AddMultilineField(name, vec);
}
void HttpPostSocket::AddMultilineField(const std::string& name,std::list<std::string>& values)
{
m_fields[name] = values;
}
void HttpPostSocket::AddFile(const std::string& name,const std::string& filename,const std::string& type)
{
struct stat st;
if (!stat(filename.c_str(), &st))
{
m_files[name] = filename;
m_content_length[filename] = st.st_size;
m_content_type[filename] = type;
m_bMultipart = true;
}
else
{
Handler().LogError(this, "AddFile", Errno, StrError(Errno), LOG_LEVEL_FATAL);
SetCloseAndDelete();
}
}
void HttpPostSocket::Open()
{
// why do I have to specify TcpSocket:: to get to the Open() method??
TcpSocket::Open(GetUrlHost(), GetUrlPort());
}
void HttpPostSocket::OnConnect()
{
if (m_bMultipart)
{
DoMultipartPost();
}
else
{
std::string body;
// only fields, no files, add urlencoding
for (std::map<std::string,std::list<std::string> >::iterator it = m_fields.begin(); it != m_fields.end(); ++it)
{
std::string name = (*it).first;
std::list<std::string>& ref = (*it).second;
if (body.size())
{
body += '&';
}
body += name + "=";
bool first = true;
for (std::list<std::string>::iterator it = ref.begin(); it != ref.end(); ++it)
{
std::string value = *it;
if (!first)
{
body += "%0d%0a"; // CRLF
}
body += Utility::rfc1738_encode(value);
first = false;
}
}
// build header, send body
SetMethod("POST");
SetHttpVersion( "HTTP/1.1" );
AddResponseHeader( "Host", GetUrlHost() ); // oops - this is actually a request header that we're adding..
AddResponseHeader( "User-agent", MyUseragent());
AddResponseHeader( "Accept", "text/html, text/plain, */*;q=0.01" );
AddResponseHeader( "Connection", "close" );
AddResponseHeader( "Content-type", "application/x-www-form-urlencoded" );
AddResponseHeader( "Content-length", Utility::l2string((long)body.size()) );
SendRequest();
// send body
Send( body );
}
}
void HttpPostSocket::DoMultipartPost()
{
long length = 0; // calculate content_length of our post body
std::string tmp;
// fields
{
for (std::map<std::string,std::list<std::string> >::iterator it = m_fields.begin(); it != m_fields.end(); ++it)
{
std::string name = (*it).first;
std::list<std::string>& ref = (*it).second;
tmp = "--" + m_boundary + "\r\n"
"content-disposition: form-data; name=\"" + name + "\"\r\n"
"\r\n";
for (std::list<std::string>::iterator it = ref.begin(); it != ref.end(); ++it)
{
std::string value = *it;
tmp += value + "\r\n";
}
length += (long)tmp.size();
}
}
// files
{
for (std::map<std::string,std::string>::iterator it = m_files.begin(); it != m_files.end(); ++it)
{
std::string name = (*it).first;
std::string filename = (*it).second;
long content_length = m_content_length[filename];
std::string content_type = m_content_type[filename];
tmp = "--" + m_boundary + "\r\n"
"content-disposition: form-data; name=\"" + name + "\"; filename=\"" + filename + "\"\r\n"
"content-type: " + content_type + "\r\n"
"\r\n";
length += (long)tmp.size();
length += content_length;
length += 2; // crlf after file
}
}
// end
tmp = "--" + m_boundary + "--\r\n";
length += (long)tmp.size();
// build header, send body
SetMethod("POST");
SetHttpVersion( "HTTP/1.1" );
AddResponseHeader( "Host", GetUrlHost() ); // oops - this is actually a request header that we're adding..
AddResponseHeader( "User-agent", MyUseragent());
AddResponseHeader( "Accept", "text/html, text/plain, */*;q=0.01" );
AddResponseHeader( "Connection", "close" );
AddResponseHeader( "Content-type", "multipart/form-data; boundary=" + m_boundary );
AddResponseHeader( "Content-length", Utility::l2string(length) );
SendRequest();
// send fields
{
for (std::map<std::string,std::list<std::string> >::iterator it = m_fields.begin(); it != m_fields.end(); ++it)
{
std::string name = (*it).first;
std::list<std::string>& ref = (*it).second;
tmp = "--" + m_boundary + "\r\n"
"content-disposition: form-data; name=\"" + name + "\"\r\n"
"\r\n";
for (std::list<std::string>::iterator it = ref.begin(); it != ref.end(); ++it)
{
std::string value = *it;
tmp += value + "\r\n";
}
Send( tmp );
}
}
// send files
{
for (std::map<std::string,std::string>::iterator it = m_files.begin(); it != m_files.end(); ++it)
{
std::string name = (*it).first;
std::string filename = (*it).second;
std::string content_type = m_content_type[filename];
tmp = "--" + m_boundary + "\r\n"
"content-disposition: form-data; name=\"" + name + "\"; filename=\"" + filename + "\"\r\n"
"content-type: " + content_type + "\r\n"
"\r\n";
Send( tmp );
{
std::auto_ptr<IFile> fil = std::auto_ptr<IFile>(new File);
if (fil -> fopen(filename, "rb"))
{
char slask[2000]; // for fread
size_t n;
while ((n = fil -> fread(slask, 1, 2000)) > 0)
{
SendBuf(slask, n);
}
fil -> fclose();
}
}
Send("\r\n");
}
}
// end of send
Send("--" + m_boundary + "--\r\n");
}
void HttpPostSocket::SetMultipart()
{
m_bMultipart = true;
}
#ifdef SOCKETS_NAMESPACE
}
#endif
@@ -1,101 +0,0 @@
/** \file HttpPostSocket.h
** \date 2004-10-30
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_HttpPostSocket_H
#define _SOCKETS_HttpPostSocket_H
#include "sockets-config.h"
#include "HttpClientSocket.h"
#include "Mutex.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class ISocketHandler;
/** Generate a http post request, get response.
\ingroup http */
class HttpPostSocket : public HttpClientSocket
{
public:
HttpPostSocket(ISocketHandler&);
/* client constructor,
\param url_in = 'http://host:port/resource' */
HttpPostSocket(ISocketHandler&,const std::string& url_in);
~HttpPostSocket();
// these must be specified before connecting / adding to handler
/** Add field to post. */
void AddField(const std::string& name,const std::string& value);
/** Add multiline field to post. */
void AddMultilineField(const std::string& name,std::list<std::string>& values);
/** Add file to post. */
void AddFile(const std::string& name,const std::string& filename,const std::string& type);
/** use this to post with content-type multipart/form-data.
// when adding a file to the post, this is the default and only content-type */
void SetMultipart();
/** connect to host:port derived from url in constructor */
void Open();
/** http put client implemented in OnConnect */
void OnConnect();
protected:
std::map<std::string,std::list<std::string> > m_fields;
private:
HttpPostSocket(const HttpPostSocket& s) : HttpClientSocket(s) {} // copy constructor
HttpPostSocket& operator=(const HttpPostSocket& ) {
return *this; // assignment operator
}
void DoMultipartPost();
//
std::map<std::string,std::string> m_files;
std::string m_boundary;
std::map<std::string,long> m_content_length;
std::map<std::string,std::string> m_content_type;
bool m_bMultipart;
static int m_boundary_count;
static Mutex m_boundary_mutex;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_HttpPostSocket_H
@@ -1,125 +0,0 @@
/** \file HttpPutSocket.cpp
** \date 2004-10-30
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _WIN32
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#else
#include <errno.h>
#endif
#include "ISocketHandler.h"
#include <sys/types.h>
#include <sys/stat.h>
#include "File.h"
#include "HttpPutSocket.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
HttpPutSocket::HttpPutSocket(ISocketHandler& h) : HttpClientSocket(h)
{
}
HttpPutSocket::HttpPutSocket(ISocketHandler& h,const std::string& url_in) : HttpClientSocket(h, url_in)
{
}
HttpPutSocket::~HttpPutSocket()
{
}
void HttpPutSocket::SetFile(const std::string& file)
{
struct stat st;
if (!stat(file.c_str(), &st))
{
m_filename = file;
m_content_length = st.st_size;
}
else
{
Handler().LogError(this, "SetFile", Errno, StrError(Errno), LOG_LEVEL_FATAL);
SetCloseAndDelete();
}
}
void HttpPutSocket::SetContentType(const std::string& type)
{
m_content_type = type;
}
void HttpPutSocket::Open()
{
// why do I have to specify TcpSocket:: to get to the Open() method??
TcpSocket::Open(GetUrlHost(), GetUrlPort());
}
void HttpPutSocket::OnConnect()
{
SetMethod( "PUT" );
SetHttpVersion( "HTTP/1.1" );
AddResponseHeader( "Host", GetUrlHost() );
AddResponseHeader( "Content-type", m_content_type );
AddResponseHeader( "Content-length", Utility::l2string(m_content_length) );
AddResponseHeader( "User-agent", MyUseragent() );
SendRequest();
std::auto_ptr<IFile> fil = std::auto_ptr<IFile>(new File);
if (fil -> fopen(m_filename, "rb"))
{
size_t n;
char buf[32768];
while ((n = fil -> fread(buf, 1, 32768)) > 0)
{
SendBuf(buf, n);
}
fil -> fclose();
}
}
#ifdef SOCKETS_NAMESPACE
}
#endif
@@ -1,88 +0,0 @@
/** \file HttpPutSocket.h
** \date 2004-10-30
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_HttpPutSocket_H
#define _SOCKETS_HttpPutSocket_H
#include "sockets-config.h"
#include "HttpClientSocket.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class ISocketHandler;
/** Put http page.
\ingroup http */
class HttpPutSocket : public HttpClientSocket
{
public:
HttpPutSocket(ISocketHandler&);
/** client constructor,
\param url_in = 'http://host:port/resource' */
HttpPutSocket(ISocketHandler&,const std::string& url_in);
~HttpPutSocket();
// these must be specified before connecting / adding to handler
/** Set filename to send. */
void SetFile(const std::string& );
/** Set mimetype of file to send. */
void SetContentType(const std::string& );
/** connect to host:port derived from url in constructor */
void Open();
/** http put client implemented in OnConnect */
void OnConnect();
private:
HttpPutSocket(const HttpPutSocket& s) : HttpClientSocket(s) {} // copy constructor
HttpPutSocket& operator=(const HttpPutSocket& ) {
return *this; // assignment operator
}
//
std::string m_filename;
std::string m_content_type;
long m_content_length;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_HttpPutSocket_H
@@ -1,428 +0,0 @@
/**
** \file HttpRequest.cpp
** \date 2007-10-05
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#include "HttpRequest.h"
#include "MemFile.h"
#include "HttpdForm.h"
#include "HttpdCookies.h"
#include "Parse.h"
#include "Exception.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
#ifdef _DEBUG
#define DEB(x) x; fflush(stderr);
#else
#define DEB(x)
#endif
// --------------------------------------------------------------------------------------
HttpRequest::HttpRequest() : HttpTransaction()
, m_server_port(0)
, m_is_ssl(false)
, m_body_file(NULL)
, m_form(NULL)
{
}
// --------------------------------------------------------------------------------------
#ifndef _WIN32
HttpRequest::HttpRequest(FILE *fil) : HttpTransaction()
, m_server_port(0)
, m_is_ssl(false)
, m_body_file(NULL)
, m_form(NULL)
{
int i = 0;
DEB( std::cout << "Initialize HttpRequest from cgi...\n";)
while (environ[i] && *environ[i])
{
Parse pa(environ[i], "=");
std::string key = pa.getword();
std::string value = pa.getrest();
if (key == "REQUEST_METHOD")
m_method = value;
else
if (key == "SERVER_PROTOCOL")
m_protocol = value;
else
if (key == "PATH_INFO")
m_req_uri = value;
else
if (key == "REMOTE_ADDR")
m_remote_addr = value;
else
if (key == "REMOTE_HOST")
m_remote_host = value;
else
if (key == "SERVER_NAME")
m_server_name = value;
else
if (key == "SERVER_PORT")
m_server_port = atoi(value.c_str());
else
if (key.size() > 5 && key.substr(0, 5) == "HTTP_")
{
key = key.substr(5);
for (size_t pos = 0; pos < key.size(); pos++)
{
if (key[pos] == '_')
key[pos] = '-';
else
if (key[pos] >= 'A' && key[pos] <= 'Z')
key[pos] |= 32;
}
DEB( std::cout << " http header '" << key << "' == '" << value << "\n";)
SetHeader(key, value);
}
++i;
}
DEB( std::cout << " setup http form\n";)
m_form = std::auto_ptr<HttpdForm>(new HttpdForm(fil));
}
#endif
// --------------------------------------------------------------------------------------
HttpRequest::HttpRequest(const HttpRequest& src) : HttpTransaction(src)
, m_method(src.m_method)
, m_protocol(src.m_protocol)
, m_req_uri(src.m_req_uri)
, m_remote_addr(src.m_remote_addr)
, m_remote_host(src.m_remote_host)
, m_server_name(src.m_server_name)
, m_server_port(src.m_server_port)
, m_is_ssl(src.m_is_ssl)
, m_attribute(src.m_attribute)
, m_null(src.m_null)
, m_body_file(src.m_body_file)
, m_form(src.m_form)
, m_cookies(src.m_cookies)
, m_cookie(src.m_cookie)
{
}
// --------------------------------------------------------------------------------------
HttpRequest::~HttpRequest()
{
}
// --------------------------------------------------------------------------------------
HttpRequest& HttpRequest::operator=(const HttpRequest& src)
{
m_method = src.m_method;
m_protocol = src.m_protocol;
m_req_uri = src.m_req_uri;
m_remote_addr = src.m_remote_addr;
m_remote_host = src.m_remote_host;
m_server_name = src.m_server_name;
m_server_port = src.m_server_port;
m_is_ssl = src.m_is_ssl;
m_attribute = src.m_attribute;
m_null = src.m_null;
m_body_file = src.m_body_file;
m_form = src.m_form;
m_cookies = src.m_cookies;
m_cookie = src.m_cookie;
HttpTransaction::operator=(src);
return *this;
}
// --------------------------------------------------------------------------------------
void HttpRequest::SetHttpMethod(const std::string& value)
{
m_method = value;
}
const std::string& HttpRequest::HttpMethod() const
{
return m_method;
}
// --------------------------------------------------------------------------------------
void HttpRequest::SetHttpVersion(const std::string& value)
{
m_protocol = value;
}
const std::string& HttpRequest::HttpVersion() const
{
return m_protocol;
}
// --------------------------------------------------------------------------------------
void HttpRequest::SetUri(const std::string& value)
{
m_req_uri = value;
}
const std::string& HttpRequest::Uri() const
{
return m_req_uri;
}
// --------------------------------------------------------------------------------------
void HttpRequest::SetRemoteAddr(const std::string& value)
{
m_remote_addr = value;
}
const std::string& HttpRequest::RemoteAddr() const
{
return m_remote_addr;
}
// --------------------------------------------------------------------------------------
void HttpRequest::SetRemoteHost(const std::string& value)
{
m_remote_host = value;
}
const std::string& HttpRequest::RemoteHost() const
{
return m_remote_host;
}
// --------------------------------------------------------------------------------------
void HttpRequest::SetServerName(const std::string& value)
{
m_server_name = value;
}
const std::string& HttpRequest::ServerName() const
{
return m_server_name;
}
// --------------------------------------------------------------------------------------
void HttpRequest::SetServerPort(int value)
{
m_server_port = value;
}
int HttpRequest::ServerPort() const
{
return m_server_port;
}
// --------------------------------------------------------------------------------------
void HttpRequest::SetIsSsl(bool value)
{
m_is_ssl = value;
}
bool HttpRequest::IsSsl() const
{
return m_is_ssl;
}
// --------------------------------------------------------------------------------------
void HttpRequest::SetAttribute(const std::string& key, const std::string& value)
{
m_attribute[key] = value;
}
void HttpRequest::SetAttribute(const std::string& key, long value)
{
m_attribute[key] = Utility::l2string(value);
}
const std::string& HttpRequest::Attribute(const std::string& key) const
{
Utility::ncmap<std::string>::const_iterator it;
if ( (it = m_attribute.find(key)) != m_attribute.end())
return it -> second;
return m_null;
}
// --------------------------------------------------------------------------------------
const Utility::ncmap<std::string>& HttpRequest::Attributes() const
{
return m_attribute;
}
// --------------------------------------------------------------------------------------
void HttpRequest::AddCookie(const std::string& str)
{
m_cookies.add( str );
Parse pa(str, ";");
std::string lstr = pa.getword();
while (!lstr.empty())
{
Parse pa2(lstr, "=");
std::string name = pa2.getword();
m_cookie[name] = lstr;
DEB(fprintf(stderr, " *** AddCookie '%s' = '%s'\n", name.c_str(), lstr.c_str());)
lstr = pa.getword();
}
}
// --------------------------------------------------------------------------------------
void HttpRequest::InitBody( size_t sz )
{
if (!m_body_file.get())
m_body_file = std::auto_ptr<IFile>(new MemFile);
DEB( else
fprintf(stderr, "Body data file already opened\n");)
}
// --------------------------------------------------------------------------------------
void HttpRequest::Write( const char *buf, size_t sz )
{
if (m_body_file.get())
m_body_file -> fwrite(buf, 1, sz);
DEB( else
fprintf(stderr, "Write: Body data file not open\n");)
}
// --------------------------------------------------------------------------------------
void HttpRequest::CloseBody()
{
if (m_body_file.get())
m_body_file -> fclose();
DEB( else
fprintf(stderr, "CloseBody: File not open\n");)
}
// --------------------------------------------------------------------------------------
void HttpRequest::ParseBody()
{
Utility::ncmap<std::string>::const_iterator it;
if ( (it = m_attribute.find("query_string")) != m_attribute.end())
{
std::string qs = it -> second;
m_form = std::auto_ptr<HttpdForm>(new HttpdForm( qs, qs.size() ));
}
else
if (m_body_file.get())
{
m_form = std::auto_ptr<HttpdForm>(new HttpdForm( m_body_file.get(), ContentType(), ContentLength() ));
}
else
{
// dummy
m_form = std::auto_ptr<HttpdForm>(new HttpdForm( "", 0 ));
}
}
// --------------------------------------------------------------------------------------
const HttpdForm& HttpRequest::Form() const
{
if (!m_form.get())
throw Exception("Form not available");
return *m_form;
}
// --------------------------------------------------------------------------------------
const HttpdCookies& HttpRequest::Cookies() const
{
return m_cookies;
}
// --------------------------------------------------------------------------------------
void HttpRequest::Reset()
{
HttpTransaction::Reset();
m_method = "";
m_protocol = "";
m_req_uri = "";
m_remote_addr = "";
m_remote_host = "";
m_server_name = "";
m_server_port = 0;
m_is_ssl = false;
while (!m_attribute.empty())
{
m_attribute.erase(m_attribute.begin());
}
m_body_file = std::auto_ptr<IFile>(NULL);
m_form = std::auto_ptr<HttpdForm>(NULL);
m_cookies.Reset();
while (!m_cookie.empty())
{
m_cookie.erase(m_cookie.begin());
}
}
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
@@ -1,145 +0,0 @@
/**
** \file HttpRequest.h
** \date 2007-10-05
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_HttpRequest_H
#define _SOCKETS_HttpRequest_H
#include "HttpTransaction.h"
#include "HttpdCookies.h"
#include "IFile.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class HttpdForm;
class IFile;
class HttpRequest : public HttpTransaction
{
public:
HttpRequest();
/** Create from plain old cgi request */
#ifndef _WIN32
HttpRequest(FILE *);
#endif
HttpRequest(const HttpRequest& src);
~HttpRequest();
HttpRequest& operator=(const HttpRequest& src);
/** Get, Post */
void SetHttpMethod(const std::string& value);
const std::string& HttpMethod() const;
/** HTTP/1.x */
void SetHttpVersion(const std::string& value);
const std::string& HttpVersion() const;
void SetUri(const std::string& value);
const std::string& Uri() const;
void SetRemoteAddr(const std::string& value);
const std::string& RemoteAddr() const;
void SetRemoteHost(const std::string& value);
const std::string& RemoteHost() const;
void SetServerName(const std::string& value);
const std::string& ServerName() const;
void SetServerPort(int value);
int ServerPort() const;
void SetIsSsl(bool value);
bool IsSsl() const;
/** Set / Read attribute value */
void SetAttribute(const std::string& key, const std::string& value);
void SetAttribute(const std::string& key, long value);
const std::string& Attribute(const std::string& key) const;
const Utility::ncmap<std::string>& Attributes() const;
/** Cookies */
void AddCookie(const std::string& );
const Utility::ncmap<std::string>& CookieMap() const {
return m_cookie;
}
/** Open file for body data */
void InitBody( size_t sz );
/** Write body data */
void Write( const char *buf, size_t sz );
/** No more writing */
void CloseBody();
void ParseBody();
const HttpdForm& Form() const;
const HttpdCookies& Cookies() const;
const IFile *BodyFile() const {
return m_body_file.get();
}
void Reset();
private:
std::string m_method;
std::string m_protocol;
std::string m_req_uri;
std::string m_remote_addr;
std::string m_remote_host;
std::string m_server_name;
int m_server_port;
bool m_is_ssl;
Utility::ncmap<std::string> m_attribute;
std::string m_null;
mutable std::auto_ptr<IFile> m_body_file;
mutable std::auto_ptr<HttpdForm> m_form;
HttpdCookies m_cookies;
Utility::ncmap<std::string> m_cookie;
}; // end of class
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // _SOCKETS_HttpRequest_H
@@ -1,251 +0,0 @@
/**
** \file HttpResponse.cpp
** \date 2007-10-05
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#include <stdarg.h>
#include <stdio.h>
#include "HttpResponse.h"
#include "HttpRequest.h"
#include "MemFile.h"
#include "File.h"
#include "Parse.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
#ifdef _DEBUG
#define DEB(x) x; fflush(stderr);
#else
#define DEB(x)
#endif
// --------------------------------------------------------------------------------------
HttpResponse::HttpResponse(const std::string& version) : HttpTransaction()
, m_http_version( version )
, m_http_status_code(0)
, m_file( new MemFile )
{
}
// --------------------------------------------------------------------------------------
HttpResponse::HttpResponse(const HttpResponse& src) : HttpTransaction(src)
, m_http_version( src.m_http_version )
, m_http_status_code( src.m_http_status_code )
, m_http_status_msg( src.m_http_status_msg )
, m_cookie( src.m_cookie )
, m_file( src.m_file )
{
}
// --------------------------------------------------------------------------------------
HttpResponse::~HttpResponse()
{
}
// --------------------------------------------------------------------------------------
HttpResponse& HttpResponse::operator=(const HttpResponse& src)
{
m_http_version = src.m_http_version;
m_http_status_code = src.m_http_status_code;
m_http_status_msg = src.m_http_status_msg;
m_cookie = src.m_cookie;
m_file = src.m_file;
HttpTransaction::operator=(src);
return *this;
}
// --------------------------------------------------------------------------------------
void HttpResponse::SetHttpVersion(const std::string& value)
{
m_http_version = value;
}
// --------------------------------------------------------------------------------------
const std::string& HttpResponse::HttpVersion() const
{
return m_http_version;
}
// --------------------------------------------------------------------------------------
void HttpResponse::SetHttpStatusCode(int value)
{
m_http_status_code = value;
}
int HttpResponse::HttpStatusCode() const
{
return m_http_status_code;
}
// --------------------------------------------------------------------------------------
void HttpResponse::SetHttpStatusMsg(const std::string& value)
{
m_http_status_msg = value;
}
const std::string& HttpResponse::HttpStatusMsg() const
{
return m_http_status_msg;
}
// --------------------------------------------------------------------------------------
void HttpResponse::SetCookie(const std::string& value)
{
Parse pa(value, "=");
std::string name = pa.getword();
m_cookie[name] = value;
DEB(fprintf(stderr, "HttpResponse::Set-Cookie<%s>: %s\n", name.c_str(), value.c_str());)
}
const std::string HttpResponse::Cookie(const std::string& name) const
{
Utility::ncmap<std::string>::const_iterator it = m_cookie.find(name);
DEB(fprintf(stderr, "HttpResponse; get value of Cookie<%s>: ", name.c_str());)
if (it != m_cookie.end())
{
DEB(fprintf(stderr, "%s\n", it -> second.c_str());)
return it -> second;
}
DEB(fprintf(stderr, "\n");)
return "";
}
std::list<std::string> HttpResponse::CookieNames() const
{
std::list<std::string> vec;
DEB(fprintf(stderr, "HttpResponse::CookieNames; ");)
for (Utility::ncmap<std::string>::const_iterator it = m_cookie.begin(); it != m_cookie.end(); ++it)
{
DEB(fprintf(stderr, " %s", it -> first.c_str());)
vec.push_back(it -> first);
}
DEB(fprintf(stderr, "\n");)
return vec;
}
// --------------------------------------------------------------------------------------
void HttpResponse::Write( const std::string& str )
{
Write( str.c_str(), str.size() );
}
// --------------------------------------------------------------------------------------
void HttpResponse::Write( const char *buf, size_t sz )
{
m_file -> fwrite( buf, 1, sz );
}
// --------------------------------------------------------------------------------------
void HttpResponse::Writef( const char *format, ... )
{
va_list ap;
va_start(ap, format);
char tmp[10000];
vsnprintf(tmp, sizeof(tmp), format, ap);
va_end(ap);
m_file -> fwrite( tmp, 1, strlen(tmp) );
}
// --------------------------------------------------------------------------------------
const IFile& HttpResponse::GetFile() const
{
return *m_file;
}
// --------------------------------------------------------------------------------------
IFile& HttpResponse::GetFile()
{
return *m_file;
}
// --------------------------------------------------------------------------------------
void HttpResponse::SetFile( const std::string& path )
{
m_file = std::auto_ptr<IFile>(new File);
m_file -> fopen( path, "rb" );
}
// --------------------------------------------------------------------------------------
void HttpResponse::SetFile( IFile *f )
{
m_file = std::auto_ptr<IFile>(f);
}
// --------------------------------------------------------------------------------------
void HttpResponse::Reset()
{
HttpTransaction::Reset();
m_http_version = "";
m_http_status_code = 0;
m_http_status_msg = "";
while (!m_cookie.empty())
{
m_cookie.erase(m_cookie.begin());
}
m_file = std::auto_ptr<IFile>(new MemFile);
}
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
@@ -1,99 +0,0 @@
/**
** \file HttpResponse.h
** \date 2007-10-05
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_HttpResponse_H
#define _SOCKETS_HttpResponse_H
#include "HttpTransaction.h"
#include <list>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class IFile;
class HttpResponse : public HttpTransaction
{
public:
HttpResponse(const std::string& version = "HTTP/1.0");
HttpResponse(const HttpResponse& src);
~HttpResponse();
HttpResponse& operator=(const HttpResponse& src);
/** HTTP/1.x */
void SetHttpVersion(const std::string& value);
const std::string& HttpVersion() const;
void SetHttpStatusCode(int value);
int HttpStatusCode() const;
void SetHttpStatusMsg(const std::string& value);
const std::string& HttpStatusMsg() const;
void SetCookie(const std::string& value);
const std::string Cookie(const std::string& name) const;
std::list<std::string> CookieNames() const;
void Write( const std::string& str );
void Write( const char *buf, size_t sz );
void Writef( const char *format, ... );
const IFile& GetFile() const;
IFile& GetFile();
/** Replace memfile with file on disk, opened for read. */
void SetFile( const std::string& path );
/** Replace memfile with another IFile */
void SetFile( IFile *f );
void Reset();
private:
std::string m_http_version;
int m_http_status_code;
std::string m_http_status_msg;
Utility::ncmap<std::string> m_cookie;
mutable std::auto_ptr<IFile> m_file;
}; // end of class
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // _SOCKETS_HttpResponse_H
@@ -1,262 +0,0 @@
/**
** \file HttpTransaction.cpp
** \date 2007-10-05
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#include "HttpTransaction.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
// --------------------------------------------------------------------------------------
HttpTransaction::HttpTransaction()
{
}
// --------------------------------------------------------------------------------------
HttpTransaction::~HttpTransaction()
{
}
// --------------------------------------------------------------------------------------
void HttpTransaction::SetHeader(const std::string& key, const std::string& value)
{
m_header[key] = value;
}
void HttpTransaction::SetHeader(const std::string& key, long value)
{
m_header[key] = Utility::l2string(value);
}
const std::string& HttpTransaction::Header(const std::string& key) const
{
Utility::ncmap<std::string>::const_iterator it;
if ((it = m_header.find(key)) != m_header.end())
return it -> second;
return m_null;
}
// --------------------------------------------------------------------------------------
void HttpTransaction::SetAccept(const std::string& value)
{
SetHeader("accept", value);
}
const std::string& HttpTransaction::Accept() const
{
return Header("accept");
}
// --------------------------------------------------------------------------------------
void HttpTransaction::SetAcceptCharset(const std::string& value)
{
SetHeader("accept-charset", value);
}
const std::string& HttpTransaction::AcceptCharset() const
{
return Header("accept-charset");
}
// --------------------------------------------------------------------------------------
void HttpTransaction::SetAcceptEncoding(const std::string& value)
{
SetHeader("accept-encoding", value);
}
const std::string& HttpTransaction::AcceptEncoding() const
{
return Header("accept-encoding");
}
// --------------------------------------------------------------------------------------
void HttpTransaction::SetAcceptLanguage(const std::string& value)
{
SetHeader("accept-language", value);
}
const std::string& HttpTransaction::AcceptLanguage() const
{
return Header("accept-language");
}
// --------------------------------------------------------------------------------------
void HttpTransaction::SetConnection(const std::string& value)
{
SetHeader("connection", value);
}
const std::string& HttpTransaction::Connection() const
{
return Header("connection");
}
// --------------------------------------------------------------------------------------
void HttpTransaction::SetContentType(const std::string& value)
{
SetHeader("content-type", value);
}
const std::string& HttpTransaction::ContentType() const
{
return Header("content-type");
}
// --------------------------------------------------------------------------------------
void HttpTransaction::SetContentLength(long value)
{
SetHeader("content-length", value );
}
long HttpTransaction::ContentLength() const
{
return atol(Header("content-length").c_str());
}
// --------------------------------------------------------------------------------------
void HttpTransaction::SetHost(const std::string& value)
{
SetHeader("host", value);
}
const std::string& HttpTransaction::Host() const
{
return Header("host");
}
const std::string HttpTransaction::HostOnly() const
{
std::string host = Header("host");
size_t pos = host.find(":");
if (pos != std::string::npos)
return host.substr(0, pos);
return host;
}
// --------------------------------------------------------------------------------------
void HttpTransaction::SetPragma(const std::string& value)
{
SetHeader("pragma", value);
}
const std::string& HttpTransaction::Pragma() const
{
return Header("pragma");
}
// --------------------------------------------------------------------------------------
void HttpTransaction::SetReferer(const std::string& value)
{
SetHeader("referer", value);
}
const std::string& HttpTransaction::Referer() const
{
return Header("referer");
}
// --------------------------------------------------------------------------------------
void HttpTransaction::SetUserAgent(const std::string& value)
{
SetHeader("user-agent", value);
}
const std::string& HttpTransaction::UserAgent() const
{
return Header("user-agent");
}
// --------------------------------------------------------------------------------------
const Utility::ncmap<std::string>& HttpTransaction::Headers() const
{
return m_header;
}
// --------------------------------------------------------------------------------------
void HttpTransaction::Reset()
{
while (!m_header.empty())
{
m_header.erase(m_header.begin());
}
}
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
@@ -1,106 +0,0 @@
/**
** \file HttpTransaction.h
** \date 2007-10-05
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_HttpTransaction_H
#define _SOCKETS_HttpTransaction_H
#include "Utility.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class HttpTransaction
{
public:
HttpTransaction();
virtual ~HttpTransaction();
/** Set / Read http header value */
void SetHeader(const std::string& key, const std::string& value);
void SetHeader(const std::string& key, long value);
const std::string& Header(const std::string& key) const;
void SetAccept(const std::string& value);
const std::string& Accept() const;
void SetAcceptCharset(const std::string& value);
const std::string& AcceptCharset() const;
void SetAcceptEncoding(const std::string& value);
const std::string& AcceptEncoding() const;
void SetAcceptLanguage(const std::string& value);
const std::string& AcceptLanguage() const;
void SetConnection(const std::string& value);
const std::string& Connection() const;
void SetContentType(const std::string& value);
const std::string& ContentType() const;
void SetContentLength(long value);
long ContentLength() const;
void SetHost(const std::string& value);
const std::string& Host() const;
const std::string HostOnly() const;
void SetPragma(const std::string& value);
const std::string& Pragma() const;
void SetReferer(const std::string& value);
const std::string& Referer() const;
void SetUserAgent(const std::string& value);
const std::string& UserAgent() const;
const Utility::ncmap<std::string>& Headers() const;
virtual void Reset();
private:
Utility::ncmap<std::string> m_header;
std::string m_null;
}; // end of class
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // _SOCKETS_HttpTransaction_H
@@ -1,287 +0,0 @@
/** \file HttpdCookies.cpp
*/
/*
Copyright (C) 2003-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#include "Parse.h"
#include "HTTPSocket.h"
#include "HttpdCookies.h"
#include <stdio.h>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
#ifdef _DEBUG
#define DEB(x) x; fflush(stderr);
#else
#define DEB(x)
#endif
HttpdCookies::HttpdCookies()
{
}
HttpdCookies::HttpdCookies(const std::string& s)
{
Parse *pa = new Parse(s,";");
std::string slask = pa -> getword();
while (slask.size())
{
Parse *pa2 = new Parse(slask,"=");
std::string name = pa2 -> getword();
std::string value = pa2 -> getword();
delete pa2;
m_cookies.push_back(std::pair<std::string, std::string>(name, value));
//
slask = pa -> getword();
}
delete pa;
}
void HttpdCookies::add(const std::string& s)
{
Parse *pa = new Parse(s,";");
DEB(fprintf(stderr, "Parse cookie: %s\n", s.c_str());)
std::string slask = pa -> getword();
while (slask.size())
{
Parse *pa2 = new Parse(slask,"=");
std::string name = pa2 -> getword();
std::string value = pa2 -> getword();
delete pa2;
m_cookies.push_back(std::pair<std::string, std::string>(name, value));
//
slask = pa -> getword();
}
delete pa;
}
HttpdCookies::~HttpdCookies()
{
}
bool HttpdCookies::getvalue(const std::string& name,std::string& buffer) const
{
for (cookie_v::const_iterator it = m_cookies.begin(); it != m_cookies.end(); ++it)
{
const std::pair<std::string, std::string>& ref = *it;
if (!strcasecmp(ref.first.c_str(),name.c_str()))
{
buffer = ref.second;
return true;
}
}
buffer = "";
return false;
}
void HttpdCookies::replacevalue(const std::string& name,const std::string& value)
{
for (cookie_v::iterator it = m_cookies.begin(); it != m_cookies.end(); ++it)
{
std::pair<std::string, std::string>& ref = *it;
if (!strcasecmp(ref.first.c_str(),name.c_str()))
{
ref.second = value;
return;
}
}
m_cookies.push_back(std::pair<std::string, std::string>(name, value));
}
void HttpdCookies::replacevalue(const std::string& name,long l)
{
replacevalue(name, Utility::l2string(l));
}
void HttpdCookies::replacevalue(const std::string& name,int i)
{
replacevalue(name, Utility::l2string(i));
}
size_t HttpdCookies::getlength(const std::string& name) const
{
for (cookie_v::const_iterator it = m_cookies.begin(); it != m_cookies.end(); ++it)
{
const std::pair<std::string, std::string>& ref = *it;
if (!strcasecmp(ref.first.c_str(),name.c_str()))
{
return ref.second.size();
}
}
return 0;
}
void HttpdCookies::setcookie(HTTPSocket *sock, const std::string& domain, const std::string& path, const std::string& name, const std::string& value)
{
size_t sz = name.size() + value.size() + domain.size() + path.size() + 100;
char *str = new char[sz];
// set-cookie response
if (domain.size())
{
snprintf(str, sz, "%s=%s; domain=%s; path=%s; expires=%s",
name.c_str(), value.c_str(),
domain.c_str(),
path.c_str(),
expiredatetime().c_str());
}
else
{
snprintf(str, sz, "%s=%s; path=%s; expires=%s",
name.c_str(), value.c_str(),
path.c_str(),
expiredatetime().c_str());
}
sock -> AddResponseHeader("Set-cookie", str);
delete[] str;
replacevalue(name, value);
}
void HttpdCookies::setcookie(HTTPSocket *sock, const std::string& domain, const std::string& path, const std::string& name, long value)
{
size_t sz = name.size() + domain.size() + path.size() + 100;
char *str = new char[sz];
char dt[80];
// set-cookie response
if (domain.size())
{
snprintf(str, sz, "%s=%ld; domain=%s; path=%s; expires=%s",
name.c_str(), value,
domain.c_str(),
path.c_str(),
expiredatetime().c_str());
}
else
{
snprintf(str, sz, "%s=%ld; path=%s; expires=%s",
name.c_str(), value,
path.c_str(),
expiredatetime().c_str());
}
sock -> AddResponseHeader("Set-cookie", str);
delete[] str;
snprintf(dt, sizeof(dt), "%ld", value);
replacevalue(name, dt);
}
void HttpdCookies::setcookie(HTTPSocket *sock, const std::string& domain, const std::string& path, const std::string& name, int value)
{
size_t sz = name.size() + domain.size() + path.size() + 100;
char *str = new char[sz];
char dt[80];
// set-cookie response
if (domain.size())
{
snprintf(str, sz, "%s=%d; domain=%s; path=%s; expires=%s",
name.c_str(), value,
domain.c_str(),
path.c_str(),
expiredatetime().c_str());
}
else
{
snprintf(str, sz, "%s=%d; path=%s; expires=%s",
name.c_str(), value,
path.c_str(),
expiredatetime().c_str());
}
sock -> AddResponseHeader("Set-cookie", str);
delete[] str;
snprintf(dt, sizeof(dt), "%d", value);
replacevalue(name, dt);
}
const std::string& HttpdCookies::expiredatetime() const
{
const char *days[7] = {"Sunday", "Monday",
"Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
const char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May",
"Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
char dt[100];
time_t t = time(NULL);
#ifdef __CYGWIN__
struct tm *tp = gmtime(&t);
snprintf(dt, sizeof(dt), "%s, %02d-%s-%04d %02d:%02d:%02d GMT",
days[tp -> tm_wday],
tp -> tm_mday,
months[tp -> tm_mon],
tp -> tm_year + 1910,
tp -> tm_hour,
tp -> tm_min,
tp -> tm_sec);
#else
struct tm tp;
#if defined( _WIN32) && !defined(__CYGWIN__)
gmtime_s(&tp, &t);
#else
gmtime_r(&t, &tp);
#endif
snprintf(dt, sizeof(dt), "%s, %02d-%s-%04d %02d:%02d:%02d GMT",
days[tp.tm_wday],
tp.tm_mday,
months[tp.tm_mon],
tp.tm_year + 1910,
tp.tm_hour,
tp.tm_min,
tp.tm_sec);
#endif
m_date = dt;
return m_date;
}
void HttpdCookies::Reset()
{
while (!m_cookies.empty())
{
m_cookies.erase(m_cookies.begin());
}
m_date = "";
}
#ifdef SOCKETS_NAMESPACE
}
#endif
@@ -1,94 +0,0 @@
/** \file HttpdCookies.h
*/
/*
Copyright (C) 2003-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_HttpdCookies_H
#define _SOCKETS_HttpdCookies_H
#include "sockets-config.h"
#include <list>
#include <string>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
//! Store the cookies name/value pairs.
//! Retrieve and manage cookies during a cgi call.
class HTTPSocket;
/** HTTP Cookie parse/container class.
\sa HttpdSocket
\sa HttpdForm
\ingroup webserver */
class HttpdCookies
{
/** list of key/value structs. */
typedef std::list<std::pair<std::string, std::string> > cookie_v;
public:
HttpdCookies();
HttpdCookies(const std::string& query_string);
~HttpdCookies();
void add(const std::string& s);
bool getvalue(const std::string&,std::string&) const;
void replacevalue(const std::string& ,const std::string& );
void replacevalue(const std::string& ,long);
void replacevalue(const std::string& ,int);
size_t getlength(const std::string& ) const;
void setcookie(HTTPSocket *,const std::string& d,const std::string& p,const std::string& c,const std::string& v);
void setcookie(HTTPSocket *,const std::string& d,const std::string& p,const std::string& c,long v);
void setcookie(HTTPSocket *,const std::string& d,const std::string& p,const std::string& c,int v);
const std::string& expiredatetime() const;
cookie_v& GetHttpdCookies() {
return m_cookies;
}
void Reset();
private:
cookie_v m_cookies;
mutable std::string m_date;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_HttpdCookies_H
@@ -1,717 +0,0 @@
/** \file HttpdForm.cpp - read stdin, parse cgi input
**
** Written: 1999-Feb-10 grymse@alhem.net
**/
/*
Copyright (C) 1999-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#include "socket_include.h"
#include "Parse.h"
#include "IFile.h"
#include "HttpdForm.h"
#include "IFileUpload.h"
#include "IStream.h"
#include "File.h"
#include <memory>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
#define TMPSIZE 32000
#ifdef _DEBUG
#define DEB(x) x
#else
#define DEB(x)
#endif
HttpdForm::HttpdForm(FILE *fil)
{
const char *r_m = getenv("REQUEST_METHOD");
const char *q_s = getenv("QUERY_STRING");
if (r_m && !strcasecmp(r_m, "post"))
{
const char *c_t = getenv("CONTENT_TYPE");
const char *c_l = getenv("CONTENT_LENGTH");
if (c_t && c_l)
{
std::auto_ptr<IFile> p = std::auto_ptr<IFile>(new File(fil));
ParseFormData( p.get(), c_t, atoi(c_l) );
}
}
if (q_s && strlen(q_s))
{
ParseQueryString(q_s, strlen(q_s));
}
}
HttpdForm::HttpdForm(IFile *infil, const std::string& content_type, size_t content_length) : raw(false)
, m_file_upload(NULL)
, m_upload_stream(NULL)
{
ParseFormData(infil, content_type, content_length);
}
// HttpdForm(buffer,l) -- request_method GET
HttpdForm::HttpdForm(const std::string& buffer,size_t l) : raw(false)
, m_file_upload(NULL)
, m_upload_stream(NULL)
{
ParseQueryString(buffer, l);
}
void HttpdForm::ParseFormData(IFile *infil, const std::string& content_type, size_t content_length)
{
CGI *cgi = NULL;
size_t extra = 2;
int cl = (int)content_length;
m_current = m_cgi.end();
if (content_type.size() >= 19 && content_type.substr(0, 19) == "multipart/form-data")
{
Parse pa(content_type,";=");
char *tempcmp = NULL;
size_t tc = 0;
size_t l = 0;
std::string str = pa.getword();
m_strBoundary = "";
while (!str.empty())
{
if (!strcmp(str.c_str(),"boundary"))
{
m_strBoundary = pa.getword();
l = m_strBoundary.size();
tempcmp = new char[l + extra];
}
//
str = pa.getword();
}
if (!m_strBoundary.empty())
{
std::string content_type;
std::string current_name;
std::string current_filename;
char *slask = new char[TMPSIZE];
infil -> fgets(slask, TMPSIZE);
cl -= (int)strlen(slask);
while (cl >= 0 && !infil -> eof())
{
while (strlen(slask) && (slask[strlen(slask) - 1] == 13 || slask[strlen(slask) - 1] == 10))
{
slask[strlen(slask) - 1] = 0;
}
content_type = "";
current_name = "";
current_filename = "";
if ((strstr(slask,m_strBoundary.c_str()) || strstr(m_strBoundary.c_str(),slask)) && strcmp(slask, m_strBoundary.c_str()))
{
m_strBoundary = slask;
l = m_strBoundary.size();
delete[] tempcmp;
tempcmp = new char[l + extra];
}
if (!strcmp(slask, m_strBoundary.c_str()))
{
// Get headers until empty line
infil -> fgets(slask, TMPSIZE);
cl -= (int)strlen(slask);
while (strlen(slask) && (slask[strlen(slask) - 1] == 13 || slask[strlen(slask) - 1] == 10))
{
slask[strlen(slask) - 1] = 0;
}
while (cl >= 0 && !infil -> eof() && *slask)
{
Parse pa(slask,":");
std::string h = pa.getword();
std::string h2 = pa.getrest();
if (!strcasecmp(h.c_str(),"Content-type"))
{
Parse pa(h2, ";");
content_type = pa.getword();
}
else
if (!strcasecmp(h.c_str(),"Content-Disposition"))
{
Parse pa(h2, ";");
h = pa.getword();
if (!strcmp(h.c_str(),"form-data"))
{
pa.EnableQuote(true);
h = pa.getword();
while (!h.empty())
{
Parse pa2(h,"=");
std::string name = pa2.getword();
h = pa2.getrest();
if (!strcmp(name.c_str(),"name"))
{
if (!h.empty() && h[0] == '"')
{
current_name = h.substr(1, h.size() - 2);
}
else
{
current_name = h;
}
}
else
if (!strcmp(name.c_str(),"filename"))
{
if (!h.empty() && h[0] == '"')
{
current_filename = h.substr(1, h.size() - 2);
}
else
{
current_filename = h;
}
size_t x = 0;
for (size_t i = 0; i < current_filename.size(); i++)
{
if (current_filename[i] == '/' || current_filename[i] == '\\')
x = i + 1;
}
if (x)
{
current_filename = current_filename.substr(x);
}
}
h = pa.getword();
}
}
}
// get next header value
infil -> fgets(slask, TMPSIZE);
cl -= (int)strlen(slask);
while (strlen(slask) && (slask[strlen(slask) - 1] == 13 || slask[strlen(slask) - 1] == 10))
{
slask[strlen(slask) - 1] = 0;
}
}
// Read content, save...?
if (current_filename.empty()) // not a file
{
std::string val;
infil -> fgets(slask, TMPSIZE);
cl -= (int)strlen(slask);
while (cl >= 0 && !infil -> eof() && strncmp(slask,m_strBoundary.c_str(),m_strBoundary.size() ))
{
val += slask;
infil -> fgets(slask, TMPSIZE);
cl -= (int)strlen(slask);
}
// remove trailing cr/linefeed
while (!val.empty() && (val[val.size() - 1] == 13 || val[val.size() - 1] == 10))
{
val = val.substr(0,val.size() - 1);
}
cgi = new CGI(current_name, val);
m_cgi.push_back(cgi);
if (!cl)
{
break;
}
}
else // current_filename.size() > 0
{
// read until m_strBoundary...
IFile *fil = NULL;
int out = 0;
char c;
char fn[2000]; // where post'd file will be saved
#ifdef _WIN32
{
char tmp_path[2000];
::GetTempPathA(2000, tmp_path);
if (tmp_path[strlen(tmp_path) - 1] != '\\')
{
#ifdef __CYGWIN__
strcat(tmp_path, "\\");
#else
strcat_s(tmp_path, sizeof(tmp_path), "\\");
#endif
}
snprintf(fn,sizeof(fn),"%s%s",tmp_path,current_filename.c_str());
}
#else
snprintf(fn,sizeof(fn),"/tmp/%s",current_filename.c_str());
#endif
if (m_file_upload && !m_upload_stream)
m_upload_stream = &m_file_upload -> IFileUploadBegin(current_name, current_filename, content_type);
else
{
fil = new File;
if (!fil -> fopen(fn, "wb"))
{
delete fil;
fil = NULL;
}
}
if (fil || m_upload_stream)
{
infil -> fread(&c,1,1);
cl -= 1;
while (cl >= 0 && !infil -> eof())
{
if (out)
{
if (m_upload_stream)
m_upload_stream -> IStreamWrite(&tempcmp[tc], 1);
else
fil -> fwrite(&tempcmp[tc],1,1);
}
tempcmp[tc] = c;
tc++;
if (tc >= l + extra)
{
tc = 0;
out = 1;
}
if (tc)
{
if (!strncmp(tempcmp + tc + extra, m_strBoundary.c_str(), l - tc) &&
!strncmp(tempcmp, m_strBoundary.c_str() + l - tc, tc))
{
break;
}
}
else
{
if (!strncmp(tempcmp + extra, m_strBoundary.c_str(), l))
{
break;
}
}
infil -> fread(&c,1,1);
cl -= 1;
}
if (m_file_upload && m_upload_stream)
{
m_file_upload -> IFileUploadEnd();
m_upload_stream = NULL;
}
else
if (fil)
{
fil -> fclose();
delete fil;
}
cgi = new CGI(current_name,fn,fn);
m_cgi.push_back(cgi);
#if defined( _WIN32) && !defined(__CYGWIN__)
strcpy_s(slask, TMPSIZE, m_strBoundary.c_str());
#else
strcpy(slask, m_strBoundary.c_str());
#endif
size_t l = strlen(slask);
infil -> fgets(slask + l, TMPSIZE - (int)l); // next line
cl -= (int)strlen(slask + l);
}
else
{
// couldn't open file
break;
}
if (!cl)
{
break;
}
}
}
else
{
// Probably '<m_strBoundary>--'
break;
}
} // while (!infil -> eof())
delete[] slask;
} // if (m_strBoundary)
if (tempcmp)
{
delete[] tempcmp;
}
} // end of multipart
else
if (strstr(content_type.c_str(), "x-www-form-urlencoded"))
{
bool got_name = false; // tnx to FatherNitwit
int cl = (int)content_length;
char c,chigh,clow;
std::string slask;
m_current = m_cgi.end();
std::string name;
infil -> fread(&c,1,1);
cl--;
while (cl >= 0 && !infil -> eof())
{
switch (c) // built-in url decoder
{
case '=': /* end of name */
name = slask;
slask.resize(0);
got_name = true;
break;
case '&': /* end of value */
if (got_name)
{
cgi = new CGI(name,slask);
got_name = false;
}
else
{
cgi = new CGI(slask, "");
}
slask.resize(0);
m_cgi.push_back(cgi);
break;
case '+': /* space */
slask += " ";
break;
case '%': /* hex value */
infil -> fread(&chigh,1,1);
cl--;
chigh -= 48 + (chigh > '9' ? 7 : 0) + (chigh >= 'a' ? 32 : 0);
infil -> fread(&clow,1,1);
cl--;
clow -= 48 + (clow > '9' ? 7 : 0) + (clow >= 'a' ? 32 : 0);
slask += (char)(chigh * 16 + clow);
break;
default: /* just another char */
slask += c;
break;
}
//
if (cl > 0)
{
infil -> fread(&c,1,1);
}
cl--;
}
if (got_name)
{
cgi = new CGI(name,slask);
}
else
{
cgi = new CGI(slask, "");
}
m_cgi.push_back(cgi);
}
else // read other content up to a limit
if (content_length > 0 && content_length < 500000)
{
int ptr = 0;
int cl = (int)content_length;
m_content.resize(cl);
while (ptr < cl)
{
int remaining = cl - ptr;
int n = fread(&m_content[ptr], 1, remaining, stdin);
if (n > 0)
ptr += n;
}
}
}
void HttpdForm::ParseQueryString(const std::string& buffer,size_t l)
{
CGI *cgi = NULL;
std::string slask;
std::string name;
char c,chigh,clow;
size_t ptr = 0;
bool got_name = false;
m_current = m_cgi.end();
ptr = 0;
while (ptr < l)
{
c = buffer[ptr++];
switch (c)
{
case '=': /* end of name */
name = slask;
slask.resize(0);
got_name = true;
break;
case '&': /* end of value */
if (got_name)
{
cgi = new CGI(name,slask);
got_name = false;
}
else
{
cgi = new CGI(slask, "");
}
slask.resize(0);
m_cgi.push_back(cgi);
break;
case '+': /* space */
slask += " ";
break;
case '%': /* hex value */
chigh = buffer[ptr++];
chigh -= 48 + (chigh > '9' ? 7 : 0) + (chigh >= 'a' ? 32 : 0);
clow = buffer[ptr++];
clow -= 48 + (clow > '9' ? 7 : 0) + (clow >= 'a' ? 32 : 0);
slask += (char)(chigh * 16 + clow);
break;
default: /* just another char */
slask += c;
break;
}
}
if (got_name)
{
cgi = new CGI(name,slask);
}
else
{
cgi = new CGI(slask, "");
}
m_cgi.push_back(cgi);
}
HttpdForm::~HttpdForm()
{
CGI *cgi = NULL; //,*tmp;
for (cgi_v::iterator it = m_cgi.begin(); it != m_cgi.end(); ++it)
{
cgi = *it;
delete cgi;
}
}
void HttpdForm::EnableRaw(bool b)
{
raw = b;
}
void HttpdForm::strcpyval(std::string& v,const char *value) const
{
v = "";
for (size_t i = 0; i < strlen(value); i++)
{
if (value[i] == '<')
{
v += "&lt;";
}
else
if (value[i] == '>')
{
v += "&gt;";
}
else
if (value[i] == '&')
{
v += "&amp;";
}
else
{
v += value[i];
}
}
}
bool HttpdForm::getfirst(std::string& n) const
{
m_current = m_cgi.begin();
return getnext(n);
}
bool HttpdForm::getnext(std::string& n) const
{
if (m_current != m_cgi.end() )
{
CGI *current = *m_current;
n = current -> name;
m_current++;
return true;
}
else
{
n = "";
}
return false;
}
bool HttpdForm::getfirst(std::string& n,std::string& v) const
{
m_current = m_cgi.begin();
return getnext(n,v);
}
bool HttpdForm::getnext(std::string& n,std::string& v) const
{
if (m_current != m_cgi.end() )
{
CGI *current = *m_current;
n = current -> name;
if (raw)
{
v = current -> value;
}
else
{
strcpyval(v,current -> value.c_str());
}
m_current++;
return true;
}
else
{
n = "";
}
return false;
}
int HttpdForm::getvalue(const std::string& n,std::string& v) const
{
CGI *cgi = NULL;
int r = 0;
for (cgi_v::const_iterator it = m_cgi.begin(); it != m_cgi.end(); ++it)
{
cgi = *it;
if (cgi -> name == n)
break;
cgi = NULL;
}
if (cgi)
{
if (raw)
{
v = cgi -> value;
}
else
{
strcpyval(v,cgi -> value.c_str());
}
r++;
}
else
{
v = "";
}
return r;
}
std::string HttpdForm::getvalue(const std::string& n) const
{
for (cgi_v::const_iterator it = m_cgi.begin(); it != m_cgi.end(); ++it)
{
CGI *cgi = *it;
if (cgi -> name == n)
{
return cgi -> value;
}
}
return "";
}
size_t HttpdForm::getlength(const std::string& n) const
{
CGI *cgi = NULL;
size_t l;
for (cgi_v::const_iterator it = m_cgi.begin(); it != m_cgi.end(); ++it)
{
cgi = *it;
if (cgi -> name == n)
break;
cgi = NULL;
}
l = cgi ? cgi -> value.size() : 0;
if (cgi && !raw)
{
for (size_t i = 0; i < cgi -> value.size(); i++)
{
switch (cgi -> value[i])
{
case '<': // &lt;
case '>': // &gt;
l += 4;
break;
case '&': // &amp;
l += 5;
break;
}
}
}
return l;
}
HttpdForm::cgi_v& HttpdForm::getbase()
{
return m_cgi;
}
const std::string& HttpdForm::GetBoundary() const
{
return m_strBoundary;
}
void HttpdForm::SetFileUpload(IFileUpload& cb)
{
m_file_upload = &cb;
}
#ifdef SOCKETS_NAMESPACE
}
#endif
@@ -1,147 +0,0 @@
/** \file HttpdForm.h - read stdin, parse cgi input
**
** Written: 1999-Feb-10 grymse@alhem.net
**/
/*
Copyright (C) 1999-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_HttpdForm_H
#define _SOCKETS_HttpdForm_H
#include "sockets-config.h"
#include <string>
#include <list>
#include <cstdio>
#include <cstring>
#include <vector>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class IFile;
class IFileUpload;
class IStream;
/** Parse/store a http query_string/form-data body.
\ingroup webserver */
class HttpdForm
{
/**
* Store the name/value pairs from a GET/POST operation.
* "name" does not have to be unique.
\ingroup webserver
*/
struct CGI {
CGI(const std::string& n,const std::string& v) : name(n),value(v) {}
CGI(const std::string& n,const std::string& v,const std::string& p) : name(n),value(v),path(p) {}
std::string name;
std::string value;
std::string path;
};
/** list of key/value pairs. */
typedef std::list<CGI *> cgi_v;
public:
/**
* Default constructor
*/
HttpdForm(FILE *);
/**
* Constructor (used in POST operations).
* Input is read from stdin. Number of characters to read
* can be found in the environment variable CONTENT_LENGTH.
*/
HttpdForm(IFile *, const std::string& content_type, size_t content_length);
/**
* Another constructor (used in GET operations).
* Input is read from the environment variable QUERY_STRING.
* @param query_string The httpd server provided QUERY_STRING
* @param length Query string length.
*/
HttpdForm(const std::string& query_string,size_t length);
~HttpdForm();
void ParseFormData(IFile *, const std::string&, size_t);
void ParseQueryString(const std::string& query_string, size_t length);
void EnableRaw(bool);
/** Encode characters '<' '>' '&' as &lt; &gt; &amp; */
void strcpyval(std::string&,const char *) const;
/* get names */
bool getfirst(std::string& n) const;
bool getnext(std::string& n) const;
/* get names and values */
bool getfirst(std::string& n,std::string& v) const;
bool getnext(std::string& n,std::string& v) const;
/* get value */
int getvalue(const std::string& ,std::string& ) const;
std::string getvalue(const std::string& ) const;
size_t getlength(const std::string& ) const;
cgi_v& getbase();
const std::string& GetBoundary() const;
/** Enable IFileUpload callback */
void SetFileUpload(IFileUpload& cb);
bool ContentAvailable() const {
return !m_content.empty();
}
const std::vector<char>& GetContent() const {
return m_content;
}
private:
HttpdForm(const HttpdForm& ) {}
HttpdForm& operator=(const HttpdForm& ) {
return *this;
}
cgi_v m_cgi;
mutable cgi_v::const_iterator m_current;
std::string m_strBoundary;
bool raw;
IFileUpload *m_file_upload;
IStream *m_upload_stream;
std::vector<char> m_content;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_HttpdForm_H
@@ -1,326 +0,0 @@
/** \file HttpdSocket.cpp
*/
/*
Copyright (C) 2001-2010 Anders Hedstrom (grymse@alhem.net)
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#include "HttpdCookies.h"
#include "HttpdForm.h"
#include "MemFile.h"
#include "HttpdSocket.h"
#include "Base64.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
#define TMPSIZE 10000
// statics
int HttpdSocket::m_request_count = 0;
std::string HttpdSocket::m_start = "";
HttpdSocket::HttpdSocket(ISocketHandler& h)
:HTTPSocket(h)
,m_content_length(0)
,m_file(NULL)
,m_received(0)
,m_request_id(++m_request_count)
,m_cookies(NULL)
,m_form(NULL)
{
m_http_date = datetime2httpdate(GetDate());
if (!m_start.size())
m_start = m_http_date;
}
HttpdSocket::~HttpdSocket()
{
if (m_file)
{
delete m_file;
}
if (m_cookies)
delete m_cookies;
if (m_form)
delete m_form;
}
void HttpdSocket::OnFirst()
{
}
void HttpdSocket::OnHeader(const std::string& key,const std::string& value)
{
if (!strcasecmp(key.c_str(),"content-length"))
{
m_content_length = atoi(value.c_str());
m_content_length_str = value;
}
else
if (!strcasecmp(key.c_str(),"cookie"))
{
m_http_cookie = value;
}
else
if (!strcasecmp(key.c_str(),"content-type"))
{
m_content_type = value;
}
else
if (!strcasecmp(key.c_str(),"if-modified-since"))
{
m_if_modified_since = value;
}
}
void HttpdSocket::OnHeaderComplete()
{
m_cookies = new HttpdCookies(m_http_cookie);
if (GetMethod() == "GET")
{
Utility::SetEnv("QUERY_STRING", GetQueryString());
}
Utility::SetEnv("REQUEST_METHOD", GetMethod());
Utility::SetEnv("HTTP_COOKIE", m_http_cookie);
Utility::SetEnv("CONTENT_TYPE", m_content_type);
Utility::SetEnv("CONTENT_LENGTH", m_content_length_str);
if (GetMethod() == "POST")
{
m_file = new MemFile;
}
else
if (GetMethod() == "GET")
{
m_form = new HttpdForm(GetQueryString(), GetQueryString().size() );
AddResponseHeader("Date", datetime2httpdate(GetDate()) );
if (GetUri() == "/image")
{
Send64(Utility::Logo, "image/png");
}
else
{
Exec();
}
Reset(); // prepare for next request
}
else
{
AddResponseHeader("Date", GetHttpDate());
AddResponseHeader("Connection", "close");
SetStatus("405");
SetStatusText("Method not allowed");
SendResponse();
}
}
void HttpdSocket::OnData(const char *p,size_t l)
{
if (m_file)
{
m_file -> fwrite(p,1,l);
}
m_received += l;
if (m_received >= m_content_length && m_content_length)
{
// all done
if (m_file && !m_form)
{
m_form = new HttpdForm(m_file, m_content_type, m_content_length);
AddResponseHeader("Date", datetime2httpdate(GetDate()) );
if (GetUri() == "/image")
{
Send64(Utility::Logo, "image/png");
}
else
{
Exec();
}
Reset(); // prepare for next request
}
}
}
void HttpdSocket::Send64(const std::string& str64, const std::string& type)
{
Base64 bb;
if (!strcasecmp(m_start.c_str(), m_if_modified_since.c_str()))
{
SetStatus("304");
SetStatusText("Not Modified");
SendResponse();
}
else
{
size_t len = bb.decode_length(str64);
unsigned char *buf = new unsigned char[len];
SetStatus("200");
SetStatusText("OK");
AddResponseHeader("Content-length", Utility::l2string( (long)len) );
AddResponseHeader("Content-type", type );
AddResponseHeader("Last-modified", m_start);
SendResponse();
bb.decode(str64, buf, len);
SendBuf( (char *)buf, len);
delete[] buf;
}
}
std::string HttpdSocket::datetime2httpdate(const std::string& dt)
{
struct tm tp;
time_t t;
const char *days[] = { "Sun","Mon","Tue","Wed","Thu","Fri","Sat" };
const char *months[] = { "Jan","Feb","Mar","Apr","May","Jun",
"Jul","Aug","Sep","Oct","Nov","Dec" };
int i;
char s[40];
/* 1997-12-16 09:50:40 */
if (dt.size() == 19)
{
tp.tm_year = atoi(dt.substr(0,4).c_str()) - 1900;
i = atoi(dt.substr(5,2).c_str()) - 1;
tp.tm_mon = i >= 0 ? i : 0;
tp.tm_mday = atoi(dt.substr(8,2).c_str());
tp.tm_hour = atoi(dt.substr(11,2).c_str());
tp.tm_min = atoi(dt.substr(14,2).c_str());
tp.tm_sec = atoi(dt.substr(17,2).c_str());
tp.tm_wday = 0;
tp.tm_yday = 0;
tp.tm_isdst = 0;
t = mktime(&tp);
if (t == -1)
{
Handler().LogError(this, "datetime2httpdate", 0, "mktime() failed");
}
snprintf(s,sizeof(s),"%s, %02d %s %d %02d:%02d:%02d GMT",
days[tp.tm_wday],
tp.tm_mday,
months[tp.tm_mon],
tp.tm_year + 1900,
tp.tm_hour,tp.tm_min,tp.tm_sec);
}
else
{
*s = 0;
}
return s;
}
std::string HttpdSocket::GetDate()
{
time_t t = time(NULL);
char slask[40]; // yyyy-mm-dd hh:mm:ss
#ifdef __CYGWIN__
struct tm *tp = localtime(&t);
snprintf(slask,sizeof(slask),"%d-%02d-%02d %02d:%02d:%02d",
tp -> tm_year + 1900,
tp -> tm_mon + 1,
tp -> tm_mday,
tp -> tm_hour,tp -> tm_min,tp -> tm_sec);
#else
struct tm tp;
#if defined( _WIN32) && !defined(__CYGWIN__)
localtime_s(&tp, &t);
#else
localtime_r(&t, &tp);
#endif
snprintf(slask,sizeof(slask),"%d-%02d-%02d %02d:%02d:%02d",
tp.tm_year + 1900,
tp.tm_mon + 1,
tp.tm_mday,
tp.tm_hour,tp.tm_min,tp.tm_sec);
#endif
return slask;
}
void HttpdSocket::Reset()
{
HTTPSocket::Reset();
m_content_length = 0;
if (m_file)
{
delete m_file;
m_file = NULL;
}
m_received = 0;
m_request_id = ++m_request_count;
if (m_cookies)
delete m_cookies;
m_cookies = NULL;
if (m_form)
delete m_form;
m_form = NULL;
}
const std::string& HttpdSocket::GetHttpDate() const
{
return m_http_date;
}
HttpdCookies *HttpdSocket::GetCookies()
{
return m_cookies;
}
const HttpdForm *HttpdSocket::GetForm() const
{
return m_form;
}
#ifdef SOCKETS_NAMESPACE
}
#endif
@@ -1,117 +0,0 @@
/** \file HttpdSocket.h
*/
/*
Copyright (C) 2001-2010 Anders Hedstrom (grymse@alhem.net)
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_HttpdSocket_H
#define _SOCKETS_HttpdSocket_H
#include "sockets-config.h"
#include "HTTPSocket.h"
#include "ISocketHandler.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class HttpdCookies;
class HttpdForm;
class IFile;
/** \defgroup webserver Webserver framework */
/** Web server socket framework.
\ingroup webserver */
class HttpdSocket : public HTTPSocket
{
public:
HttpdSocket(ISocketHandler& );
~HttpdSocket();
void OnFirst();
void OnHeader(const std::string& key,const std::string& value);
void OnHeaderComplete();
void OnData(const char *,size_t);
/** This method needs to be implemented with logic to produce
a response to an incoming request. */
virtual void Exec() = 0;
/** Get current date in http rfc format. */
const std::string& GetHttpDate() const;
/** Get pointer to cookie class. */
HttpdCookies *GetCookies();
/** Get pointer to query string/form data class. */
const HttpdForm *GetForm() const;
size_t ContentLength() const {
return m_content_length;
}
const IFile *Body() const {
return m_file;
}
int RequestId() const {
return m_request_id;
}
protected:
HttpdSocket(const HttpdSocket& s) : HTTPSocket(s) {}
/** Decode and send a base64-encoded string.
\param str64 Base64-encoded string
\param type Mime type of content (content-type header) */
void Send64(const std::string& str64, const std::string& type);
std::string datetime2httpdate(const std::string& dt);
std::string GetDate();
void Reset();
// headers
std::string m_http_cookie;
std::string m_content_type;
std::string m_content_length_str;
std::string m_if_modified_since;
private:
HttpdSocket& operator=(const HttpdSocket& s) {
return *this;
}
static int m_request_count;
static std::string m_start;
size_t m_content_length;
IFile *m_file;
size_t m_received;
int m_request_id;
std::string m_http_date;
HttpdCookies *m_cookies;
HttpdForm *m_form;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_HttpdSocket_H
@@ -1,45 +0,0 @@
/**
** \file
** \date 2007-06-05
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_IBase_H
#define _SOCKETS_IBase_H
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class IBase
{
public:
virtual ~IBase() {}
};
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // _SOCKETS_IBase_H
@@ -1,78 +0,0 @@
/** \file IEventHandler.h
** \date 2005-12-07
** \author grymse@alhem.net
**/
/*
Copyright (C) 2005-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_IEventHandler_H
#define _SOCKETS_IEventHandler_H
#include "sockets-config.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class IEventOwner;
/** Timer event handler pure virtual base class.
\ingroup timer */
class IEventHandler
{
public:
virtual ~IEventHandler() {}
/** Return time left until next event.
\param tv Time struct that will be filled by method
\return true if time is set for next event */
virtual bool GetTimeUntilNextEvent(struct timeval *) = 0;
/** Will fire events whose time has come. */
virtual void CheckEvents() = 0;
/** Schedule event for an owner.
\param from Event owner
\param sec Seconds until event
\param usec Microseconds until event */
virtual long AddEvent(IEventOwner *,long sec,long usec) = 0;
/** Clear all events for a specific owner. */
virtual void ClearEvents(IEventOwner *) = 0;
/** Remove one specific event for an event owner. */
virtual void RemoveEvent(IEventOwner *,long) = 0;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_IEventHandler_H
@@ -1,81 +0,0 @@
/** \file IEventOwner.cpp
** \date 2005-12-07
** \author grymse@alhem.net
**/
/*
Copyright (C) 2005-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "IEventOwner.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
IEventOwner::IEventOwner(IEventHandler& h) : m_event_handler(h), m_handler_invalid(false)
{
}
IEventOwner::~IEventOwner()
{
if (!m_handler_invalid)
{
m_event_handler.ClearEvents(this);
}
}
IEventHandler& IEventOwner::GetEventHandler()
{
return m_event_handler;
}
long IEventOwner::AddEvent(long sec,long usec)
{
return m_event_handler.AddEvent(this, sec, usec);
}
void IEventOwner::ClearEvents()
{
m_event_handler.ClearEvents(this);
}
void IEventOwner::RemoveEvent(long eid)
{
m_event_handler.RemoveEvent(this, eid);
}
#ifdef SOCKETS_NAMESPACE
}
#endif
@@ -1,82 +0,0 @@
/** \file IEventOwner.h
** \date 2005-12-07
** \author grymse@alhem.net
**/
/*
Copyright (C) 2005-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_IEventOwner_H
#define _SOCKETS_IEventOwner_H
#include "sockets-config.h"
#include "IEventHandler.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
/** Any class that wants to use timer events inherits this.
\ingroup timer */
class IEventOwner
{
public:
IEventOwner(IEventHandler& h);
virtual ~IEventOwner();
/** Schedule event.
\param sec Seconds until event
\param usec Microseconds until event
\return Event ID */
long AddEvent(long sec,long usec);
/** Clear all events scheduled by this owner. */
void ClearEvents();
/** Remove one event scheduled by this owner.
\param eid Event ID to remove */
void RemoveEvent(long eid);
/** Event callback will fire when time is up. */
virtual void OnEvent(int) = 0;
IEventHandler& GetEventHandler();
void SetHandlerInvalid(bool x = true) {
m_handler_invalid = x;
}
private:
IEventHandler& m_event_handler;
bool m_handler_invalid;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_IEventOwner_H
@@ -1,75 +0,0 @@
/** \file IFile.h
** \date 2005-04-25
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_IFile_H
#define _SOCKETS_IFile_H
#include "sockets-config.h"
#include <string>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
/** \defgroup file File handling */
/** Pure virtual file I/O interface.
\ingroup file */
class IFile
{
public:
virtual ~IFile() {}
virtual bool fopen(const std::string&, const std::string&) = 0;
virtual void fclose() const = 0;
virtual size_t fread(char *, size_t, size_t) const = 0;
virtual size_t fwrite(const char *, size_t, size_t) = 0;
virtual char *fgets(char *, int) const = 0;
virtual void fprintf(const char *format, ...) = 0;
virtual off_t size() const = 0;
virtual bool eof() const = 0;
virtual void reset_read() const = 0;
virtual void reset_write() = 0;
virtual const std::string& Path() const = 0;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_IFile_H
@@ -1,61 +0,0 @@
/** \file IFileUpload.h
** \date 2009-04-22
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_IFileUpload_H
#define _SOCKETS_IFileUpload_H
#include "sockets-config.h"
#include <string>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class IStream;
/** Multipart form file upload callback.
\ingroup webserver */
class IFileUpload
{
public:
virtual ~IFileUpload() {}
virtual IStream& IFileUploadBegin(const std::string& input_name, const std::string& filename, const std::string& content_type) = 0;
virtual void IFileUploadEnd() = 0;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_IFileUpload_H
@@ -1,69 +0,0 @@
/**
** \file IHttpServer.h
** \date 2007-10-05
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_IHttpServer_H
#define _SOCKETS_IHttpServer_H
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class HttpRequest;
class HttpResponse;
class IHttpServer
{
public:
virtual ~IHttpServer() {}
/** Complete request has been received and parsed. Send response
using the Respond() method. */
virtual void OnExec(const HttpRequest& req) = 0;
/** Send response. */
virtual void Respond(const HttpResponse& res) = 0;
/** Called when the body part of the response has been sent. */
virtual void OnResponseComplete() = 0;
};
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // _SOCKETS_IHttpServer_H
@@ -1,58 +0,0 @@
/** \file IMutex.h
** \date 2008-10-25
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_IMutex_H
#define _SOCKETS_IMutex_H
#include "sockets-config.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
/** IMutex interface.
\ingroup threading */
class IMutex
{
public:
virtual ~IMutex() {}
virtual void Lock() const = 0;
virtual void Unlock() const = 0;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_IMutex_H
@@ -1,262 +0,0 @@
/** \file ISocketHandler.h
** \date 2004-02-13
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_ISocketHandler_H
#define _SOCKETS_ISocketHandler_H
#include "sockets-config.h"
#include <list>
#include <map>
#include "socket_include.h"
#include "Socket.h"
#include "StdLog.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class SocketAddress;
class IMutex;
/** Socket container class, event generator.
\ingroup basic */
class ISocketHandler
{
friend class Socket;
public:
/** Connection pool class for internal use by the ISocketHandler.
\ingroup internal */
#ifdef ENABLE_POOL
class PoolSocket : public Socket
{
public:
PoolSocket(ISocketHandler& h,Socket *src) : Socket(h) {
CopyConnection( src );
SetIsClient();
}
void OnRead() {
Handler().LogError(this, "OnRead", 0, "data on hibernating socket", LOG_LEVEL_FATAL);
SetCloseAndDelete();
}
void OnOptions(int,int,int,SOCKET) {}
};
#endif
public:
virtual ~ISocketHandler() {}
/** Return another instance */
virtual ISocketHandler *Create(StdLog * = NULL) = 0;
/** Return another instance */
virtual ISocketHandler *Create(IMutex&, ISocketHandler&, StdLog * = NULL) = 0;
/** Handler created with parent */
virtual bool ParentHandlerIsValid() = 0;
/** Get parent sockethandler */
virtual ISocketHandler& ParentHandler() = 0;
/** Get thread handler with least connections */
virtual ISocketHandler& GetRandomHandler() = 0;
/** Return parent handler if valid, otherwise return normal handler */
virtual ISocketHandler& GetEffectiveHandler() = 0;
/** Enable threading */
virtual void SetNumberOfThreads(size_t n) = 0;
/** Threading is enabled */
virtual bool IsThreaded() = 0;
/** Enable select release */
virtual void EnableRelease() = 0;
/** Make select release */
virtual void Release() = 0;
/** Get mutex reference for threadsafe operations. */
virtual IMutex& GetMutex() const = 0;
/** Register StdLog object for error callback.
\param log Pointer to log class */
virtual void RegStdLog(StdLog *log) = 0;
/** Log error to log class for print out / storage. */
virtual void LogError(Socket *p,const std::string& user_text,int err,const std::string& sys_err,loglevel_t t = LOG_LEVEL_WARNING) = 0;
// -------------------------------------------------------------------------
// Socket stuff
// -------------------------------------------------------------------------
/** Add socket instance to socket map. Removal is always automatic. */
virtual void Add(Socket *) = 0;
protected:
/** Remove socket from socket map, used by Socket class. */
virtual void Remove(Socket *) = 0;
/** Actual call to select() */
virtual int ISocketHandler_Select(struct timeval *) = 0;
public:
/** Set read/write/exception file descriptor sets (fd_set). */
virtual void ISocketHandler_Add(Socket *,bool bRead,bool bWrite) = 0;
virtual void ISocketHandler_Mod(Socket *,bool bRead,bool bWrite) = 0;
virtual void ISocketHandler_Del(Socket *) = 0;
/** Wait for events, generate callbacks. */
virtual int Select(long sec,long usec) = 0;
/** This method will not return until an event has been detected. */
virtual int Select() = 0;
/** Wait for events, generate callbacks. */
virtual int Select(struct timeval *tsel) = 0;
/** Check that a socket really is handled by this socket handler. */
virtual bool Valid(Socket *) = 0;
/** Preferred method - Check that a socket still is handled by this socket handler. */
virtual bool Valid(socketuid_t) = 0;
/** Return number of sockets handled by this handler. */
virtual size_t GetCount() = 0;
/** Return maximum number of sockets allowed. */
virtual size_t MaxCount() = 0;
/** Override and return false to deny all incoming connections.
\param p ListenSocket class pointer (use GetPort to identify which one) */
virtual bool OkToAccept(Socket *p) = 0;
/** Use with care, always lock with h.GetMutex() if multithreaded */
virtual const std::map<SOCKET, Socket *>& AllSockets() = 0;
/** Override to accept longer lines than TCP_LINE_SIZE */
virtual size_t MaxTcpLineSize() = 0;
virtual void SetCallOnConnect(bool = true) = 0;
virtual void SetDetach(bool = true) = 0;
virtual void SetTimeout(bool = true) = 0;
virtual void SetRetry(bool = true) = 0;
virtual void SetClose(bool = true) = 0;
// -------------------------------------------------------------------------
// Connection pool
// -------------------------------------------------------------------------
#ifdef ENABLE_POOL
/** Find available open connection (used by connection pool). */
virtual ISocketHandler::PoolSocket *FindConnection(int type,const std::string& protocol,SocketAddress&) = 0;
/** Enable connection pool (by default disabled). */
virtual void EnablePool(bool = true) = 0;
/** Check pool status.
\return true if connection pool is enabled */
virtual bool PoolEnabled() = 0;
#endif // ENABLE_POOL
// -------------------------------------------------------------------------
// Socks4
// -------------------------------------------------------------------------
#ifdef ENABLE_SOCKS4
/** Set socks4 server ip that all new tcp sockets should use. */
virtual void SetSocks4Host(ipaddr_t) = 0;
/** Set socks4 server hostname that all new tcp sockets should use. */
virtual void SetSocks4Host(const std::string& ) = 0;
/** Set socks4 server port number that all new tcp sockets should use. */
virtual void SetSocks4Port(port_t) = 0;
/** Set optional socks4 userid. */
virtual void SetSocks4Userid(const std::string& ) = 0;
/** If connection to socks4 server fails, immediately try direct connection to final host. */
virtual void SetSocks4TryDirect(bool = true) = 0;
/** Get socks4 server ip.
\return socks4 server ip */
virtual ipaddr_t GetSocks4Host() = 0;
/** Get socks4 port number.
\return socks4 port number */
virtual port_t GetSocks4Port() = 0;
/** Get socks4 userid (optional).
\return socks4 userid */
virtual const std::string& GetSocks4Userid() = 0;
/** Check status of socks4 try direct flag.
\return true if direct connection should be tried if connection to socks4 server fails */
virtual bool Socks4TryDirect() = 0;
#endif // ENABLE_SOCKS4
// -------------------------------------------------------------------------
// DNS resolve server
// -------------------------------------------------------------------------
#ifdef ENABLE_RESOLVER
/** Enable asynchronous DNS.
\param port Listen port of asynchronous dns server */
virtual void EnableResolver(port_t = 16667) = 0;
/** Check resolver status.
\return true if resolver is enabled */
virtual bool ResolverEnabled() = 0;
/** Queue a dns request.
\param host Hostname to be resolved
\param port Port number will be echoed in Socket::OnResolved callback */
virtual int Resolve(Socket *,const std::string& host,port_t port) = 0;
#ifdef ENABLE_IPV6
virtual int Resolve6(Socket *,const std::string& host,port_t port) = 0;
#endif
/** Do a reverse dns lookup. */
virtual int Resolve(Socket *,ipaddr_t a) = 0;
#ifdef ENABLE_IPV6
virtual int Resolve(Socket *,in6_addr& a) = 0;
#endif
/** Get listen port of asynchronous dns server. */
virtual port_t GetResolverPort() = 0;
/** Resolver thread ready for queries. */
virtual bool ResolverReady() = 0;
/** Returns true if socket waiting for a resolve event. */
virtual bool Resolving(Socket *) = 0;
#endif // ENABLE_RESOLVER
#ifdef ENABLE_DETACH
/** Indicates that the handler runs under SocketThread. */
virtual void SetSlave(bool x = true) = 0;
/** Indicates that the handler runs under SocketThread. */
virtual bool IsSlave() = 0;
#endif // ENABLE_DETACH
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_ISocketHandler_H
@@ -1,61 +0,0 @@
/** \file IStream.h
** \date 2008-11-15
** \author grymse@alhem.net
**/
/*
Copyright (C) 2008-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_IStream_H
#define _SOCKETS_IStream_H
#include "sockets-config.h"
#include <string>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class IStream
{
public:
virtual ~IStream() {}
/** Try to read 'buf_sz' number of bytes from source.
\return Number of bytes actually read. */
virtual size_t IStreamRead(char *buf, size_t buf_sz) = 0;
/** Write 'sz' bytes to destination. */
virtual void IStreamWrite(const char *buf, size_t sz) = 0;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_IStream_H
@@ -1,223 +0,0 @@
/**
** \file Ipv4Address.cpp
** \date 2006-09-21
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "Ipv4Address.h"
#include "Utility.h"
#ifndef _WIN32
#include <netdb.h>
#endif
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
Ipv4Address::Ipv4Address(port_t port) : m_valid(true)
{
memset(&m_addr, 0, sizeof(m_addr));
m_addr.sin_family = AF_INET;
m_addr.sin_port = htons( port );
}
Ipv4Address::Ipv4Address(ipaddr_t a,port_t port) : m_valid(true)
{
memset(&m_addr, 0, sizeof(m_addr));
m_addr.sin_family = AF_INET;
m_addr.sin_port = htons( port );
memcpy(&m_addr.sin_addr, &a, sizeof(struct in_addr));
}
Ipv4Address::Ipv4Address(struct in_addr& a,port_t port) : m_valid(true)
{
memset(&m_addr, 0, sizeof(m_addr));
m_addr.sin_family = AF_INET;
m_addr.sin_port = htons( port );
m_addr.sin_addr = a;
}
Ipv4Address::Ipv4Address(const std::string& host,port_t port) : m_valid(false)
{
memset(&m_addr, 0, sizeof(m_addr));
m_addr.sin_family = AF_INET;
m_addr.sin_port = htons( port );
{
ipaddr_t a;
if (Utility::u2ip(host, a))
{
memcpy(&m_addr.sin_addr, &a, sizeof(struct in_addr));
m_valid = true;
}
}
}
Ipv4Address::Ipv4Address(struct sockaddr_in& sa)
{
m_addr = sa;
m_valid = sa.sin_family == AF_INET;
}
Ipv4Address::~Ipv4Address()
{
}
Ipv4Address::operator struct sockaddr *()
{
return (struct sockaddr *)&m_addr;
}
Ipv4Address::operator socklen_t()
{
return sizeof(struct sockaddr_in);
}
void Ipv4Address::SetPort(port_t port)
{
m_addr.sin_port = htons( port );
}
port_t Ipv4Address::GetPort()
{
return ntohs( m_addr.sin_port );
}
bool Ipv4Address::Resolve(const std::string& hostname,struct in_addr& a)
{
struct sockaddr_in sa;
memset(&a, 0, sizeof(a));
if (Utility::isipv4(hostname))
{
if (!Utility::u2ip(hostname, sa, AI_NUMERICHOST))
return false;
a = sa.sin_addr;
return true;
}
if (!Utility::u2ip(hostname, sa))
return false;
a = sa.sin_addr;
return true;
}
bool Ipv4Address::Reverse(struct in_addr& a,std::string& name)
{
struct sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr = a;
return Utility::reverse((struct sockaddr *)&sa, sizeof(sa), name);
}
std::string Ipv4Address::Convert(bool include_port)
{
if (include_port)
return Convert(m_addr.sin_addr) + ":" + Utility::l2string(GetPort());
return Convert(m_addr.sin_addr);
}
std::string Ipv4Address::Convert(struct in_addr& a)
{
struct sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr = a;
std::string name;
Utility::reverse((struct sockaddr *)&sa, sizeof(sa), name, NI_NUMERICHOST);
return name;
}
void Ipv4Address::SetAddress(struct sockaddr *sa)
{
memcpy(&m_addr, sa, sizeof(struct sockaddr_in));
}
int Ipv4Address::GetFamily()
{
return m_addr.sin_family;
}
bool Ipv4Address::IsValid()
{
return m_valid;
}
bool Ipv4Address::operator==(SocketAddress& a)
{
if (a.GetFamily() != GetFamily())
return false;
if ((socklen_t)a != sizeof(m_addr))
return false;
struct sockaddr *sa = a;
struct sockaddr_in *p = (struct sockaddr_in *)sa;
if (p -> sin_port != m_addr.sin_port)
return false;
if (memcmp(&p -> sin_addr, &m_addr.sin_addr, 4))
return false;
return true;
}
std::auto_ptr<SocketAddress> Ipv4Address::GetCopy()
{
return std::auto_ptr<SocketAddress>(new Ipv4Address(m_addr));
}
std::string Ipv4Address::Reverse()
{
std::string tmp;
Reverse(m_addr.sin_addr, tmp);
return tmp;
}
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
@@ -1,111 +0,0 @@
/**
** \file Ipv4Address.h
** \date 2006-09-21
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_Ipv4Address_H
#define _SOCKETS_Ipv4Address_H
#include "sockets-config.h"
#include "SocketAddress.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
/* Ipv4 address implementation.
\ingroup basic */
class Ipv4Address : public SocketAddress
{
public:
/** Create empty Ipv4 address structure.
\param port Port number */
Ipv4Address(port_t port = 0);
/** Create Ipv4 address structure.
\param a Socket address in network byte order (as returned by Utility::u2ip)
\param port Port number in host byte order */
Ipv4Address(ipaddr_t a,port_t port);
/** Create Ipv4 address structure.
\param a Socket address in network byte order
\param port Port number in host byte order */
Ipv4Address(struct in_addr& a,port_t port);
/** Create Ipv4 address structure.
\param host Hostname to be resolved
\param port Port number in host byte order */
Ipv4Address(const std::string& host,port_t port);
Ipv4Address(struct sockaddr_in&);
~Ipv4Address();
// SocketAddress implementation
operator struct sockaddr *();
operator socklen_t();
bool operator==(SocketAddress&);
void SetPort(port_t port);
port_t GetPort();
void SetAddress(struct sockaddr *sa);
int GetFamily();
bool IsValid();
std::auto_ptr<SocketAddress> GetCopy();
/** Convert address struct to text. */
std::string Convert(bool include_port = false);
std::string Reverse();
/** Resolve hostname. */
static bool Resolve(const std::string& hostname,struct in_addr& a);
/** Reverse resolve (IP to hostname). */
static bool Reverse(struct in_addr& a,std::string& name);
/** Convert address struct to text. */
static std::string Convert(struct in_addr& a);
private:
Ipv4Address(const Ipv4Address& ) {} // copy constructor
Ipv4Address& operator=(const Ipv4Address& ) {
return *this; // assignment operator
}
struct sockaddr_in m_addr;
bool m_valid;
};
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // _SOCKETS_Ipv4Address_H
@@ -1,286 +0,0 @@
/**
** \file Ipv6Address.cpp
** \date 2006-09-21
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include "Ipv6Address.h"
#ifdef ENABLE_IPV6
#include "Utility.h"
#ifndef _WIN32
#include <netdb.h>
#endif
#ifdef IPPROTO_IPV6
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
Ipv6Address::Ipv6Address(port_t port) : m_valid(true)
{
memset(&m_addr, 0, sizeof(m_addr));
m_addr.sin6_family = AF_INET6;
m_addr.sin6_port = htons( port );
}
Ipv6Address::Ipv6Address(struct in6_addr& a,port_t port) : m_valid(true)
{
memset(&m_addr, 0, sizeof(m_addr));
m_addr.sin6_family = AF_INET6;
m_addr.sin6_port = htons( port );
m_addr.sin6_addr = a;
}
Ipv6Address::Ipv6Address(const std::string& host,port_t port) : m_valid(false)
{
memset(&m_addr, 0, sizeof(m_addr));
m_addr.sin6_family = AF_INET6;
m_addr.sin6_port = htons( port );
{
struct in6_addr a;
if (Utility::u2ip(host, a))
{
m_addr.sin6_addr = a;
m_valid = true;
}
}
}
Ipv6Address::Ipv6Address(struct sockaddr_in6& sa)
{
m_addr = sa;
m_valid = sa.sin6_family == AF_INET6;
}
Ipv6Address::~Ipv6Address()
{
}
Ipv6Address::operator struct sockaddr *()
{
return (struct sockaddr *)&m_addr;
}
Ipv6Address::operator socklen_t()
{
return sizeof(struct sockaddr_in6);
}
void Ipv6Address::SetPort(port_t port)
{
m_addr.sin6_port = htons( port );
}
port_t Ipv6Address::GetPort()
{
return ntohs( m_addr.sin6_port );
}
bool Ipv6Address::Resolve(const std::string& hostname,struct in6_addr& a)
{
struct sockaddr_in6 sa;
memset(&a, 0, sizeof(a));
if (Utility::isipv6(hostname))
{
if (!Utility::u2ip(hostname, sa, AI_NUMERICHOST))
return false;
a = sa.sin6_addr;
return true;
}
if (!Utility::u2ip(hostname, sa))
return false;
a = sa.sin6_addr;
return true;
}
bool Ipv6Address::Reverse(struct in6_addr& a,std::string& name)
{
struct sockaddr_in6 sa;
memset(&sa, 0, sizeof(sa));
sa.sin6_family = AF_INET6;
sa.sin6_addr = a;
return Utility::reverse((struct sockaddr *)&sa, sizeof(sa), name);
}
std::string Ipv6Address::Convert(bool include_port)
{
if (include_port)
return Convert(m_addr.sin6_addr) + ":" + Utility::l2string(GetPort());
return Convert(m_addr.sin6_addr);
}
std::string Ipv6Address::Convert(struct in6_addr& a,bool mixed)
{
char slask[100]; // l2ip temporary
*slask = 0;
unsigned int prev = 0;
bool skipped = false;
bool ok_to_skip = true;
if (mixed)
{
unsigned short x;
unsigned short addr16[8];
memcpy(addr16, &a, sizeof(addr16));
for (size_t i = 0; i < 6; i++)
{
x = ntohs(addr16[i]);
if (*slask && (x || !ok_to_skip || prev))
{
#if defined( _WIN32) && !defined(__CYGWIN__)
strcat_s(slask,sizeof(slask),":");
#else
strcat(slask,":");
#endif
}
if (x || !ok_to_skip)
{
snprintf(slask + strlen(slask), sizeof(slask) - strlen(slask),"%x", x);
if (x && skipped)
ok_to_skip = false;
}
else
{
skipped = true;
}
prev = x;
}
x = ntohs(addr16[6]);
snprintf(slask + strlen(slask), sizeof(slask) - strlen(slask),":%u.%u",x / 256,x & 255);
x = ntohs(addr16[7]);
snprintf(slask + strlen(slask), sizeof(slask) - strlen(slask),".%u.%u",x / 256,x & 255);
}
else
{
struct sockaddr_in6 sa;
memset(&sa, 0, sizeof(sa));
sa.sin6_family = AF_INET6;
sa.sin6_addr = a;
std::string name;
Utility::reverse((struct sockaddr *)&sa, sizeof(sa), name, NI_NUMERICHOST);
return name;
}
return slask;
}
void Ipv6Address::SetAddress(struct sockaddr *sa)
{
memcpy(&m_addr, sa, sizeof(struct sockaddr_in6));
}
int Ipv6Address::GetFamily()
{
return m_addr.sin6_family;
}
void Ipv6Address::SetFlowinfo(uint32_t x)
{
m_addr.sin6_flowinfo = x;
}
uint32_t Ipv6Address::GetFlowinfo()
{
return m_addr.sin6_flowinfo;
}
#ifndef _WIN32
void Ipv6Address::SetScopeId(uint32_t x)
{
m_addr.sin6_scope_id = x;
}
uint32_t Ipv6Address::GetScopeId()
{
return m_addr.sin6_scope_id;
}
#endif
bool Ipv6Address::IsValid()
{
return m_valid;
}
bool Ipv6Address::operator==(SocketAddress& a)
{
if (a.GetFamily() != GetFamily())
return false;
if ((socklen_t)a != sizeof(m_addr))
return false;
struct sockaddr *sa = a;
struct sockaddr_in6 *p = (struct sockaddr_in6 *)sa;
if (p -> sin6_port != m_addr.sin6_port)
return false;
if (memcmp(&p -> sin6_addr, &m_addr.sin6_addr, sizeof(struct in6_addr)))
return false;
return true;
}
std::auto_ptr<SocketAddress> Ipv6Address::GetCopy()
{
return std::auto_ptr<SocketAddress>(new Ipv6Address(m_addr));
}
std::string Ipv6Address::Reverse()
{
std::string tmp;
Reverse(m_addr.sin6_addr, tmp);
return tmp;
}
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // IPPROTO_IPV6
#endif // ENABLE_IPV6
@@ -1,120 +0,0 @@
/**
** \file Ipv6Address.h
** \date 2006-09-21
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_Ipv6Address_H
#define _SOCKETS_Ipv6Address_H
#include "sockets-config.h"
#ifdef ENABLE_IPV6
#include "SocketAddress.h"
#ifdef IPPROTO_IPV6
#if defined( _WIN32) && !defined(__CYGWIN__)
typedef unsigned __int32 uint32_t;
#endif
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
/** Ipv6 address implementation.
\ingroup basic */
class Ipv6Address : public SocketAddress
{
public:
/** Create empty Ipv6 address structure.
\param port Port number */
Ipv6Address(port_t port = 0);
/** Create Ipv6 address structure.
\param a Socket address in network byte order
\param port Port number in host byte order */
Ipv6Address(struct in6_addr& a,port_t port);
/** Create Ipv6 address structure.
\param host Hostname to be resolved
\param port Port number in host byte order */
Ipv6Address(const std::string& host,port_t port);
Ipv6Address(struct sockaddr_in6&);
~Ipv6Address();
// SocketAddress implementation
operator struct sockaddr *();
operator socklen_t();
bool operator==(SocketAddress&);
void SetPort(port_t port);
port_t GetPort();
void SetAddress(struct sockaddr *sa);
int GetFamily();
bool IsValid();
std::auto_ptr<SocketAddress> GetCopy();
/** Convert address struct to text. */
std::string Convert(bool include_port = false);
std::string Reverse();
/** Resolve hostname. */
static bool Resolve(const std::string& hostname,struct in6_addr& a);
/** Reverse resolve (IP to hostname). */
static bool Reverse(struct in6_addr& a,std::string& name);
/** Convert address struct to text. */
static std::string Convert(struct in6_addr& a,bool mixed = false);
void SetFlowinfo(uint32_t);
uint32_t GetFlowinfo();
#ifndef _WIN32
void SetScopeId(uint32_t);
uint32_t GetScopeId();
#endif
private:
Ipv6Address(const Ipv6Address& ) {} // copy constructor
Ipv6Address& operator=(const Ipv6Address& ) {
return *this; // assignment operator
}
struct sockaddr_in6 m_addr;
bool m_valid;
};
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // IPPROTO_IPV6
#endif // ENABLE_IPV6
#endif // _SOCKETS_Ipv6Address_H
@@ -1,572 +0,0 @@
#include "Json.h"
#include <stdio.h>
#include <sstream>
#include "Utility.h"
#define C buffer[index]
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
// --------------------------------------------------------------------------------
Json::Json() : m_type(TYPE_UNKNOWN)
{
}
// --------------------------------------------------------------------------------
Json::Json(char value) : m_type(TYPE_INTEGER), m_i_value(value)
{
}
// --------------------------------------------------------------------------------
Json::Json(short value) : m_type(TYPE_INTEGER), m_i_value(value)
{
}
// --------------------------------------------------------------------------------
Json::Json(long value) : m_type(TYPE_INTEGER), m_i_value(value)
{
}
// --------------------------------------------------------------------------------
//Json::Json(int64_t value) : m_type(TYPE_INTEGER), m_i_value(value)
Json::Json(long long value) : m_type(TYPE_INTEGER), m_i_value(value)
{
}
// --------------------------------------------------------------------------------
Json::Json(double value) : m_type(TYPE_REAL), m_d_value(value)
{
}
// --------------------------------------------------------------------------------
Json::Json(const char *value) : m_type(TYPE_STRING), m_str_value(value)
{
}
// --------------------------------------------------------------------------------
Json::Json(const std::string& value) : m_type(TYPE_STRING), m_str_value(value)
{
}
// --------------------------------------------------------------------------------
Json::Json(bool value) : m_type(TYPE_BOOLEAN), m_b_value(value)
{
}
// --------------------------------------------------------------------------------
Json::Json(json_type_t t) : m_type(t)
{
if (t != TYPE_ARRAY && t != TYPE_OBJECT)
throw Exception("Must be type: Array or type: Object");
}
// --------------------------------------------------------------------------------
Json::~Json()
{
}
// --------------------------------------------------------------------------------
Json::json_type_t Json::Type() const { return m_type; }
// --------------------------------------------------------------------------------
bool Json::HasValue(const std::string& name) const
{
if (m_type != TYPE_OBJECT)
return false;
return m_object.find(name) != m_object.end();
}
// --------------------------------------------------------------------------------
Json::operator char() const
{
return (char)m_i_value;
}
// --------------------------------------------------------------------------------
Json::operator short() const
{
return (short)m_i_value;
}
// --------------------------------------------------------------------------------
Json::operator long() const
{
return m_i_value;
}
// --------------------------------------------------------------------------------
Json::operator int64_t() const
{
return m_i_value;
}
// --------------------------------------------------------------------------------
Json::operator double() const
{
return m_d_value;
}
// --------------------------------------------------------------------------------
Json::operator std::string() const
{
return m_str_value;
}
// --------------------------------------------------------------------------------
Json::operator bool() const
{
return m_b_value;
}
// --------------------------------------------------------------------------------
const Json& Json::operator[](const char *name) const
{
if (m_type != TYPE_OBJECT)
throw Exception("Must be type: Object");
json_map_t::const_iterator it = m_object.find(name);
if (it != m_object.end())
return it -> second;
throw Exception("Key not found: " + std::string(name));
}
// --------------------------------------------------------------------------------
Json& Json::operator[](const char *name)
{
if (m_type == TYPE_UNKNOWN)
m_type = TYPE_OBJECT;
if (m_type != TYPE_OBJECT)
throw Exception("Must be type: Object");
return m_object[name];
}
// --------------------------------------------------------------------------------
const Json& Json::operator[](const std::string& name) const
{
if (m_type != TYPE_OBJECT)
throw Exception("Must be type: Object");
json_map_t::const_iterator it = m_object.find(name);
if (it != m_object.end())
return it -> second;
throw Exception("Key not found: " + name);
}
// --------------------------------------------------------------------------------
Json& Json::operator[](const std::string& name)
{
if (m_type == TYPE_UNKNOWN)
m_type = TYPE_OBJECT;
if (m_type != TYPE_OBJECT)
throw Exception("Must be type: Object");
return m_object[name];
}
// --------------------------------------------------------------------------------
void Json::Add(Json data)
{
if (m_type == TYPE_UNKNOWN)
m_type = TYPE_ARRAY;
if (m_type != TYPE_ARRAY)
throw Exception("trying to add array data in non-array");
m_array.push_back(data);
}
// --------------------------------------------------------------------------------
const std::string& Json::GetString() const
{
return m_str_value;
}
// --------------------------------------------------------------------------------
Json::json_list_t& Json::GetArray()
{
if (m_type == TYPE_UNKNOWN)
m_type = TYPE_ARRAY;
if (m_type != TYPE_ARRAY)
throw Exception("Json instance not of type: Array");
return m_array;
}
// --------------------------------------------------------------------------------
Json::json_map_t& Json::GetObject()
{
if (m_type == TYPE_UNKNOWN)
m_type = TYPE_OBJECT;
if (m_type != TYPE_OBJECT)
throw Exception("Json instance not of type: Array");
return m_object;
}
// --------------------------------------------------------------------------------
const Json::json_list_t& Json::GetArray() const
{
if (m_type != TYPE_ARRAY)
throw Exception("Json instance not of type: Array");
return m_array;
}
// --------------------------------------------------------------------------------
const Json::json_map_t& Json::GetObject() const
{
if (m_type != TYPE_OBJECT)
throw Exception("Json instance not of type: Array");
return m_object;
}
// --------------------------------------------------------------------------------
Json Json::Parse(const std::string& data)
{
size_t i = 0;
Json obj;
obj.Parse(data.c_str(), i);
return obj;
}
// --------------------------------------------------------------------------------
char Json::Parse(const char *buffer, size_t& index)
{
while (C == ' ' || C == 9 || C == 13 || C == 10)
++index;
size_t x = index; // origin
std::string ord;
if (C == '-' || isdigit(C)) // Number
{
bool dot = false;
if (C == '-')
{
++index;
}
while (isdigit(C) || C == '.')
{
if (C == '.')
dot = true;
++index;
}
size_t sz = index - x;
ord.resize(sz);
memcpy(&ord[0], &buffer[x], sz);
if (dot)
{
m_type = TYPE_REAL;
m_d_value = atof(ord.c_str());
}
else
{
m_type = TYPE_INTEGER;
m_i_value = atoi(ord.c_str());
}
}
else
if (C == 34) // " - String
{
bool ign = false;
x = ++index;
while (C && (ign || C != 34))
{
if (ign)
{
ign = false;
}
else
if (C == '\\')
{
ign = true;
}
++index;
}
size_t sz = index - x;
ord.resize(sz);
memcpy(&ord[0], &buffer[x], sz);
decode(ord);
++index;
m_type = TYPE_STRING;
m_str_value = ord;
}
else
if (!strncmp(&buffer[index], "null", 4)) // null value
{
m_type = TYPE_UNKNOWN;
index += 4;
}
else
if (!strncmp(&buffer[index], "true", 4)) // Boolean: true
{
m_type = TYPE_BOOLEAN;
m_b_value = true;
index += 4;
}
else
if (!strncmp(&buffer[index], "false", 5)) // Boolean: false
{
m_type = TYPE_BOOLEAN;
m_b_value = false;
index += 5;
}
else
if (C == '[') // Array
{
++index;
m_type = TYPE_ARRAY;
while (true)
{
char res;
Json o;
if ((res = o.Parse(buffer, index)) == 0)
{
m_array.push_back(o);
}
else
if (res == ']')
{
break;
}
else
if (res == ',') // another element follows
{
}
else
{
throw Exception(std::string("Unexpected end of Array: ") + res);
}
}
}
else
if (C == ']') // end of Array
{
++index;
return ']';
}
else
if (C == '{') // Object
{
++index;
m_type = TYPE_OBJECT;
int state = 0;
std::string element_name;
bool quit = false;
while (!quit)
{
Json o;
char res = o.Parse(buffer, index);
switch (state)
{
case 0:
if (res == ',') // another object follow
break;
if (res == '}') // end of Object
{
quit = true;
break;
}
if (res || o.Type() != TYPE_STRING)
throw Exception("Object element name missing");
element_name = o.GetString();
state = 1;
break;
case 1:
if (res != ':')
throw Exception("Object element separator missing");
state = 2;
break;
case 2:
if (res)
throw Exception(std::string("Unexpected character when parsing anytype: ") + res);
m_object[element_name] = o;
state = 0;
break;
}
}
}
else
if (C == '}') // end of Object
{
++index;
return '}';
}
else
if (C == ',')
{
++index;
return ',';
}
else
if (C == ':')
{
++index;
return ':';
}
else
{
throw Exception("Can't parse Json representation: " + std::string(&buffer[index]));
}
return 0;
}
// --------------------------------------------------------------------------------
std::string Json::ToString(bool quote) const
{
switch (m_type)
{
case TYPE_UNKNOWN:
break;
case TYPE_INTEGER:
return Utility::l2string(m_i_value);
case TYPE_REAL:
{
char slask[100];
sprintf(slask, "%f", m_d_value);
return slask;
}
case TYPE_STRING:
{
std::ostringstream tmp;
tmp << "\"" << encode(m_str_value) << "\"";
return tmp.str();
}
case TYPE_BOOLEAN:
return m_b_value ? "true" : "false";
case TYPE_ARRAY:
{
std::ostringstream tmp;
bool first = true;
tmp << "[";
for (json_list_t::const_iterator it = m_array.begin(); it != m_array.end(); it++)
{
const Json& ref = *it;
if (!first)
tmp << ",";
tmp << ref.ToString(quote);
first = false;
}
tmp << "]";
return tmp.str();
}
case TYPE_OBJECT:
{
std::ostringstream tmp;
bool first = true;
tmp << "{";
for (json_map_t::const_iterator it = m_object.begin(); it != m_object.end(); it++)
{
const std::pair<std::string, Json>& ref = *it;
if (!first)
tmp << ",";
if (quote)
tmp << "\"" << encode(ref.first) << "\":" << ref.second.ToString(quote);
else
tmp << ref.first << ":" << ref.second.ToString(quote);
first = false;
}
tmp << "}";
return tmp.str();
}
}
return "null";
}
// --------------------------------------------------------------------------------
void Json::encode(std::string& src) const
{
size_t pos = src.find("\\");
while (pos != std::string::npos)
{
src.replace(pos, 1, "\\\\");
pos = src.find("\\", pos + 2);
}
pos = src.find("\r");
while (pos != std::string::npos)
{
src.replace(pos, 1, "\\r");
pos = src.find("\r", pos + 2);
}
pos = src.find("\n");
while (pos != std::string::npos)
{
src.replace(pos, 1, "\\n");
pos = src.find("\n", pos + 2);
}
pos = src.find("\"");
while (pos != std::string::npos)
{
src.replace(pos, 1, "\\\"");
pos = src.find("\"", pos + 2);
}
}
// --------------------------------------------------------------------------------
void Json::decode(std::string& src) const
{
size_t pos = src.find("\\\"");
while (pos != std::string::npos)
{
src.replace(pos, 2, "\"");
pos = src.find("\\\"", pos + 1);
}
pos = src.find("\\r");
while (pos != std::string::npos)
{
src.replace(pos, 2, "\r");
pos = src.find("\\r", pos + 1);
}
pos = src.find("\\n");
while (pos != std::string::npos)
{
src.replace(pos, 2, "\n");
pos = src.find("\\n", pos + 1);
}
pos = src.find("\\\\");
while (pos != std::string::npos)
{
src.replace(pos, 2, "\\");
pos = src.find("\\\\", pos + 1);
}
}
// --------------------------------------------------------------------------------
std::string Json::encode(const std::string& src) const
{
std::string tmp(src);
encode(tmp);
return tmp;
}
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
@@ -1,102 +0,0 @@
#ifndef _SOCKETS_Json_H
#define _SOCKETS_Json_H
#include "Exception.h"
#include <list>
#include <map>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class Json
{
public:
typedef std::list<Json> json_list_t;
typedef std::map<std::string, Json> json_map_t;
typedef enum {
TYPE_UNKNOWN = 0,
TYPE_INTEGER,
TYPE_REAL,
TYPE_STRING,
TYPE_BOOLEAN,
TYPE_ARRAY,
TYPE_OBJECT
} json_type_t;
public:
/** Default constructor */
Json(); //m_type(TYPE_UNKNOWN);
/** Basic type constructors */
Json(char value);
Json(short value);
Json(long value); //m_type(TYPE_INTEGER), m_i_value(value);
Json(long long value);
// LG Json(int64_t value);
Json(double value); //m_type(TYPE_REAL), m_d_value(value);
Json(const char *value); //m_type(TYPE_STRING), m_str_value(value);
Json(const std::string& value); //m_type(TYPE_STRING), m_str_value(value);
Json(bool value); //m_type(TYPE_BOOLEAN), m_b_value(value);
/** Complex type constructor (array, object) */
Json(json_type_t t); //m_type(t);
virtual ~Json();
char Parse(const char *buffer, size_t& index);
json_type_t Type() const;
bool HasValue(const std::string& name) const;
operator char() const;
operator short() const;
operator long() const;
//operator int64_t() const;
operator long long() const;
operator double() const;
operator std::string() const;
operator bool() const;
const Json& operator[](const char *name) const;
Json& operator[](const char *name);
const Json& operator[](const std::string& name) const;
Json& operator[](const std::string& name);
void Add(Json data);
const std::string& GetString() const;
const json_list_t& GetArray() const;
json_list_t& GetArray();
const json_map_t& GetObject() const;
json_map_t& GetObject();
std::string ToString(bool quote = true) const;
static Json Parse(const std::string& data);
void encode(std::string& src) const;
void decode(std::string& src) const;
std::string encode(const std::string&) const;
private:
json_type_t m_type;
long m_i_value;
double m_d_value;
std::string m_str_value;
bool m_b_value;
json_list_t m_array;
json_map_t m_object;
};
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // _SOCKETS_Json_H
@@ -1,511 +0,0 @@
/** \file ListenSocket.h
** \date 2004-02-13
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_ListenSocket_H
#define _SOCKETS_ListenSocket_H
#include "sockets-config.h"
#ifdef _WIN32
#include <stdlib.h>
#else
#include <errno.h>
#endif
#include "ISocketHandler.h"
#include "Socket.h"
#include "Utility.h"
#include "SctpSocket.h"
#include "Ipv4Address.h"
#include "Ipv6Address.h"
#ifdef ENABLE_EXCEPTIONS
#include "Exception.h"
#endif
#include "Lock.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
/** Binds incoming port number to new Socket class X.
\ingroup basic */
template <class X>
class ListenSocket : public Socket
{
public:
/** Constructor.
\param h ISocketHandler reference
\param use_creator Optional use of creator (default true) */
ListenSocket(ISocketHandler& h,bool use_creator = true) : Socket(h), m_depth(0), m_creator(NULL)
,m_bHasCreate(false) {
if (use_creator) {
m_creator = new X(h);
Socket *tmp = m_creator -> Create();
if (tmp && dynamic_cast<X *>(tmp)) {
m_bHasCreate = true;
}
if (tmp) {
delete tmp;
}
}
}
~ListenSocket() {
if (m_creator) {
delete m_creator;
}
}
/** Close file descriptor. */
int Close() {
if (GetSocket() != INVALID_SOCKET) {
if (closesocket(GetSocket()) == -1) {
} else {
Attach(INVALID_SOCKET);
}
}
return 0;
}
/** Bind and listen to any interface.
\param port Port (0 is random)
\param depth Listen queue depth */
int Bind(port_t port,int depth = 20) {
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
if (IsIpv6()) {
Ipv6Address ad(port);
return Bind(ad, depth);
} else
#endif
#endif
{
Ipv4Address ad(port);
return Bind(ad, depth);
}
}
int Bind(SocketAddress& ad,int depth) {
#ifdef USE_SCTP
if (dynamic_cast<SctpSocket *>(m_creator)) {
return Bind(ad, "sctp", depth);
}
#endif
return Bind(ad, "tcp", depth);
}
/** Bind and listen to any interface, with optional protocol.
\param port Port (0 is random)
\param protocol Network protocol
\param depth Listen queue depth */
int Bind(port_t port,const std::string& protocol,int depth = 20) {
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
if (IsIpv6()) {
Ipv6Address ad(port);
return Bind(ad, protocol, depth);
} else
#endif
#endif
{
Ipv4Address ad(port);
return Bind(ad, protocol, depth);
}
}
/** Bind and listen to specific interface.
\param intf Interface hostname
\param port Port (0 is random)
\param depth Listen queue depth */
int Bind(const std::string& intf,port_t port,int depth = 20) {
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
if (IsIpv6()) {
Ipv6Address ad(intf, port);
if (ad.IsValid()) {
return Bind(ad, depth);
}
Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
return -1;
} else
#endif
#endif
{
Ipv4Address ad(intf, port);
if (ad.IsValid()) {
return Bind(ad, depth);
}
Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
return -1;
}
}
/** Bind and listen to specific interface.
\param intf Interface hostname
\param port Port (0 is random)
\param protocol Network protocol
\param depth Listen queue depth */
int Bind(const std::string& intf,port_t port,const std::string& protocol,int depth = 20) {
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
if (IsIpv6()) {
Ipv6Address ad(intf, port);
if (ad.IsValid()) {
return Bind(ad, protocol, depth);
}
Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
return -1;
} else
#endif
#endif
{
Ipv4Address ad(intf, port);
if (ad.IsValid()) {
return Bind(ad, protocol, depth);
}
Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
return -1;
}
}
/** Bind and listen to ipv4 interface.
\param a Ipv4 interface address
\param port Port (0 is random)
\param depth Listen queue depth */
int Bind(ipaddr_t a,port_t port,int depth = 20) {
Ipv4Address ad(a, port);
#ifdef USE_SCTP
if (dynamic_cast<SctpSocket *>(m_creator)) {
return Bind(ad, "sctp", depth);
}
#endif
return Bind(ad, "tcp", depth);
}
/** Bind and listen to ipv4 interface.
\param a Ipv4 interface address
\param port Port (0 is random)
\param protocol Network protocol
\param depth Listen queue depth */
int Bind(ipaddr_t a,port_t port,const std::string& protocol,int depth) {
Ipv4Address ad(a, port);
return Bind(ad, protocol, depth);
}
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
/** Bind and listen to ipv6 interface.
\param a Ipv6 interface address
\param port Port (0 is random)
\param depth Listen queue depth */
int Bind(in6_addr a,port_t port,int depth = 20) {
Ipv6Address ad(a, port);
#ifdef USE_SCTP
if (dynamic_cast<SctpSocket *>(m_creator)) {
return Bind(ad, "sctp", depth);
}
#endif
return Bind(ad, "tcp", depth);
}
/** Bind and listen to ipv6 interface.
\param a Ipv6 interface address
\param port Port (0 is random)
\param protocol Network protocol
\param depth Listen queue depth */
int Bind(in6_addr a,port_t port,const std::string& protocol,int depth) {
Ipv6Address ad(a, port);
return Bind(ad, protocol, depth);
}
#endif
#endif
/** Bind and listen to network interface.
\param ad Interface address
\param protocol Network protocol
\param depth Listen queue depth */
int Bind(SocketAddress& ad,const std::string& protocol,int depth) {
SOCKET s;
if ( (s = CreateSocket(ad.GetFamily(), SOCK_STREAM, protocol)) == INVALID_SOCKET) {
return -1;
}
// socket must be nonblocking for async connect
if (!SetNonblocking(true, s)) {
closesocket(s);
return -1;
}
if (bind(s, ad, ad) == -1) {
Handler().LogError(this, "bind", Errno, StrError(Errno), LOG_LEVEL_FATAL);
closesocket(s);
#ifdef ENABLE_EXCEPTIONS
throw Exception("bind() failed for port " + Utility::l2string(ad.GetPort()) + ": " + StrError(Errno));
#endif
return -1;
}
if (listen(s, depth) == -1) {
Handler().LogError(this, "listen", Errno, StrError(Errno), LOG_LEVEL_FATAL);
closesocket(s);
#ifdef ENABLE_EXCEPTIONS
throw Exception("listen() failed for port " + Utility::l2string(ad.GetPort()) + ": " + StrError(Errno));
#endif
return -1;
}
m_depth = depth;
Attach(s);
return 0;
}
/** Return assigned port number. */
port_t GetPort() {
return GetSockPort();
}
/** Return listen queue depth. */
int GetDepth() {
return m_depth;
}
/** OnRead on a ListenSocket receives an incoming connection. */
void OnRead() {
struct sockaddr sa;
int max = 10; // process max 10 incoming connection in one call
while (max--) {
socklen_t sa_len = sizeof(struct sockaddr);
SOCKET a_s = accept(GetSocket(), &sa, &sa_len);
if (a_s == INVALID_SOCKET) {
// EAGAIN or EWOULDBLOCK
#ifdef _WIN32
if (Errno != WSAEWOULDBLOCK)
#else
if (Errno != EWOULDBLOCK)
#endif
{
Handler().LogError(this, "accept", Errno, StrError(Errno), LOG_LEVEL_ERROR);
}
return;
}
if (!Handler().OkToAccept(this)) {
Handler().LogError(this, "accept", -1, "Not OK to accept", LOG_LEVEL_WARNING);
closesocket(a_s);
return;
}
if (Handler().GetCount() >= Handler().MaxCount()) {
Handler().LogError(this, "accept", (int)Handler().GetCount(), "ISocketHandler socket limit reached", LOG_LEVEL_FATAL);
closesocket(a_s);
return;
}
//
Socket *tmp = NULL;
if (Handler().IsThreaded()) {
ISocketHandler& h = Handler().GetRandomHandler();
tmp = new X(h); // %! no support for Create
#ifdef ENABLE_IPV6
tmp -> SetIpv6( IsIpv6() );
#endif
tmp -> SetParent(this);
tmp -> Attach(a_s);
tmp -> SetNonblocking(true);
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
if (sa_len == sizeof(struct sockaddr_in6)) {
if (reinterpret_cast<struct sockaddr_in6&>(sa).sin6_family == AF_INET6) {
Ipv6Address ad(reinterpret_cast<struct sockaddr_in6&>(sa).sin6_addr,
ntohs(reinterpret_cast<struct sockaddr_in6&>(sa).sin6_port));
ad.SetFlowinfo(reinterpret_cast<struct sockaddr_in6&>(sa).sin6_flowinfo);
#ifndef _WIN32
ad.SetScopeId(reinterpret_cast<struct sockaddr_in6&>(sa).sin6_scope_id);
#endif
tmp -> SetRemoteAddress(ad);
}
}
#endif
#endif
if (sa_len == sizeof(struct sockaddr_in)) {
struct sockaddr_in *p = (struct sockaddr_in *)&sa;
if (p -> sin_family == AF_INET) {
Ipv4Address ad(p -> sin_addr,ntohs(p -> sin_port));
tmp -> SetRemoteAddress(ad);
}
}
tmp -> SetConnected(true);
tmp -> Init();
tmp -> SetDeleteByHandler(true);
{
Lock lock(h.GetMutex());
h.Add(tmp);
#ifdef HAVE_OPENSSL
if (tmp -> IsSSL()) { // SSL Enabled socket
// %! OnSSLAccept calls SSLNegotiate that can finish in this one call.
// %! If that happens and negotiation fails, the 'tmp' instance is
// %! still added to the list of active sockets in the sockethandler.
// %! See bugfix for this in SocketHandler::Select - don't Set rwx
// %! flags if CloseAndDelete() flag is true.
// %! An even better fugbix (see TcpSocket::OnSSLAccept) now avoids
// %! the Add problem altogether, so ignore the above.
// %! (OnSSLAccept does no longer call SSLNegotiate().)
tmp -> OnSSLAccept();
} else
#endif
{
tmp -> OnAccept();
}
}
h.Release();
} else {
tmp = m_bHasCreate ? m_creator -> Create() : new X(Handler());
#ifdef ENABLE_IPV6
tmp -> SetIpv6( IsIpv6() );
#endif
tmp -> SetParent(this);
tmp -> Attach(a_s);
tmp -> SetNonblocking(true);
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
if (sa_len == sizeof(struct sockaddr_in6)) {
if (reinterpret_cast<struct sockaddr_in6&>(sa).sin6_family == AF_INET6) {
Ipv6Address ad(reinterpret_cast<struct sockaddr_in6&>(sa).sin6_addr,
ntohs(reinterpret_cast<struct sockaddr_in6&>(sa).sin6_port));
ad.SetFlowinfo(reinterpret_cast<struct sockaddr_in6&>(sa).sin6_flowinfo);
#ifndef _WIN32
ad.SetScopeId(reinterpret_cast<struct sockaddr_in6&>(sa).sin6_scope_id);
#endif
tmp -> SetRemoteAddress(ad);
}
}
#endif
#endif
if (sa_len == sizeof(struct sockaddr_in)) {
struct sockaddr_in *p = (struct sockaddr_in *)&sa;
if (p -> sin_family == AF_INET) {
Ipv4Address ad(p -> sin_addr,ntohs(p -> sin_port));
tmp -> SetRemoteAddress(ad);
}
}
tmp -> SetConnected(true);
tmp -> Init();
tmp -> SetDeleteByHandler(true);
Handler().Add(tmp);
#ifdef HAVE_OPENSSL
if (tmp -> IsSSL()) { // SSL Enabled socket
// %! OnSSLAccept calls SSLNegotiate that can finish in this one call.
// %! If that happens and negotiation fails, the 'tmp' instance is
// %! still added to the list of active sockets in the sockethandler.
// %! See bugfix for this in SocketHandler::Select - don't Set rwx
// %! flags if CloseAndDelete() flag is true.
// %! An even better fugbix (see TcpSocket::OnSSLAccept) now avoids
// %! the Add problem altogether, so ignore the above.
// %! (OnSSLAccept does no longer call SSLNegotiate().)
tmp -> OnSSLAccept();
} else
#endif
{
tmp -> OnAccept();
}
}
} // while (true)
}
/** Please don't use this method.
"accept()" is handled automatically in the OnRead() method. */
virtual SOCKET Accept(SOCKET socket, struct sockaddr *saptr, socklen_t *lenptr) {
return accept(socket, saptr, lenptr);
}
bool HasCreator() {
return m_bHasCreate;
}
void OnOptions(int,int,int,SOCKET) {
SetSoReuseaddr(true);
}
protected:
ListenSocket(const ListenSocket& s) : Socket(s) {}
private:
ListenSocket& operator=(const ListenSocket& ) {
return *this;
}
int m_depth;
X *m_creator;
bool m_bHasCreate;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_ListenSocket_H
@@ -1,57 +0,0 @@
/** \file Lock.cpp
** \date 2005-08-22
** \author grymse@alhem.net
**/
/*
Copyright (C) 2005-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "IMutex.h"
#include "Lock.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
Lock::Lock(const IMutex& m) : m_mutex(m)
{
m_mutex.Lock();
}
Lock::~Lock()
{
m_mutex.Unlock();
}
#ifdef SOCKETS_NAMESPACE
}
#endif
@@ -1,62 +0,0 @@
/** \file Lock.h
** \date 2005-08-22
** \author grymse@alhem.net
**/
/*
Copyright (C) 2005-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_Lock_H
#define _SOCKETS_Lock_H
#include "sockets-config.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class IMutex;
/** IMutex encapsulation class.
\ingroup threading */
class Lock
{
public:
Lock(const IMutex&);
~Lock();
private:
const IMutex& m_mutex;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_Lock_H
@@ -1,44 +0,0 @@
noinst_LIBRARIES = libsockets.a
libsockets_a_SOURCES = Ajp13Socket.cpp HttpRequest.cpp SocketHandlerEp.cpp \
AjpBaseSocket.cpp HttpResponse.cpp SocketHandlerThread.cpp \
Base64.cpp HTTPSocket.cpp socket_include.cpp \
Debug.cpp HttpTransaction.cpp \
Event.cpp IEventOwner.cpp SocketStream.cpp \
EventHandler.cpp Ipv4Address.cpp SocketThread.cpp \
EventTime.cpp Ipv6Address.cpp SSLInitializer.cpp \
Exception.cpp Json.cpp StdoutLog.cpp \
File.cpp Lock.cpp StreamSocket.cpp \
FileStream.cpp MemFile.cpp StreamWriter.cpp \
HttpBaseSocket.cpp Mutex.cpp TcpSocket.cpp \
HttpClientSocket.cpp Parse.cpp Thread.cpp \
HttpdCookies.cpp ResolvServer.cpp UdpSocket.cpp \
HttpDebugSocket.cpp ResolvSocket.cpp Utility.cpp \
HttpdForm.cpp SctpSocket.cpp XmlDocument.cpp \
HttpdSocket.cpp Semaphore.cpp XmlException.cpp \
HttpGetSocket.cpp SmtpdSocket.cpp XmlNode.cpp \
HttpPostSocket.cpp Socket.cpp \
HttpPutSocket.cpp SocketHandler.cpp \
ajp13.h HttpTransaction.h SocketAddress.h \
Ajp13Socket.h IBase.h Socket.h \
AjpBaseSocket.h IEventHandler.h SocketHandlerEp.h \
Base64.h IEventOwner.h SocketHandler.h \
Debug.h IFile.h SocketHandlerThread.h \
Event.h IFileUpload.h socket_include.h \
EventHandler.h IHttpServer.h sockets-config.h \
EventTime.h IMutex.h SocketStream.h \
Exception.h Ipv4Address.h SocketThread.h \
File.h Ipv6Address.h SSLInitializer.h \
FileStream.h ISocketHandler.h StdLog.h \
HttpBaseSocket.h IStream.h StdoutLog.h \
HttpClientSocket.h Json.h StreamSocket.h \
HttpdCookies.h ListenSocket.h StreamWriter.h \
HttpDebugSocket.h Lock.h TcpSocket.h \
HttpdForm.h MemFile.h Thread.h \
HttpdSocket.h Mutex.h UdpSocket.h \
HttpGetSocket.h Parse.h Utility.h \
HttpPostSocket.h ResolvServer.h XmlDocument.h \
HttpPutSocket.h ResolvSocket.h XmlException.h \
HttpRequest.h SctpSocket.h XmlNode.h \
HttpResponse.h Semaphore.h \
HTTPSocket.h SmtpdSocket.h
@@ -1,349 +0,0 @@
/** \file MemFile.cpp
** \date 2005-04-25
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#include <stdio.h>
#include <stdarg.h>
#include <cstring>
#include <iostream>
#include "MemFile.h"
#include "Exception.h"
#include "Lock.h"
#include "Utility.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
MemFile::MemFile()
:m_src(m_src)
,m_src_valid(false)
,m_base(new block_t)
,m_current_read(m_base)
,m_current_write(m_base)
,m_current_write_nr(0)
,m_read_ptr(0)
,m_write_ptr(0)
,m_b_read_caused_eof(false)
,m_ref_count(0)
,m_ref_decreased(false)
{
}
MemFile::MemFile(MemFile& s)
:m_src(s)
,m_src_valid(true)
,m_base(s.m_base)
,m_current_read(m_base)
,m_current_write(s.m_current_write)
,m_current_write_nr(s.m_current_write_nr)
,m_read_ptr(0)
,m_write_ptr(s.m_write_ptr)
,m_b_read_caused_eof(false)
,m_ref_count(0)
,m_ref_decreased(false)
,m_path(s.m_path)
{
m_src.Increase();
}
MemFile::MemFile(File& f)
:m_src(m_src)
,m_src_valid(false)
,m_base(new block_t)
,m_current_read(NULL)
,m_current_write(NULL)
,m_current_write_nr(0)
,m_read_ptr(0)
,m_write_ptr(0)
,m_b_read_caused_eof(false)
,m_ref_count(0)
,m_ref_decreased(false)
,m_path(f.Path())
{
m_current_read = m_base;
m_current_write = m_base;
char slask[32768];
size_t n;
while ((n = f.fread(slask, 1, 32768)) > 0)
{
fwrite(slask, 1, n);
}
}
MemFile::~MemFile()
{
if (m_ref_count)
std::cerr << "MemFile destructor with a ref count of " + Utility::l2string(m_ref_count) << std::endl;
while (m_base && !m_src_valid)
{
block_t *p = m_base;
m_base = p -> next;
delete p;
}
if (m_src_valid && !m_ref_decreased)
{
m_src.Decrease();
m_ref_decreased = true;
}
}
bool MemFile::fopen(const std::string& path, const std::string& mode)
{
return true;
}
void MemFile::fclose() const
{
if (m_src_valid && !m_ref_decreased)
{
m_src.Decrease();
m_ref_decreased = true;
}
}
size_t MemFile::fread(char *ptr, size_t size, size_t nmemb) const
{
size_t p = m_read_ptr % BLOCKSIZE;
size_t sz = size * nmemb;
size_t available = m_write_ptr - m_read_ptr;
if (sz > available) // read beyond eof
{
sz = available;
m_b_read_caused_eof = true;
}
if (!sz)
{
return 0;
}
if (p + sz < BLOCKSIZE)
{
memcpy(ptr, m_current_read -> data + p, sz);
m_read_ptr += sz;
}
else
{
size_t sz1 = BLOCKSIZE - p;
size_t sz2 = sz - sz1;
memcpy(ptr, m_current_read -> data + p, sz1);
m_read_ptr += sz1;
while (sz2 > BLOCKSIZE)
{
if (m_current_read -> next)
{
m_current_read = m_current_read -> next;
memcpy(ptr + sz1, m_current_read -> data, BLOCKSIZE);
m_read_ptr += BLOCKSIZE;
sz1 += BLOCKSIZE;
sz2 -= BLOCKSIZE;
}
else
{
return sz1;
}
}
if (m_current_read -> next)
{
m_current_read = m_current_read -> next;
memcpy(ptr + sz1, m_current_read -> data, sz2);
m_read_ptr += sz2;
}
else
{
return sz1;
}
}
return sz;
}
size_t MemFile::fwrite(const char *ptr, size_t size, size_t nmemb)
{
size_t p = m_write_ptr % BLOCKSIZE;
int nr = (int)m_write_ptr / BLOCKSIZE;
size_t sz = size * nmemb;
if (m_current_write_nr < nr)
{
block_t *next = new block_t;
m_current_write -> next = next;
m_current_write = next;
m_current_write_nr++;
}
if (p + sz <= BLOCKSIZE)
{
memcpy(m_current_write -> data + p, ptr, sz);
m_write_ptr += sz;
}
else
{
size_t sz1 = BLOCKSIZE - p; // size left
size_t sz2 = sz - sz1;
memcpy(m_current_write -> data + p, ptr, sz1);
m_write_ptr += sz1;
while (sz2 > BLOCKSIZE)
{
if (m_current_write -> next)
{
m_current_write = m_current_write -> next;
m_current_write_nr++;
}
else
{
block_t *next = new block_t;
m_current_write -> next = next;
m_current_write = next;
m_current_write_nr++;
}
memcpy(m_current_write -> data, ptr + sz1, BLOCKSIZE);
m_write_ptr += BLOCKSIZE;
sz1 += BLOCKSIZE;
sz2 -= BLOCKSIZE;
}
if (m_current_write -> next)
{
m_current_write = m_current_write -> next;
m_current_write_nr++;
}
else
{
block_t *next = new block_t;
m_current_write -> next = next;
m_current_write = next;
m_current_write_nr++;
}
memcpy(m_current_write -> data, ptr + sz1, sz2);
m_write_ptr += sz2;
}
return sz;
}
char *MemFile::fgets(char *s, int size) const
{
int n = 0;
while (n < size - 1 && !eof())
{
char c;
size_t sz = fread(&c, 1, 1);
if (sz)
{
if (c == 10)
{
s[n] = 0;
return s;
}
s[n++] = c;
}
}
s[n] = 0;
return s;
}
void MemFile::fprintf(const char *format, ...)
{
va_list ap;
char tmp[BLOCKSIZE];
va_start(ap, format);
vsnprintf(tmp, sizeof(tmp), format, ap);
va_end(ap);
fwrite(tmp, 1, strlen(tmp));
}
off_t MemFile::size() const
{
return (off_t)m_write_ptr;
}
bool MemFile::eof() const
{
return m_b_read_caused_eof; //(m_read_ptr < m_write_ptr) ? false : true;
}
void MemFile::reset_read() const
{
m_read_ptr = 0;
m_current_read = m_base;
}
void MemFile::reset_write()
{
m_write_ptr = 0;
m_current_write = m_base;
m_current_write_nr = 0;
}
int MemFile::RefCount() const
{
return m_ref_count;
}
void MemFile::Increase()
{
++m_ref_count;
}
void MemFile::Decrease()
{
--m_ref_count;
}
const std::string& MemFile::Path() const
{
return m_path;
}
#ifdef SOCKETS_NAMESPACE
}
#endif
@@ -1,118 +0,0 @@
/** \file MemFile.h
** \date 2005-04-25
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_MemFile_H
#define _SOCKETS_MemFile_H
#include "sockets-config.h"
#include <map>
#include "File.h"
#include "Mutex.h"
#define BLOCKSIZE 32768
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
/** Implements a memory file.
\ingroup file */
class MemFile : public IFile
{
public:
/** File block structure.
\ingroup file */
struct block_t {
block_t() : next(NULL) {}
struct block_t *next;
char data[BLOCKSIZE];
};
public:
/** Create temporary memory buffer, will be freed when object destructs */
MemFile();
/** Copy buffer from source, reset read ptr */
MemFile(MemFile& );
/** Read file and write to this, create non-temporary memory buffer from f.Path() */
MemFile(File& f);
~MemFile();
bool fopen(const std::string& path, const std::string& mode);
void fclose() const;
size_t fread(char *ptr, size_t size, size_t nmemb) const;
size_t fwrite(const char *ptr, size_t size, size_t nmemb);
char *fgets(char *s, int size) const;
void fprintf(const char *format, ...);
off_t size() const;
bool eof() const;
void reset_read() const;
void reset_write();
/** Reference count when copy constructor is used */
int RefCount() const;
void Increase();
void Decrease();
const std::string& Path() const;
private:
MemFile& operator=(const MemFile& ) {
return *this; // assignment operator
}
MemFile& m_src;
bool m_src_valid;
block_t *m_base;
mutable block_t *m_current_read;
block_t *m_current_write;
int m_current_write_nr;
mutable size_t m_read_ptr;
size_t m_write_ptr;
mutable bool m_b_read_caused_eof;
int m_ref_count;
mutable bool m_ref_decreased;
std::string m_path;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_MemFile_H
@@ -1,83 +0,0 @@
/** \file Mutex.cpp
** \date 2004-10-30
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "Mutex.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
Mutex::Mutex()
{
#ifdef _WIN32
m_mutex = ::CreateMutex(NULL, FALSE, NULL);
#else
pthread_mutex_init(&m_mutex, NULL);
#endif
}
Mutex::~Mutex()
{
#ifdef _WIN32
::CloseHandle(m_mutex);
#else
pthread_mutex_destroy(&m_mutex);
#endif
}
void Mutex::Lock() const
{
#ifdef _WIN32
DWORD d = WaitForSingleObject(m_mutex, INFINITE);
/// \todo check 'd' for result
#else
pthread_mutex_lock(&m_mutex);
#endif
}
void Mutex::Unlock() const
{
#ifdef _WIN32
::ReleaseMutex(m_mutex);
#else
pthread_mutex_unlock(&m_mutex);
#endif
}
#ifdef SOCKETS_NAMESPACE
}
#endif
@@ -1,73 +0,0 @@
/** \file Mutex.h
** \date 2004-10-30
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_Mutex_H
#define _SOCKETS_Mutex_H
#include "sockets-config.h"
#ifndef _WIN32
#include <pthread.h>
#else
#include "socket_include.h"
#include <windows.h>
#endif
#include "IMutex.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
/** Mutex container class, used by Lock.
\ingroup threading */
class Mutex : public IMutex
{
public:
Mutex();
~Mutex();
virtual void Lock() const;
virtual void Unlock() const;
private:
#ifdef _WIN32
HANDLE m_mutex;
#else
mutable pthread_mutex_t m_mutex;
#endif
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_Mutex_H
@@ -1,323 +0,0 @@
/** \file Parse.cpp - parse a string
**
** Written: 1999-Feb-10 grymse@alhem.net
**/
/*
Copyright (C) 1999-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <cstring>
#include "Parse.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
/* implementation of class Parse */
Parse::Parse()
:pa_the_str("")
,pa_splits("")
,pa_ord("")
,pa_the_ptr(0)
,pa_breakchar(0)
,pa_enable(0)
,pa_disable(0)
,pa_nospace(0)
,pa_quote(false)
{
}
Parse::Parse(const std::string&s)
:pa_the_str(s)
,pa_splits("")
,pa_ord("")
,pa_the_ptr(0)
,pa_breakchar(0)
,pa_enable(0)
,pa_disable(0)
,pa_nospace(0)
,pa_quote(false)
{
}
Parse::Parse(const std::string&s,const std::string&sp)
:pa_the_str(s)
,pa_splits(sp)
,pa_ord("")
,pa_the_ptr(0)
,pa_breakchar(0)
,pa_enable(0)
,pa_disable(0)
,pa_nospace(0)
,pa_quote(false)
{
}
Parse::Parse(const std::string&s,const std::string&sp,short nospace)
:pa_the_str(s)
,pa_splits(sp)
,pa_ord("")
,pa_the_ptr(0)
,pa_breakchar(0)
,pa_enable(0)
,pa_disable(0)
,pa_nospace(1)
,pa_quote(false)
{
}
Parse::~Parse()
{
}
#define C ((pa_the_ptr<pa_the_str.size()) ? pa_the_str[pa_the_ptr] : 0)
short Parse::issplit(const char c)
{
for (size_t i = 0; i < pa_splits.size(); i++)
if (pa_splits[i] == c)
return 1;
return 0;
}
void Parse::getsplit()
{
size_t x;
if (C == '=')
{
x = pa_the_ptr++;
} else
{
while (C && (issplit(C)))
pa_the_ptr++;
x = pa_the_ptr;
while (C && !issplit(C) && C != '=')
pa_the_ptr++;
}
if (x == pa_the_ptr && C == '=')
pa_the_ptr++;
pa_ord = (x < pa_the_str.size()) ? pa_the_str.substr(x,pa_the_ptr - x) : "";
}
std::string Parse::getword()
{
size_t x;
int disabled = 0;
int quote = 0;
int rem = 0;
if (pa_nospace)
{
while (C && issplit(C))
pa_the_ptr++;
x = pa_the_ptr;
while (C && !issplit(C) && (C != pa_breakchar || !pa_breakchar || disabled))
{
if (pa_breakchar && C == pa_disable)
disabled = 1;
if (pa_breakchar && C == pa_enable)
disabled = 0;
if (pa_quote && C == '"')
quote = 1;
pa_the_ptr++;
while (quote && C && C != '"')
{
pa_the_ptr++;
}
if (pa_quote && C == '"')
{
pa_the_ptr++;
}
quote = 0;
}
} else
{
if (C == pa_breakchar && pa_breakchar)
{
x = pa_the_ptr++;
rem = 1;
} else
{
while (C && (C == ' ' || C == 9 || C == 13 || C == 10 || issplit(C)))
pa_the_ptr++;
x = pa_the_ptr;
while (C && C != ' ' && C != 9 && C != 13 && C != 10 && !issplit(C) &&
(C != pa_breakchar || !pa_breakchar || disabled))
{
if (pa_breakchar && C == pa_disable)
disabled = 1;
if (pa_breakchar && C == pa_enable)
disabled = 0;
if (pa_quote && C == '"')
{
quote = 1;
pa_the_ptr++;
while (quote && C && C != '"')
{
pa_the_ptr++;
}
if (pa_quote && C == '"')
{
pa_the_ptr++;
}
}
else
pa_the_ptr++;
quote = 0;
}
pa_the_ptr++;
rem = 1;
}
if (x == pa_the_ptr && C == pa_breakchar && pa_breakchar)
pa_the_ptr++;
}
if (x < pa_the_str.size())
{
pa_ord = pa_the_str.substr(x,pa_the_ptr - x - rem);
}
else
{
pa_ord = "";
}
return pa_ord;
}
void Parse::getword(std::string&s)
{
s = Parse::getword();
}
void Parse::getsplit(std::string&s)
{
Parse::getsplit();
s = pa_ord;
}
void Parse::getword(std::string&s,std::string&fill,int l)
{
Parse::getword();
s = "";
while (s.size() + pa_ord.size() < (size_t)l)
s += fill;
s += pa_ord;
}
std::string Parse::getrest()
{
std::string s;
while (C && (C == ' ' || C == 9 || issplit(C)))
pa_the_ptr++;
s = (pa_the_ptr < pa_the_str.size()) ? pa_the_str.substr(pa_the_ptr) : "";
return s;
}
void Parse::getrest(std::string&s)
{
while (C && (C == ' ' || C == 9 || issplit(C)))
pa_the_ptr++;
s = (pa_the_ptr < pa_the_str.size()) ? pa_the_str.substr(pa_the_ptr) : "";
}
long Parse::getvalue()
{
Parse::getword();
return atol(pa_ord.c_str());
}
void Parse::setbreak(const char c)
{
pa_breakchar = c;
}
int Parse::getwordlen()
{
size_t x,y = pa_the_ptr,len;
if (C == pa_breakchar && pa_breakchar)
{
x = pa_the_ptr++;
} else
{
while (C && (C == ' ' || C == 9 || C == 13 || C == 10 || issplit(C)))
pa_the_ptr++;
x = pa_the_ptr;
while (C && C != ' ' && C != 9 && C != 13 && C != 10 && !issplit(C) && (C != pa_breakchar || !pa_breakchar))
pa_the_ptr++;
}
if (x == pa_the_ptr && C == pa_breakchar && pa_breakchar)
pa_the_ptr++;
len = pa_the_ptr - x;
pa_the_ptr = y;
return (int)len;
}
int Parse::getrestlen()
{
size_t y = pa_the_ptr;
size_t len;
while (C && (C == ' ' || C == 9 || issplit(C)))
pa_the_ptr++;
len = strlen(pa_the_str.c_str() + pa_the_ptr);
pa_the_ptr = y;
return (int)len;
}
void Parse::getline()
{
size_t x;
x = pa_the_ptr;
while (C && C != 13 && C != 10)
pa_the_ptr++;
pa_ord = (x < pa_the_str.size()) ? pa_the_str.substr(x,pa_the_ptr - x) : "";
if (C == 13)
pa_the_ptr++;
if (C == 10)
pa_the_ptr++;
}
void Parse::getline(std::string&s)
{
getline();
s = pa_ord;
}
/* end of implementation of class Parse */
/***************************************************/
#ifdef SOCKETS_NAMESPACE
}
#endif
@@ -1,108 +0,0 @@
/** \file Parse.h - parse a string
**
** Written: 1999-Feb-10 grymse@alhem.net
**/
/*
Copyright (C) 1999-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_Parse_H
#define _SOCKETS_Parse_H
#include "sockets-config.h"
#ifdef _MSC_VER
#pragma warning(disable:4514)
#endif
#include <string>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
/***************************************************/
/* interface of class Parse */
/** Splits a string whatever way you want.
\ingroup util */
class Parse
{
public:
Parse();
Parse(const std::string&);
Parse(const std::string&,const std::string&);
Parse(const std::string&,const std::string&,short);
~Parse();
short issplit(const char);
void getsplit();
void getsplit(std::string&);
std::string getword();
void getword(std::string&);
void getword(std::string&,std::string&,int);
std::string getrest();
void getrest(std::string&);
long getvalue();
void setbreak(const char);
int getwordlen();
int getrestlen();
void enablebreak(const char c) {
pa_enable = c;
}
void disablebreak(const char c) {
pa_disable = c;
}
void getline();
void getline(std::string&);
size_t getptr() {
return pa_the_ptr;
}
void EnableQuote(bool b) {
pa_quote = b;
}
private:
std::string pa_the_str;
std::string pa_splits;
std::string pa_ord;
size_t pa_the_ptr;
char pa_breakchar;
char pa_enable;
char pa_disable;
short pa_nospace;
bool pa_quote;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_Parse_H
@@ -1,90 +0,0 @@
http://www.alhem.net/Sockets/
C++ Sockets Library :: installation instructions
Unix (and Cygwin/Mingw on windows)
==================================
1. Change the 'PLATFORM =' line in Makefile
Possible values are
linux-x86-32
win32-cygwin
solaris9-sparc-64
macosx
solaris8
2. If you want to use ssl encrypted socket communication, the library
has support for the third-party library openssl. If necessary, add
the following include directory to Makefile:
INCLUDE = -I<path to openssl>/include
The openssl include directory contains only one directory named
'openssl', in which all header files can be found.
OpenSSL support is enabled by default.
If you don't need encrypted communications, make sure to comment
out this line in the file 'sockets-config.h':
#define HAVE_OPENSSL
3. If you really need thread-safe dns lookups, and your operating has
support for *addrinfo and *nameinfo function calls, make sure this
line in 'sockets-config.h' is commented:
#define NO_GETADDRINFO
By default, dns lookups using getaddrinfo/getnameinfo is disabled.
4. If your operating system supports SCTP, there might be a slight
chance the sctp code in the library works. Uncomment this line in
'sockets-config.h' to try:
//#define USE_SCTP
5. If you need IPv6 support, uncomment this line in
'sockets-config.h':
//#define ENABLE_IPV6
6. Type 'make'
7. If all builds ok, you'll find the static library file 'libSockets.a'
in the build directory.
When compiling the application, any flags used when compiling the library
also needs to be present when including the library .h files. All flags
can be retrieved using the 'Sockets-config' executable. Add something like
this in your Makefile:
CFLAGS += `Sockets-config`
CPPFLAGS += `Sockets-config`
When linking an application using the library, make sure the object and
library files are in correct order on your link command line:
First: Application object files
2nd: -lSockets
3rd: openssl libraries
Finally: Everything else, ending with -lpthread
windows
=======
Project files for various IDE's can be found here:
Project/ Visual studio 6.0
Project.net/ Visual studio .NET
DevCpp/ Dev C++
Please see steps 2-5 above for some details on configuring the library.
When linking on cygwin/mingw, add the following libraries:
-lwsock32
-lws2_32
@@ -1,9 +0,0 @@
MAC notes
---------
The file OSX.zip contains xcode project files for an older version of the library.
Find uuid.h (if missing) here:
http://www.die.net/doc/linux/include/uuid/uuid.h
This used to be a problem, but isn't any more afaik.
@@ -1,99 +0,0 @@
/** \file ResolvServer.cpp
** \date 2005-03-24
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#include "ResolvServer.h"
#ifdef ENABLE_RESOLVER
#include "StdoutLog.h"
#include "ListenSocket.h"
#include "ResolvSocket.h"
#include "SocketHandler.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
ResolvServer::ResolvServer(port_t port)
:Thread()
,m_quit(false)
,m_port(port)
,m_ready(false)
{
}
ResolvServer::~ResolvServer()
{
}
void ResolvServer::Run()
{
// StdoutLog log;
SocketHandler h;
ListenSocket<ResolvSocket> l(h);
if (l.Bind("127.0.0.1", m_port))
{
return;
}
h.Add(&l);
m_ready = true;
while (!m_quit && IsRunning() )
{
h.Select(0, 500000);
}
SetRunning(false);
}
void ResolvServer::Quit()
{
m_quit = true;
}
bool ResolvServer::Ready()
{
return m_ready;
}
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // ENABLE_RESOLVER
@@ -1,78 +0,0 @@
/** \file ResolvServer.h
** \date 2005-03-24
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_ResolvServer_H
#define _SOCKETS_ResolvServer_H
#include "sockets-config.h"
#ifdef ENABLE_RESOLVER
#include "socket_include.h"
#include "Thread.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
/** \defgroup async Asynchronous DNS */
/** Async DNS resolver thread.
\ingroup async */
class ResolvServer : public Thread
{
public:
ResolvServer(port_t);
~ResolvServer();
void Run();
void Quit();
bool Ready();
private:
ResolvServer(const ResolvServer& ) {} // copy constructor
ResolvServer& operator=(const ResolvServer& ) {
return *this; // assignment operator
}
bool m_quit;
port_t m_port;
bool m_ready;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // ENABLE_RESOLVER
#endif // _SOCKETS_ResolvServer_H
@@ -1,442 +0,0 @@
/** \file ResolvSocket.cpp
** \date 2005-03-24
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _WIN32
#ifdef _MSC_VER
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif
#else
#include <netdb.h>
#endif
#include "ResolvSocket.h"
#ifdef ENABLE_RESOLVER
#include "Utility.h"
#include "Parse.h"
#include "ISocketHandler.h"
#include "Lock.h"
#include "Mutex.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
#ifdef _DEBUG
#define DEB(x) x
#else
#define DEB(x)
#endif
// static
ResolvSocket::cache_t ResolvSocket::m_cache;
ResolvSocket::timeout_t ResolvSocket::m_cache_to;
Mutex ResolvSocket::m_cache_mutex;
ResolvSocket::ResolvSocket(ISocketHandler& h)
:TcpSocket(h)
,m_bServer(false)
,m_parent(NULL)
,m_parent_uid(0)
#ifdef ENABLE_IPV6
,m_resolve_ipv6(false)
#endif
,m_cached(false)
{
SetLineProtocol();
}
ResolvSocket::ResolvSocket(ISocketHandler& h, Socket *parent, const std::string& host, port_t port, bool ipv6)
:TcpSocket(h)
,m_bServer(false)
,m_parent(parent)
,m_parent_uid(parent -> UniqueIdentifier())
,m_resolv_host(host)
,m_resolv_port(port)
#ifdef ENABLE_IPV6
,m_resolve_ipv6(ipv6)
#endif
,m_cached(false)
{
SetLineProtocol();
}
ResolvSocket::ResolvSocket(ISocketHandler& h, Socket *parent, ipaddr_t a)
:TcpSocket(h)
,m_bServer(false)
,m_parent(parent)
,m_parent_uid(parent -> UniqueIdentifier())
,m_resolv_port(0)
,m_resolv_address(a)
#ifdef ENABLE_IPV6
,m_resolve_ipv6(false)
#endif
,m_cached(false)
{
SetLineProtocol();
}
#ifdef ENABLE_IPV6
ResolvSocket::ResolvSocket(ISocketHandler& h, Socket *parent, in6_addr& a)
:TcpSocket(h)
,m_bServer(false)
,m_parent(parent)
,m_parent_uid(parent -> UniqueIdentifier())
,m_resolv_port(0)
,m_resolve_ipv6(true)
,m_resolv_address6(a)
,m_cached(false)
{
SetLineProtocol();
}
#endif
ResolvSocket::~ResolvSocket()
{
}
void ResolvSocket::OnLine(const std::string& line)
{
Parse pa(line, ":");
if (m_bServer)
{
m_query = pa.getword();
m_data = pa.getrest();
DEB( fprintf(stderr, " *** ResolvSocket server; query=%s, data=%s\n", m_query.c_str(), m_data.c_str());)
// %! check cache
{
Lock lock(m_cache_mutex);
if (m_cache[m_query].find(m_data) != m_cache[m_query].end())
{
if (time(NULL) - m_cache_to[m_query][m_data] < 3600) // ttl
{
std::string result = m_cache[m_query][m_data];
DEB(fprintf(stderr, " *** Returning cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), result.c_str());)
Send("Cached\n");
if (!result.size()) /* failed */
{
Send("Failed\n\n");
SetCloseAndDelete();
return;
}
else
if (m_query == "gethostbyname")
{
Send("A: " + result + "\n\n");
SetCloseAndDelete();
return;
}
else
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
if (m_query == "gethostbyname2")
{
Send("AAAA: " + result + "\n\n");
SetCloseAndDelete();
return;
}
else
#endif
#endif
if (m_query == "gethostbyaddr")
{
Send("Name: " + result + "\n\n");
SetCloseAndDelete();
return;
}
}
}
}
if (!Detach()) // detach failed?
{
SetCloseAndDelete();
}
return;
}
std::string key = pa.getword();
std::string value = pa.getrest();
DEB( fprintf(stderr, " *** ResolvSocket response; %s: %s\n", key.c_str(), value.c_str());)
if (key == "Cached")
{
m_cached = true;
}
else
if (key == "Failed" && m_parent)
{
DEB( fprintf(stderr, " ************ Resolve failed\n");)
if (Handler().Resolving(m_parent) || Handler().Valid(m_parent_uid))
{
m_parent -> OnResolveFailed(m_resolv_id);
}
// update cache
if (!m_cached)
{
Lock lock(m_cache_mutex);
DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
m_cache[m_query][m_data] = value;
m_cache_to[m_query][m_data] = time(NULL);
}
m_parent = NULL;
}
else
if (key == "Name" && !m_resolv_host.size() && m_parent)
{
if (Handler().Resolving(m_parent) || Handler().Valid(m_parent_uid))
{
m_parent -> OnReverseResolved(m_resolv_id, value);
}
// update cache
if (!m_cached)
{
Lock lock(m_cache_mutex);
DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
m_cache[m_query][m_data] = value;
m_cache_to[m_query][m_data] = time(NULL);
}
m_parent = NULL;
}
else
if (key == "A" && m_parent)
{
if (Handler().Resolving(m_parent) || Handler().Valid(m_parent_uid))
{
ipaddr_t l;
Utility::u2ip(value, l); // ip2ipaddr_t
m_parent -> OnResolved(m_resolv_id, l, m_resolv_port);
}
// update cache
if (!m_cached)
{
Lock lock(m_cache_mutex);
DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
m_cache[m_query][m_data] = value;
m_cache_to[m_query][m_data] = time(NULL);
}
m_parent = NULL; // always use first ip in case there are several
}
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
else
if (key == "AAAA" && m_parent)
{
if (Handler().Resolving(m_parent) || Handler().Valid(m_parent_uid))
{
in6_addr a;
Utility::u2ip(value, a);
m_parent -> OnResolved(m_resolv_id, a, m_resolv_port);
}
// update cache
if (!m_cached)
{
Lock lock(m_cache_mutex);
DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
m_cache[m_query][m_data] = value;
m_cache_to[m_query][m_data] = time(NULL);
}
m_parent = NULL;
}
#endif
#endif
}
void ResolvSocket::OnDetached()
{
DEB( fprintf(stderr, " *** ResolvSocket::OnDetached(); query=%s, data=%s\n", m_query.c_str(), m_data.c_str());)
if (m_query == "gethostbyname")
{
struct sockaddr_in sa;
if (Utility::u2ip(m_data, sa))
{
std::string ip;
Utility::l2ip(sa.sin_addr, ip);
Send("A: " + ip + "\n");
}
else
{
Send("Failed\n");
}
Send("\n");
}
else
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
if (m_query == "gethostbyname2")
{
struct sockaddr_in6 sa;
if (Utility::u2ip(m_data, sa))
{
std::string ip;
Utility::l2ip(sa.sin6_addr, ip);
Send("AAAA: " + ip + "\n");
}
else
{
Send("Failed\n");
}
Send("\n");
}
else
#endif
#endif
if (m_query == "gethostbyaddr")
{
if (Utility::isipv4( m_data ))
{
struct sockaddr_in sa;
if (!Utility::u2ip(m_data, sa, AI_NUMERICHOST))
{
Send("Failed: convert to sockaddr_in failed\n");
}
else
{
std::string name;
if (!Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), name))
{
Send("Failed: ipv4 reverse lookup of " + m_data + "\n");
}
else
{
Send("Name: " + name + "\n");
}
}
}
else
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
if (Utility::isipv6( m_data ))
{
struct sockaddr_in6 sa;
if (!Utility::u2ip(m_data, sa, AI_NUMERICHOST))
{
Send("Failed: convert to sockaddr_in6 failed\n");
}
else
{
std::string name;
if (!Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), name))
{
Send("Failed: ipv6 reverse lookup of " + m_data + "\n");
}
else
{
Send("Name: " + name + "\n");
}
}
}
else
#endif
#endif
{
Send("Failed: malformed address\n");
}
Send("\n");
}
else
{
std::string msg = "Unknown query type: " + m_query;
Handler().LogError(this, "OnDetached", 0, msg);
Send("Unknown\n\n");
}
SetCloseAndDelete();
}
void ResolvSocket::OnConnect()
{
if (m_resolv_host.size())
{
#ifdef ENABLE_IPV6
std::string msg = (m_resolve_ipv6 ? "gethostbyname2 " : "gethostbyname ") + m_resolv_host + "\n";
m_query = m_resolve_ipv6 ? "gethostbyname2" : "gethostbyname";
#else
std::string msg = "gethostbyname " + m_resolv_host + "\n";
m_query = "gethostbyname";
#endif
m_data = m_resolv_host;
Send( msg );
return;
}
#ifdef ENABLE_IPV6
if (m_resolve_ipv6)
{
std::string tmp;
Utility::l2ip(m_resolv_address6, tmp);
m_query = "gethostbyaddr";
m_data = tmp;
std::string msg = "gethostbyaddr " + tmp + "\n";
Send( msg );
}
#endif
std::string tmp;
Utility::l2ip(m_resolv_address, tmp);
m_query = "gethostbyaddr";
m_data = tmp;
std::string msg = "gethostbyaddr " + tmp + "\n";
Send( msg );
}
void ResolvSocket::OnDelete()
{
if (m_parent)
{
if (Handler().Resolving(m_parent) || Handler().Valid(m_parent_uid))
{
m_parent -> OnResolveFailed(m_resolv_id);
}
// update cache
if (!m_cached)
{
Lock lock(m_cache_mutex);
std::string value;
DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
m_cache[m_query][m_data] = value;
m_cache_to[m_query][m_data] = time(NULL);
}
m_parent = NULL;
}
}
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // ENABLE_RESOLVER
@@ -1,120 +0,0 @@
/** \file ResolvSocket.h
** \date 2005-03-24
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_ResolvSocket_H
#define _SOCKETS_ResolvSocket_H
#include "sockets-config.h"
#ifdef ENABLE_RESOLVER
#include "TcpSocket.h"
#include <map>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class Mutex;
/** Async DNS resolver socket.
\ingroup async */
class ResolvSocket : public TcpSocket
{
typedef std::map<std::string, /* type */
std::map<std::string, std::string> > cache_t; /* host, result */
typedef std::map<std::string, /* type */
std::map<std::string, time_t> > timeout_t; /* host, time */
public:
ResolvSocket(ISocketHandler&);
ResolvSocket(ISocketHandler&, Socket *parent, const std::string& host, port_t port, bool ipv6 = false);
ResolvSocket(ISocketHandler&, Socket *parent, ipaddr_t);
#ifdef ENABLE_IPV6
ResolvSocket(ISocketHandler&, Socket *parent, in6_addr&);
#endif
~ResolvSocket();
void OnAccept() {
m_bServer = true;
}
void OnLine(const std::string& line);
void OnDetached();
void OnDelete();
void SetId(int x) {
m_resolv_id = x;
}
int GetId() {
return m_resolv_id;
}
void OnConnect();
#ifdef ENABLE_IPV6
void SetResolveIpv6(bool x = true) {
m_resolve_ipv6 = x;
}
#endif
private:
ResolvSocket(const ResolvSocket& s) : TcpSocket(s) {} // copy constructor
ResolvSocket& operator=(const ResolvSocket& ) {
return *this; // assignment operator
}
std::string m_query;
std::string m_data;
bool m_bServer;
Socket *m_parent;
socketuid_t m_parent_uid;
int m_resolv_id;
std::string m_resolv_host;
port_t m_resolv_port;
ipaddr_t m_resolv_address;
#ifdef ENABLE_IPV6
bool m_resolve_ipv6;
in6_addr m_resolv_address6;
#endif
static cache_t m_cache;
static timeout_t m_cache_to;
static Mutex m_cache_mutex;
bool m_cached;
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // ENABLE_RESOLVER
#endif // _SOCKETS_ResolvSocket_H
@@ -1,181 +0,0 @@
/**
** \file SSLInitializer.cpp
** \date 2007-04-30
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef _WIN32
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#include <io.h>
#endif
#include "SSLInitializer.h"
#ifdef HAVE_OPENSSL
#include <map>
#include "Utility.h"
#include <openssl/rand.h>
#include "Lock.h"
#ifdef _DEBUG
#define DEB(x) x
#else
#define DEB(x)
#endif
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
std::map<int, IMutex *> *SSLInitializer::m_mmap = NULL;
Mutex *SSLInitializer::m_mmap_mutex = NULL;
SSLInitializer::SSLInitializer()
{
DEB( fprintf(stderr, "SSLInitializer()\n");)
bio_err = NULL;
m_rand_size = 1024;
/* An error write context */
bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
/* Global system initialization*/
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
CRYPTO_set_locking_callback( SSL_locking_function );
CRYPTO_set_id_callback( SSL_id_function );
std::string randfile = Utility::GetEnv("RANDFILE");
std::string home = Utility::GetEnv("HOME");
if (randfile.empty() && home.empty())
{
std::string homepath = Utility::GetEnv("HOMEPATH");
if (!homepath.empty())
{
Utility::SetEnv("HOME", homepath);
}
}
char path[512];
*path = 0;
RAND_file_name(path, 512);
if (*path)
{
m_rand_file = path;
m_rand_size = 1024;
RAND_write_file(path);
}
else
{
DEB( fprintf(stderr, "SSLInitializer: no random file generated\n");)
}
/* Load randomness */
if (!m_rand_file.size() || !RAND_load_file(m_rand_file.c_str(), m_rand_size))
{
DEB( fprintf(stderr, "SSLInitializer: PRNG not initialized\n");)
}
}
SSLInitializer::~SSLInitializer()
{
DEB( fprintf(stderr, "~SSLInitializer()\n");)
DeleteRandFile();
// %! delete mutexes
}
void SSLInitializer::DeleteRandFile()
{
if (m_rand_file.size())
{
#ifdef _WIN32
_unlink(m_rand_file.c_str());
#else
unlink(m_rand_file.c_str());
#endif
}
}
void SSLInitializer::SSL_locking_function(int mode, int n, const char *file, int line)
{
IMutex *mutex = NULL;
{
Lock lock(MMapMutex());
if (MMap().find(n) == MMap().end())
{
MMap()[n] = new Mutex;
}
mutex = MMap()[n];
}
if (mode & CRYPTO_LOCK)
{
mutex -> Lock();
}
else
{
mutex -> Unlock();
}
}
unsigned long SSLInitializer::SSL_id_function()
{
return Utility::ThreadID();
}
std::map<int, IMutex *>& SSLInitializer::MMap()
{
if (m_mmap == NULL)
m_mmap = new std::map<int, IMutex *>();
return *m_mmap;
}
Mutex& SSLInitializer::MMapMutex()
{
if (m_mmap_mutex == NULL)
m_mmap_mutex = new Mutex();
return *m_mmap_mutex;
}
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // HAVE_OPENSSL
@@ -1,97 +0,0 @@
/**
** \file SSLInitializer.h
** \date 2007-04-30
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __SOCKETS_SSLInitializer_H
#define __SOCKETS_SSLInitializer_H
#include "sockets-config.h"
#ifdef HAVE_OPENSSL
#ifdef _WIN32
#include <winsock2.h>
#endif
#include <openssl/ssl.h>
#include <string>
#include <map>
#include "Mutex.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class SSLInitializer
{
public:
/**
init openssl
bio_err
create random file
*/
SSLInitializer();
/**
remove random file
*/
~SSLInitializer();
void DeleteRandFile();
/** SSL; mutex locking function callback. */
static void SSL_locking_function(int mode, int n, const char *file, int line);
/** Return thread id. */
static unsigned long SSL_id_function();
BIO *bio_err;
private:
std::string m_rand_file;
long m_rand_size;
static std::map<int, IMutex *> *m_mmap;
static Mutex *m_mmap_mutex;
static std::map<int, IMutex *>& MMap();
static Mutex& MMapMutex();
};
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // HAVE_OPENSSL
#endif // __SOCKETS_SSLInitializer_H
@@ -1,506 +0,0 @@
/**
** \file SctpSocket.cpp
** \date 2006-09-04
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "SctpSocket.h"
#ifdef USE_SCTP
#include "Utility.h"
#include "ISocketHandler.h"
#include <errno.h>
#include "Ipv4Address.h"
#include "Ipv6Address.h"
#ifdef ENABLE_EXCEPTIONS
#include "Exception.h"
#endif
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
SctpSocket::SctpSocket(ISocketHandler& h,int type) : StreamSocket(h)
,m_type(type)
,m_buf(new char[SCTP_BUFSIZE_READ])
{
if (type != SOCK_STREAM && type != SOCK_SEQPACKET)
{
}
}
SctpSocket::~SctpSocket()
{
delete[] m_buf;
}
int SctpSocket::Bind(const std::string& a,port_t p)
{
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
if (IsIpv6())
{
Ipv6Address ad(a, p);
return Bind(ad);
}
#endif
#endif
Ipv4Address ad(a, p);
return Bind(ad);
}
int SctpSocket::Bind(SocketAddress& ad)
{
if (!ad.IsValid())
{
Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
return -1;
}
if (GetSocket() == INVALID_SOCKET)
{
Attach(CreateSocket(ad.GetFamily(), m_type, "sctp"));
}
if (GetSocket() != INVALID_SOCKET)
{
int n = bind(GetSocket(), ad, ad);
if (n == -1)
{
Handler().LogError(this, "SctpSocket", -1, "bind() failed", LOG_LEVEL_ERROR);
#ifdef ENABLE_EXCEPTIONS
throw Exception("bind() failed for SctpSocket, port: " + Utility::l2string(ad.GetPort()));
#endif
}
return n;
}
return -1;
}
int SctpSocket::AddAddress(const std::string& a,port_t p)
{
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
if (IsIpv6())
{
Ipv6Address ad(a, p);
return AddAddress(ad);
}
#endif
#endif
Ipv4Address ad(a, p);
return AddAddress(ad);
}
int SctpSocket::AddAddress(SocketAddress& ad)
{
if (!ad.IsValid())
{
Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
return -1;
}
if (GetSocket() == INVALID_SOCKET)
{
Handler().LogError(this, "SctpSocket", -1, "AddAddress called with invalid file descriptor", LOG_LEVEL_ERROR);
return -1;
}
int n = sctp_bindx(GetSocket(), ad, ad, SCTP_BINDX_ADD_ADDR);
if (n == -1)
{
Handler().LogError(this, "SctpSocket", -1, "sctp_bindx() failed", LOG_LEVEL_ERROR);
}
return n;
}
int SctpSocket::RemoveAddress(const std::string& a,port_t p)
{
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
if (IsIpv6())
{
Ipv6Address ad(a, p);
return RemoveAddress(ad);
}
#endif
#endif
Ipv4Address ad(a, p);
return RemoveAddress(ad);
}
int SctpSocket::RemoveAddress(SocketAddress& ad)
{
if (!ad.IsValid())
{
Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
return -1;
}
if (GetSocket() == INVALID_SOCKET)
{
Handler().LogError(this, "SctpSocket", -1, "RemoveAddress called with invalid file descriptor", LOG_LEVEL_ERROR);
return -1;
}
int n = sctp_bindx(GetSocket(), ad, ad, SCTP_BINDX_REM_ADDR);
if (n == -1)
{
Handler().LogError(this, "SctpSocket", -1, "sctp_bindx() failed", LOG_LEVEL_ERROR);
}
return n;
}
int SctpSocket::Open(const std::string& a,port_t p)
{
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
if (IsIpv6())
{
Ipv6Address ad(a, p);
return Open(ad);
}
#endif
#endif
Ipv4Address ad(a, p);
return Open(ad);
}
int SctpSocket::Open(SocketAddress& ad)
{
if (!ad.IsValid())
{
Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
return -1;
}
if (GetSocket() == INVALID_SOCKET)
{
Attach(CreateSocket(ad.GetFamily(), m_type, "sctp"));
}
if (GetSocket() != INVALID_SOCKET)
{
if (!SetNonblocking(true))
{
return -1;
}
int n = connect(GetSocket(), ad, ad);
if (n == -1)
{
// check error code that means a connect is in progress
#ifdef _WIN32
if (Errno == WSAEWOULDBLOCK)
#else
if (Errno == EINPROGRESS)
#endif
{
Handler().LogError(this, "connect: connection pending", Errno, StrError(Errno), LOG_LEVEL_INFO);
SetConnecting( true ); // this flag will control fd_set's
}
else
{
Handler().LogError(this, "SctpSocket", -1, "connect() failed", LOG_LEVEL_ERROR);
}
}
return n;
}
return -1;
}
#ifndef SOLARIS
int SctpSocket::AddConnection(const std::string& a,port_t p)
{
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
if (IsIpv6())
{
Ipv6Address ad(a, p);
return AddConnection(ad);
}
#endif
#endif
Ipv4Address ad(a, p);
return AddConnection(ad);
}
int SctpSocket::AddConnection(SocketAddress& ad)
{
if (!ad.IsValid())
{
Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
return -1;
}
if (GetSocket() == INVALID_SOCKET)
{
Handler().LogError(this, "SctpSocket", -1, "AddConnection called with invalid file descriptor", LOG_LEVEL_ERROR);
return -1;
}
int n = sctp_connectx(GetSocket(), ad, ad);
if (n == -1)
{
Handler().LogError(this, "SctpSocket", -1, "sctp_connectx() failed", LOG_LEVEL_ERROR);
}
else
{
SetConnecting();
}
return n;
}
#endif
int SctpSocket::getpaddrs(sctp_assoc_t id,std::list<std::string>& vec)
{
struct sockaddr *p = NULL;
int n = sctp_getpaddrs(GetSocket(), id, &p);
if (!n || n == -1)
{
Handler().LogError(this, "SctpSocket", -1, "sctp_getpaddrs failed", LOG_LEVEL_WARNING);
return n;
}
for (int i = 0; i < n; i++)
{
vec.push_back(Utility::Sa2String(&p[i]));
}
sctp_freepaddrs(p);
return n;
}
int SctpSocket::getladdrs(sctp_assoc_t id,std::list<std::string>& vec)
{
struct sockaddr *p = NULL;
int n = sctp_getladdrs(GetSocket(), id, &p);
if (!n || n == -1)
{
Handler().LogError(this, "SctpSocket", -1, "sctp_getladdrs failed", LOG_LEVEL_WARNING);
return n;
}
for (int i = 0; i < n; i++)
{
vec.push_back(Utility::Sa2String(&p[i]));
}
sctp_freeladdrs(p);
return n;
}
int SctpSocket::PeelOff(sctp_assoc_t id)
{
int n = sctp_peeloff(GetSocket(), id);
if (n == -1)
{
Handler().LogError(this, "SctpSocket", -1, "PeelOff failed", LOG_LEVEL_WARNING);
return -1;
}
Socket *p = Create();
p -> Attach(n);
p -> SetDeleteByHandler();
Handler().Add(p);
return n;
}
void SctpSocket::OnRead()
{
/*
int sctp_recvmsg(int sd, void * msg, size_t * len,
struct sockaddr * from, socklen_t * fromlen,
struct sctp_sndrcvinfo * sinfo, int * msg_flags);
DESCRIPTION
sctp_recvmsg is a wrapper library function that can be used to receive a message from a socket while using the advanced
features of SCTP. sd is the socket descriptor on which the message pointed to by msg of length len is received.
If from is not NULL, the source address of the message is filled in. The argument fromlen is a value-result parameter.
initialized to the size of the buffer associated with from , and modified on return to indicate the actual size of the
address stored.
sinfo is a pointer to a sctp_sndrcvinfo structure to be filled upon receipt of the message. msg_flags is a pointer to a
integer that is filled with any message flags like MSG_NOTIFICATION or MSG_EOR.
*/
struct sockaddr sa;
socklen_t sa_len = 0;
struct sctp_sndrcvinfo sinfo;
int flags = 0;
int n = sctp_recvmsg(GetSocket(), m_buf, SCTP_BUFSIZE_READ, &sa, &sa_len, &sinfo, &flags);
if (n == -1)
{
Handler().LogError(this, "SctpSocket", Errno, StrError(Errno), LOG_LEVEL_FATAL);
SetCloseAndDelete();
}
else
{
OnReceiveMessage(m_buf, n, &sa, sa_len, &sinfo, flags);
}
}
void SctpSocket::OnReceiveMessage(const char *buf,size_t sz,struct sockaddr *sa,socklen_t sa_len,struct sctp_sndrcvinfo *sinfo,int msg_flags)
{
}
void SctpSocket::OnWrite()
{
if (Connecting())
{
int err = SoError();
// don't reset connecting flag on error here, we want the OnConnectFailed timeout later on
/// \todo add to read fd_set here
if (!err) // ok
{
Set(!IsDisableRead(), false);
SetConnecting(false);
SetCallOnConnect();
return;
}
Handler().LogError(this, "sctp: connect failed", err, StrError(err), LOG_LEVEL_FATAL);
Set(false, false); // no more monitoring because connection failed
// failed
#ifdef ENABLE_SOCKS4
if (Socks4())
{
OnSocks4ConnectFailed();
return;
}
#endif
if (GetConnectionRetry() == -1 ||
(GetConnectionRetry() && GetConnectionRetries() < GetConnectionRetry()) )
{
// even though the connection failed at once, only retry after
// the connection timeout.
// should we even try to connect again, when CheckConnect returns
// false it's because of a connection error - not a timeout...
return;
}
SetConnecting(false);
SetCloseAndDelete( true );
/// \todo state reason why connect failed
OnConnectFailed();
return;
}
}
void SctpSocket::OnConnectTimeout()
{
Handler().LogError(this, "connect", -1, "connect timeout", LOG_LEVEL_FATAL);
#ifdef ENABLE_SOCKS4
if (Socks4())
{
OnSocks4ConnectFailed();
// retry direct connection
}
else
#endif
if (GetConnectionRetry() == -1 ||
(GetConnectionRetry() && GetConnectionRetries() < GetConnectionRetry()) )
{
IncreaseConnectionRetries();
// ask socket via OnConnectRetry callback if we should continue trying
if (OnConnectRetry())
{
SetRetryClientConnect();
}
else
{
SetCloseAndDelete( true );
/// \todo state reason why connect failed
OnConnectFailed();
}
}
else
{
SetCloseAndDelete(true);
/// \todo state reason why connect failed
OnConnectFailed();
}
//
SetConnecting(false);
}
#ifdef _WIN32
void SctpSocket::OnException()
{
if (Connecting())
{
#ifdef ENABLE_SOCKS4
if (Socks4())
OnSocks4ConnectFailed();
else
#endif
if (GetConnectionRetry() == -1 ||
(GetConnectionRetry() &&
GetConnectionRetries() < GetConnectionRetry() ))
{
// even though the connection failed at once, only retry after
// the connection timeout
// should we even try to connect again, when CheckConnect returns
// false it's because of a connection error - not a timeout...
}
else
{
SetConnecting(false); // tnx snibbe
SetCloseAndDelete();
OnConnectFailed();
}
return;
}
// %! exception doesn't always mean something bad happened, this code should be reworked
// errno valid here?
int err = SoError();
Handler().LogError(this, "exception on select", err, StrError(err), LOG_LEVEL_FATAL);
SetCloseAndDelete();
}
#endif // _WIN32
int SctpSocket::Protocol()
{
return IPPROTO_SCTP;
}
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE
#endif
#endif // USE_SCTP
@@ -1,122 +0,0 @@
/**
** \file SctpSocket.h
** \date 2006-09-04
** \author grymse@alhem.net
**/
/*
Copyright (C) 2008-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_SctpSocket_H
#define _SOCKETS_SctpSocket_H
#include "sockets-config.h"
#include "StreamSocket.h"
#ifdef USE_SCTP
#include <netinet/sctp.h>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
#define SCTP_BUFSIZE_READ 16400
class SocketAddress;
class SctpSocket : public StreamSocket
{
public:
/** SctpSocket constructor.
\param h Owner
\param type SCTP_STREAM or SCTP_SEQPACKET */
SctpSocket(ISocketHandler& h,int type);
~SctpSocket();
/** bind() */
int Bind(const std::string&,port_t);
int Bind(SocketAddress&);
/** sctp_bindx() */
int AddAddress(const std::string&,port_t);
int AddAddress(SocketAddress&);
/** sctp_bindx() */
int RemoveAddress(const std::string&,port_t);
int RemoveAddress(SocketAddress&);
/** connect() */
int Open(const std::string&,port_t);
int Open(SocketAddress&);
/** Connect timeout callback. */
void OnConnectTimeout();
#ifdef _WIN32
/** Connection failed reported as exception on win32 */
void OnException();
#endif
#ifndef SOLARIS
/** sctp_connectx() */
int AddConnection(const std::string&,port_t);
int AddConnection(SocketAddress&);
#endif
/** Get peer addresses of an association. */
int getpaddrs(sctp_assoc_t id,std::list<std::string>&);
/** Get all bound addresses of an association. */
int getladdrs(sctp_assoc_t id,std::list<std::string>&);
/** sctp_peeloff */
int PeelOff(sctp_assoc_t id);
/** recvmsg callback */
virtual void OnReceiveMessage(const char *buf,size_t sz,struct sockaddr *sa,socklen_t sa_len,struct sctp_sndrcvinfo *sinfo,int msg_flags) = 0;
void OnOptions(int,int,int,SOCKET) {}
virtual int Protocol();
protected:
SctpSocket(const SctpSocket& s) : StreamSocket(s) {}
void OnRead();
void OnWrite();
private:
SctpSocket& operator=(const SctpSocket& s) {
return *this;
}
int m_type; ///< SCTP_STREAM or SCTP_SEQPACKET
char *m_buf; ///< Temporary receive buffer
};
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE
#endif
#endif // USE_SCTP
#endif // _SOCKETS_SctpSocket_H
@@ -1,123 +0,0 @@
/**
** \file Semaphore.cpp
** \date 2007-04-13
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "Semaphore.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
// ---------------------------------------------------------------
#ifdef _WIN32
Semaphore::Semaphore(value_t start_val)
{
m_handle = ::CreateSemaphore((LPSECURITY_ATTRIBUTES)NULL, start_val, 1, (LPCTSTR)NULL);
}
Semaphore::~Semaphore()
{
::CloseHandle(m_handle);
}
int Semaphore::Post()
{
return (::ReleaseSemaphore(m_handle, 1, (LPLONG)NULL) != 0) ? 0 : -1;
}
int Semaphore::Wait()
{
return (WaitForSingleObject(m_handle, INFINITE) == WAIT_OBJECT_0) ? 0 : -1;
}
int Semaphore::TryWait()
{
return -1; // %! not implemented
}
int Semaphore::GetValue(int& i)
{
return 0; // %! not implemented
}
// ---------------------------------------------------------------
#else
Semaphore::Semaphore(value_t start_val)
{
sem_init(&m_sem, 0, start_val);
}
Semaphore::~Semaphore()
{
sem_destroy(&m_sem);
}
int Semaphore::Post()
{
return sem_post(&m_sem);
}
int Semaphore::Wait()
{
return sem_wait(&m_sem);
}
int Semaphore::TryWait()
{
return sem_trywait(&m_sem);
}
int Semaphore::GetValue(int& i)
{
return sem_getvalue(&m_sem, &i);
}
#endif
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
@@ -1,100 +0,0 @@
/**
** \file Semaphore.h
** \date 2007-04-13
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_Semaphore_H
#define _SOCKETS_Semaphore_H
#include "sockets-config.h"
#ifdef _WIN32
#include "socket_include.h"
#include <windows.h>
#else
#include <pthread.h>
#ifdef MACOSX
#include <sys/semaphore.h>
#else
#include <semaphore.h>
#endif
#endif
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
#ifdef _WIN32
typedef LONG value_t;
#else
typedef unsigned int value_t;
#endif
/** pthread semaphore wrapper.
\ingroup threading */
class Semaphore
{
public:
Semaphore(value_t start_val = 0);
~Semaphore();
/** \return 0 if successful */
int Post();
/** Wait for Post
\return 0 if successful */
int Wait();
/** Not implemented for win32 */
int TryWait();
/** Not implemented for win32 */
int GetValue(int&);
private:
Semaphore(const Semaphore& ) {} // copy constructor
Semaphore& operator=(const Semaphore& ) {
return *this; // assignment operator
}
#ifdef _WIN32
HANDLE m_handle;
#else
sem_t m_sem;
#endif
};
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // _SOCKETS_Semaphore_H
@@ -1,244 +0,0 @@
/**
** \file SmtpdSocket.cpp
** \date 2007-05-10
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "SmtpdSocket.h"
#include "Parse.h"
#include "Utility.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
SmtpdSocket::SmtpdSocket(ISocketHandler& h)
:TcpSocket(h)
,m_hello(false)
,m_data(false)
,m_header(false)
{
SetLineProtocol();
}
void SmtpdSocket::OnAccept()
{
Send("220 ESMTP; \r\n");
}
void SmtpdSocket::OnLine(const std::string& line)
{
if (m_data)
{
if (m_header)
{
if (!line.size())
{
if (m_header_line.size())
{
Parse pa(m_header_line, ":");
std::string key = pa.getword();
OnHeader(key, pa.getrest());
}
m_header = false;
OnHeaderComplete();
}
else
if (line[0] == ' ' || line[0] == '\t')
{
m_header_line += line;
}
else
{
if (m_header_line.size())
{
Parse pa(m_header_line, ":");
std::string key = pa.getword();
OnHeader(key, pa.getrest());
}
m_header_line = line;
}
}
else
if (line == ".")
{
m_data = false;
if (OnDataComplete())
Send("250 OK\r\n");
else
Send("550 Failed\r\n");
}
else
if (line.size() && line[0] == '.')
{
OnData(line.substr(1));
}
else
{
OnData(line);
}
return;
}
Parse pa(line);
std::string cmd = Utility::ToUpper(pa.getword());
if (cmd == "EHLO")
{
if (!OnHello(pa.getrest()))
{
Send("550 Failed\r\n");
}
else
{
m_hello = true;
Send("250 mail.alhem.net\r\n");
}
}
else
if (cmd == "HELO")
{
if (!OnHello(pa.getrest()))
{
Send("550 Failed\r\n");
}
else
{
m_hello = true;
Send("250 mail.alhem.net\r\n");
}
}
else
if (!m_hello)
{
OnAbort(SMTP_NO_HELLO);
SetCloseAndDelete();
}
else
if (cmd == "MAIL") // mail from:
{
Parse pa(line, ":");
pa.getword(); // 'mail'
pa.getword(); // 'from'
std::string email = Utility::ToLower(pa.getrest());
EmailAddress addr( email );
if (addr.GetName().size() > 64)
{
OnAbort(SMTP_NAME_TOO_LONG);
Send("500 Name too long.\r\n");
return;
}
if (addr.GetDomain().size() > 64)
{
OnAbort(SMTP_DOMAIN_TOO_LONG);
Send("500 Domain too long.\r\n");
return;
}
if (!OnMailFrom( addr ))
{
Send("550 Failed\r\n");
}
else
{
Send("250 OK\r\n");
}
}
else
if (cmd == "RCPT") // rcpt to:
{
Parse pa(line, ":");
pa.getword(); // 'rcpt'
pa.getword(); // 'to'
std::string email = Utility::ToLower(pa.getrest());
// %! reject based on user / domain?
EmailAddress addr( email );
if (addr.GetName().size() > 64)
{
OnAbort(SMTP_NAME_TOO_LONG);
Send("500 Name too long.\r\n");
return;
}
if (addr.GetDomain().size() > 64)
{
OnAbort(SMTP_DOMAIN_TOO_LONG);
Send("500 Domain too long.\r\n");
return;
}
if (!OnRcptTo( addr ))
{
Send("553 Failed\r\n");
}
else
{
Send("250 OK\r\n");
}
}
else
if (cmd == "DATA")
{
Send("354 Enter mail, end with \".\" on a line by itself\r\n");
m_data = true;
m_header = false;
}
else
if (cmd == "RSET")
{
m_data = false;
m_header = false;
OnRset();
Send("250 OK\r\n"); // %! ???
}
else
if (cmd == "QUIT")
{
OnAbort(SMTP_QUIT);
Send("221 Bye Bye\r\n");
SetCloseAndDelete();
}
else
if (cmd == "NOOP")
{
Send("250 OK\r\n");
}
else
{
OnNotSupported(cmd, pa.getrest());
}
}
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
@@ -1,171 +0,0 @@
/**
** \file SmtpdSocket.h
** \date 2007-05-10
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_SmtpdSocket_H
#define _SOCKETS_SmtpdSocket_H
#include "sockets-config.h"
#include <string>
#include "TcpSocket.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
/** Smtp server base class. */
class SmtpdSocket : public TcpSocket
{
protected:
typedef enum {
SMTP_NO_HELLO,
SMTP_NAME_TOO_LONG,
SMTP_DOMAIN_TOO_LONG,
SMTP_QUIT
} reason_t;
public:
class EmailAddress
{
public:
EmailAddress(const std::string& str_in) {
std::string str = str_in;
size_t i = str.find("<");
if (i != std::string::npos)
str = str.substr(i + 1);
i = str.find("@");
if (i != std::string::npos) {
m_name = str.substr(0, i);
str = str.substr(i + 1);
i = str.find(">");
if (i != std::string::npos)
str = str.substr(0, i);
m_domain = str;
}
while (m_name.size() && m_name[m_name.size() - 1] == ' ')
m_name.resize(m_name.size() - 1);
while (m_domain.size() && m_domain[m_domain.size() - 1] == ' ')
m_domain.resize(m_domain.size() - 1);
while (m_name.size() && m_name[0] == ' ')
m_name = m_name.substr(1);
while (m_domain.size() && m_domain[0] == ' ')
m_domain = m_domain.substr(1);
m_top = m_domain;
{
for (size_t i = 0; i < m_domain.size(); i++) {
if (m_domain[i] == '.') {
m_sub = m_top;
m_top = m_domain.substr(i + 1);
}
}
}
}
const std::string& GetName() const {
return m_name;
}
const std::string& GetDomain() const {
return m_domain;
}
const std::string& GetTopDomain() const {
return m_top;
}
const std::string& GetSubDomain() const {
return m_sub;
}
std::string ToString() const {
return m_name + "@" + m_domain;
}
private:
std::string m_name;
std::string m_domain;
std::string m_top;
std::string m_sub;
};
public:
SmtpdSocket(ISocketHandler&);
void OnAccept();
void OnLine(const std::string&);
/** \return 'false' to abort */
virtual bool OnHello(const std::string& domain) = 0;
/** \return 'false' to abort */
virtual bool OnMailFrom(const EmailAddress& addr) = 0;
/** \return 'false' to abort */
virtual bool OnRcptTo(const EmailAddress& addr) = 0;
virtual void OnHeader(const std::string& key, const std::string& value) = 0;
virtual void OnHeaderComplete() = 0;
virtual void OnData(const std::string& line) = 0;
/** \return 'false' if message write failed (message will probably be resent) */
virtual bool OnDataComplete() = 0;
virtual void OnRset() = 0;
virtual void OnAbort(reason_t) = 0;
virtual void OnNotSupported(const std::string& cmd, const std::string& arg) = 0;
private:
bool m_hello; // we need HELO or EHLO first of all
bool m_data;
bool m_header;
std::string m_header_line;
};
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // _SOCKETS_SmtpdSocket_H
File diff suppressed because it is too large Load Diff
@@ -1,735 +0,0 @@
/** \file Socket.h
** \date 2004-02-13
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_Socket_H
#define _SOCKETS_Socket_H
#include "sockets-config.h"
#include <string>
#include <vector>
#include <list>
#ifdef HAVE_OPENSSL
#include <openssl/ssl.h>
#endif
#include "socket_include.h"
#include <time.h>
#include "SocketAddress.h"
#include "Thread.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class ISocketHandler;
class SocketAddress;
class IFile;
class SocketThread;
/** \defgroup basic Basic sockets */
/** Socket base class.
\ingroup basic */
class Socket
{
/** Socket mode flags. */
/*
enum {
// Socket
SOCK_DEL = 0x01, ///< Delete by handler flag
SOCK_CLOSE = 0x02, ///< Close and delete flag
SOCK_DISABLE_READ = 0x04, ///< Disable checking for read events
SOCK_CONNECTED = 0x08, ///< Socket is connected (tcp/udp)
SOCK_ERASED_BY_HANDLER = 0x10, ///< Set by handler before delete
// HAVE_OPENSSL
SOCK_ENABLE_SSL = 0x20, ///< Enable SSL for this TcpSocket
SOCK_SSL = 0x40, ///< ssl negotiation mode (TcpSocket)
SOCK_SSL_SERVER = 0x80, ///< True if this is an incoming ssl TcpSocket connection
// ENABLE_IPV6
SOCK_IPV6 = 0x0100, ///< This is an ipv6 socket if this one is true
// ENABLE_POOL
SOCK_CLIENT = 0x0200, ///< only client connections are pooled
SOCK_RETAIN = 0x0400, ///< keep connection on close
SOCK_LOST = 0x0800, ///< connection lost
// ENABLE_SOCKS4
SOCK_SOCKS4 = 0x1000, ///< socks4 negotiation mode (TcpSocket)
// ENABLE_DETACH
SOCK_DETACH = 0x2000, ///< Socket ordered to detach flag
SOCK_DETACHED = 0x4000, ///< Socket has been detached
// StreamSocket
STREAMSOCK_CONNECTING = 0x8000, ///< Flag indicating connection in progress
STREAMSOCK_FLUSH_BEFORE_CLOSE = 0x010000L, ///< Send all data before closing (default true)
STREAMSOCK_CALL_ON_CONNECT = 0x020000L, ///< OnConnect will be called next ISocketHandler cycle if true
STREAMSOCK_RETRY_CONNECT = 0x040000L, ///< Try another connection attempt next ISocketHandler cycle
STREAMSOCK_LINE_PROTOCOL = 0x080000L, ///< Line protocol mode flag
};
*/
public:
/** "Default" constructor */
Socket(ISocketHandler&);
virtual ~Socket();
/** Socket class instantiation method. Used when a "non-standard" constructor
* needs to be used for the socket class. Note: the socket class still needs
* the "default" constructor with one ISocketHandler& as input parameter.
*/
virtual Socket *Create() {
return NULL;
}
/** Returns reference to sockethandler that owns the socket.
If the socket is detached, this is a reference to the slave sockethandler.
*/
ISocketHandler& Handler() const;
/** Returns reference to sockethandler that owns the socket.
This one always returns the reference to the original sockethandler,
even if the socket is detached.
*/
ISocketHandler& MasterHandler() const;
/** Called by ListenSocket after accept but before socket is added to handler.
* CTcpSocket uses this to create its ICrypt member variable.
* The ICrypt member variable is created by a virtual method, therefore
* it can't be called directly from the CTcpSocket constructor.
* Also used to determine if incoming HTTP connection is normal (port 80)
* or ssl (port 443).
*/
virtual void Init();
/** Create a socket file descriptor.
\param af Address family AF_INET / AF_INET6 / ...
\param type SOCK_STREAM / SOCK_DGRAM / ...
\param protocol "tcp" / "udp" / ... */
SOCKET CreateSocket(int af,int type,const std::string& protocol = "");
/** Assign this socket a file descriptor created
by a call to socket() or otherwise. */
void Attach(SOCKET s);
/** Return file descriptor assigned to this socket. */
SOCKET GetSocket();
/** Close connection immediately - internal use.
\sa SetCloseAndDelete */
virtual int Close();
/** Returns true when socket file descriptor is valid
and socket is not about to be closed. */
virtual bool Ready();
/** Returns pointer to ListenSocket that created this instance
* on an incoming connection. */
Socket *GetParent();
/** Used by ListenSocket to set parent pointer of newly created
* socket instance. */
void SetParent(Socket *);
/** Get listening port from ListenSocket<>. */
virtual port_t GetPort();
/** Set socket non-block operation. */
bool SetNonblocking(bool);
/** Set socket non-block operation. */
bool SetNonblocking(bool, SOCKET);
/** Total lifetime of instance. */
time_t Uptime();
/** Set address/port of last connect() call. */
void SetClientRemoteAddress(SocketAddress&);
/** Get address/port of last connect() call. */
std::auto_ptr<SocketAddress> GetClientRemoteAddress();
/** Common interface for SendBuf used by Tcp and Udp sockets. */
virtual void SendBuf(const char *,size_t,int = 0);
/** Common interface for Send used by Tcp and Udp sockets. */
virtual void Send(const std::string&,int = 0);
/** Outgoing traffic counter. */
virtual uint64_t GetBytesSent(bool clear = false);
/** Incoming traffic counter. */
virtual uint64_t GetBytesReceived(bool clear = false);
// LIST_TIMEOUT
/** Enable timeout control. 0=disable timeout check. */
void SetTimeout(time_t secs);
bool CheckTimeout();
/** Check timeout. \return true if time limit reached */
bool Timeout(time_t tnow);
/** Used by ListenSocket. ipv4 and ipv6 */
void SetRemoteAddress(SocketAddress&);
/** \name Event callbacks */
//@{
/** Called when there is something to be read from the file descriptor. */
virtual void OnRead();
/** Called when there is room for another write on the file descriptor. */
virtual void OnWrite();
/** Called on socket exception. */
virtual void OnException();
/** Called before a socket class is deleted by the ISocketHandler. */
virtual void OnDelete();
/** Called when a connection has completed. */
virtual void OnConnect();
/** Called when an incoming connection has been completed. */
virtual void OnAccept();
/** Called when a complete line has been read and the socket is in
* line protocol mode. */
virtual void OnLine(const std::string& );
/** Called on connect timeout (5s). */
virtual void OnConnectFailed();
/** Called when a client socket is created, to set socket options.
\param family AF_INET, AF_INET6, etc
\param type SOCK_STREAM, SOCK_DGRAM, etc
\param protocol Protocol number (tcp, udp, sctp, etc)
\param s Socket file descriptor
*/
virtual void OnOptions(int family,int type,int protocol,SOCKET s) = 0;
/** Connection retry callback - return false to abort connection attempts */
virtual bool OnConnectRetry();
#ifdef ENABLE_RECONNECT
/** a reconnect has been made */
virtual void OnReconnect();
#endif
/** TcpSocket: When a disconnect has been detected (recv/SSL_read returns 0 bytes). */
virtual void OnDisconnect();
/** TcpSocket: When a disconnect has been detected (recv/SSL_read returns 0 bytes).
\param info bit 0 read(0)/write(1)
bit 1 normal(read or write returned 0)/error(r/w returned -1)
bit 2 ssl
\param code error code from read/write call (errno / ssl error)
*/
virtual void OnDisconnect(short info, int code);
/** Timeout callback. */
virtual void OnTimeout();
/** Connection timeout. */
virtual void OnConnectTimeout();
//@}
/** \name Socket mode flags, set/reset */
//@{
/** Set delete by handler true when you want the sockethandler to
delete the socket instance after use. */
void SetDeleteByHandler(bool = true);
/** Check delete by handler flag.
\return true if this instance should be deleted by the sockethandler */
bool DeleteByHandler();
// LIST_CLOSE - conditional event queue
/** Set close and delete to terminate the connection. */
void SetCloseAndDelete(bool = true);
/** Check close and delete flag.
\return true if this socket should be closed and the instance removed */
bool CloseAndDelete();
/** Return number of seconds since socket was ordered to close. \sa SetCloseAndDelete */
time_t TimeSinceClose();
/** Ignore read events for an output only socket. */
void DisableRead(bool x = true);
/** Check ignore read events flag.
\return true if read events should be ignored */
bool IsDisableRead();
/** Set connected status. */
void SetConnected(bool = true);
/** Check connected status.
\return true if connected */
bool IsConnected();
/** Connection lost - error while reading/writing from a socket - TcpSocket only. */
void SetLost();
/** Check connection lost status flag, used by TcpSocket only.
\return true if there was an error while r/w causing the socket to close */
bool Lost();
/** Set flag indicating the socket is being actively deleted by the sockethandler. */
void SetErasedByHandler(bool x = true);
/** Get value of flag indicating socket is deleted by sockethandler. */
bool ErasedByHandler();
//@}
/** \name Information about remote connection */
//@{
/** Returns address of remote end. */
std::auto_ptr<SocketAddress> GetRemoteSocketAddress();
/** Returns address of remote end: ipv4. */
ipaddr_t GetRemoteIP4();
//#ifdef ENABLE_IPV6
/** Returns address of remote end: ipv6. */
//#ifdef IPPROTO_IPV6
struct in6_addr GetRemoteIP6();
//#endif
//#endif
/** Returns remote port number: ipv4 and ipv6. */
port_t GetRemotePort();
/** Returns remote ip as string? ipv4 and ipv6. */
std::string GetRemoteAddress();
/** ipv4 and ipv6(not implemented) */
std::string GetRemoteHostname();
//@}
/** Returns local port number for bound socket file descriptor. */
port_t GetSockPort();
/** Returns local ipv4 address for bound socket file descriptor. */
ipaddr_t GetSockIP4();
/** Returns local ipv4 address as text for bound socket file descriptor. */
std::string GetSockAddress();
//#ifdef ENABLE_IPV6
//#ifdef IPPROTO_IPV6
/** Returns local ipv6 address for bound socket file descriptor. */
struct in6_addr GetSockIP6();
/** Returns local ipv6 address as text for bound socket file descriptor. */
std::string GetSockAddress6();
//#endif
//#endif
socketuid_t UniqueIdentifier() {
return m_uid;
}
// --------------------------------------------------------------------------
/** @name IP options
When an ip or socket option is available on all of the operating systems
I'm testing on (linux 2.4.x, _win32, macosx, solaris9 intel) they are not
checked with an #ifdef below.
This might cause a compile error on other operating systems. */
// --------------------------------------------------------------------------
// IP options
//@{
bool SetIpOptions(const void *p, socklen_t len);
bool SetIpTOS(unsigned char tos);
unsigned char IpTOS();
bool SetIpTTL(int ttl);
int IpTTL();
bool SetIpHdrincl(bool x = true);
bool SetIpMulticastTTL(int);
int IpMulticastTTL();
bool SetMulticastLoop(bool x = true);
bool IpAddMembership(struct ip_mreq&);
bool IpDropMembership(struct ip_mreq&);
#ifdef IP_PKTINFO
bool SetIpPktinfo(bool x = true);
#endif
#ifdef IP_RECVTOS
bool SetIpRecvTOS(bool x = true);
#endif
#ifdef IP_RECVTTL
bool SetIpRecvTTL(bool x = true);
#endif
#ifdef IP_RECVOPTS
bool SetIpRecvopts(bool x = true);
#endif
#ifdef IP_RETOPTS
bool SetIpRetopts(bool x = true);
#endif
#ifdef IP_RECVERR
bool SetIpRecverr(bool x = true);
#endif
#ifdef IP_MTU_DISCOVER
bool SetIpMtudiscover(bool x = true);
#endif
#ifdef IP_MTU
int IpMtu();
#endif
#ifdef IP_ROUTER_ALERT
bool SetIpRouterAlert(bool x = true);
#endif
#ifdef LINUX
bool IpAddMembership(struct ip_mreqn&);
#endif
#ifdef LINUX
bool IpDropMembership(struct ip_mreqn&);
#endif
//@}
// SOCKET options
/** @name Socket Options */
//@{
bool SoAcceptconn();
bool SetSoBroadcast(bool x = true);
bool SetSoDebug(bool x = true);
int SoError();
bool SetSoDontroute(bool x = true);
bool SetSoLinger(int onoff, int linger);
bool SetSoOobinline(bool x = true);
bool SetSoRcvlowat(int);
bool SetSoSndlowat(int);
bool SetSoRcvtimeo(struct timeval&);
bool SetSoSndtimeo(struct timeval&);
bool SetSoRcvbuf(int);
int SoRcvbuf();
bool SetSoSndbuf(int);
int SoSndbuf();
int SoType();
bool SetSoReuseaddr(bool x = true);
bool SetSoKeepalive(bool x = true);
#ifdef SO_BSDCOMPAT
bool SetSoBsdcompat(bool x = true);
#endif
#ifdef SO_BINDTODEVICE
bool SetSoBindtodevice(const std::string& intf);
#endif
#ifdef SO_PASSCRED
bool SetSoPasscred(bool x = true);
#endif
#ifdef SO_PEERCRED
bool SoPeercred(struct ucred& );
#endif
#ifdef SO_PRIORITY
bool SetSoPriority(int);
#endif
#ifdef SO_RCVBUFFORCE
bool SetSoRcvbufforce(int);
#endif
#ifdef SO_SNDBUFFORCE
bool SetSoSndbufforce(int);
#endif
#ifdef SO_TIMESTAMP
bool SetSoTimestamp(bool x = true);
#endif
#ifdef SO_NOSIGPIPE
bool SetSoNosigpipe(bool x = true);
#endif
//@}
// TCP options in TcpSocket.h/TcpSocket.cpp
// LIST_CALLONCONNECT
/** Instruct socket to call OnConnect callback next sockethandler cycle. */
void SetCallOnConnect(bool x = true);
/** Check call on connect flag.
\return true if OnConnect() should be called a.s.a.p */
bool CallOnConnect();
// LIST_RETRY
/** Set flag to initiate a connection attempt after a connection timeout. */
void SetRetryClientConnect(bool x = true);
/** Check if a connection attempt should be made.
\return true when another attempt should be made */
bool RetryClientConnect();
#ifdef HAVE_OPENSSL
/** @name SSL Support */
//@{
/** SSL client/server support - internal use. \sa TcpSocket */
virtual void OnSSLConnect();
/** SSL client/server support - internal use. \sa TcpSocket */
virtual void OnSSLAccept();
/** SSL negotiation failed for client connect. */
virtual void OnSSLConnectFailed();
/** SSL negotiation failed for server accept. */
virtual void OnSSLAcceptFailed();
/** new SSL support */
virtual bool SSLNegotiate();
/** Check if SSL is Enabled for this TcpSocket.
\return true if this is a TcpSocket with SSL enabled */
bool IsSSL();
/** Enable SSL operation for a TcpSocket. */
void EnableSSL(bool x = true);
/** Still negotiating ssl connection.
\return true if ssl negotiating is still in progress */
bool IsSSLNegotiate();
/** Set flag indicating ssl handshaking still in progress. */
void SetSSLNegotiate(bool x = true);
/** OnAccept called with SSL Enabled.
\return true if this is a TcpSocket with an incoming SSL connection */
bool IsSSLServer();
/** Set flag indicating that this is a TcpSocket with incoming SSL connection. */
void SetSSLServer(bool x = true);
/** SSL; Get pointer to ssl context structure. */
virtual SSL_CTX *GetSslContext() {
return NULL;
}
/** SSL; Get pointer to ssl structure. */
virtual SSL *GetSsl() {
return NULL;
}
//@}
#endif // HAVE_OPENSSL
//#ifdef ENABLE_IPV6
/** Enable ipv6 for this socket. */
void SetIpv6(bool x = true);
/** Check ipv6 socket.
\return true if this is an ipv6 socket */
bool IsIpv6();
//#endif
#ifdef ENABLE_POOL
/** @name Connection Pool */
//@{
/** Client = connecting TcpSocket. */
void SetIsClient();
/** Socket type from socket() call. */
void SetSocketType(int x);
/** Socket type from socket() call. */
int GetSocketType();
/** Protocol type from socket() call. */
void SetSocketProtocol(const std::string& x);
/** Protocol type from socket() call. */
const std::string& GetSocketProtocol();
/** Instruct a client socket to stay open in the connection pool after use.
If you have connected to a server using tcp, you can call SetRetain
to leave the connection open after your socket instance has been deleted.
The next connection you make to the same server will reuse the already
opened connection, if it is still available.
*/
void SetRetain();
/** Check retain flag.
\return true if the socket should be moved to connection pool after use */
bool Retain();
/** Copy connection parameters from sock. */
void CopyConnection(Socket *sock);
//@}
#endif // ENABLE_POOL
#ifdef ENABLE_SOCKS4
/** \name Socks4 support */
//@{
/** Socks4 client support internal use. \sa TcpSocket */
virtual void OnSocks4Connect();
/** Socks4 client support internal use. \sa TcpSocket */
virtual void OnSocks4ConnectFailed();
/** Socks4 client support internal use. \sa TcpSocket */
virtual bool OnSocks4Read();
/** Called when the last write caused the tcp output buffer to
* become empty. */
/** socket still in socks4 negotiation mode */
bool Socks4();
/** Set flag indicating Socks4 handshaking in progress */
void SetSocks4(bool x = true);
/** Set socks4 server host address to use */
void SetSocks4Host(ipaddr_t a);
/** Set socks4 server hostname to use. */
void SetSocks4Host(const std::string& );
/** Socks4 server port to use. */
void SetSocks4Port(port_t p);
/** Provide a socks4 userid if required by the socks4 server. */
void SetSocks4Userid(const std::string& x);
/** Get the ip address of socks4 server to use.
\return socks4 server host address */
ipaddr_t GetSocks4Host();
/** Get the socks4 server port to use.
\return socks4 server port */
port_t GetSocks4Port();
/** Get socks4 userid.
\return Socks4 userid */
const std::string& GetSocks4Userid();
//@}
#endif // ENABLE_SOCKS4
#ifdef ENABLE_RESOLVER
/** \name Asynchronous Resolver */
//@{
/** Request an asynchronous dns resolution.
\param host hostname to be resolved
\param port port number passed along for the ride
\return Resolve ID */
int Resolve(const std::string& host,port_t port = 0);
//#ifdef ENABLE_IPV6
int Resolve6(const std::string& host, port_t port = 0);
//#endif
/** Callback returning a resolved address.
\param id Resolve ID from Resolve call
\param a resolved ip address
\param port port number passed to Resolve */
virtual void OnResolved(int id,ipaddr_t a,port_t port);
//#ifdef ENABLE_IPV6
virtual void OnResolved(int id,in6_addr& a,port_t port);
//#endif
/** Request asynchronous reverse dns lookup.
\param a in_addr to be translated */
int Resolve(ipaddr_t a);
//#ifdef ENABLE_IPV6
int Resolve(in6_addr& a);
//#endif
/** Callback returning reverse resolve results.
\param id Resolve ID
\param name Resolved hostname */
virtual void OnReverseResolved(int id,const std::string& name);
/** Callback indicating failed dns lookup.
\param id Resolve ID */
virtual void OnResolveFailed(int id);
//@}
#endif // ENABLE_RESOLVER
#ifdef ENABLE_DETACH
/** \name Thread Support */
//@{
/** Callback fires when a new socket thread has started and this
socket is ready for operation again.
\sa ResolvSocket */
virtual void OnDetached();
// LIST_DETACH
/** Internal use. */
void SetDetach(bool x = true);
/** Check detach flag.
\return true if the socket should detach to its own thread */
bool IsDetach();
/** Internal use. */
void SetDetached(bool x = true);
/** Check detached flag.
\return true if the socket runs in its own thread. */
const bool IsDetached() const;
/** Order this socket to start its own thread and call OnDetached
when ready for operation. */
bool Detach();
/** Store the slave sockethandler pointer. */
void SetSlaveHandler(ISocketHandler *);
/** Create new thread for this socket to run detached in. */
void DetachSocket();
//@}
#endif // ENABLE_DETACH
/** Write traffic to an IFile. Socket will not delete this object. */
void SetTrafficMonitor(IFile *p) {
m_traffic_monitor = p;
}
protected:
/** default constructor not available */
Socket() : m_handler(m_handler) {}
/** copy constructor not available */
Socket(const Socket& s) : m_handler(s.m_handler) {}
/** assignment operator not available. */
Socket& operator=(const Socket& ) {
return *this;
}
/** All traffic will be written to this IFile, if set. */
IFile *GetTrafficMonitor() {
return m_traffic_monitor;
}
// unsigned long m_flags; ///< boolean flags, replacing old 'bool' members
private:
ISocketHandler& m_handler; ///< Reference of ISocketHandler in control of this socket
SOCKET m_socket; ///< File descriptor
bool m_bDel; ///< Delete by handler flag
bool m_bClose; ///< Close and delete flag
time_t m_tCreate; ///< Time in seconds when this socket was created
Socket *m_parent; ///< Pointer to ListenSocket class, valid for incoming sockets
bool m_b_disable_read; ///< Disable checking for read events
bool m_connected; ///< Socket is connected (tcp/udp)
bool m_b_erased_by_handler; ///< Set by handler before delete
time_t m_tClose; ///< Time in seconds when ordered to close
std::auto_ptr<SocketAddress> m_client_remote_address; ///< Address of last connect()
std::auto_ptr<SocketAddress> m_remote_address; ///< Remote end address
IFile *m_traffic_monitor;
time_t m_timeout_start; ///< Set by SetTimeout
time_t m_timeout_limit; ///< Defined by SetTimeout
bool m_bLost; ///< connection lost
static socketuid_t m_next_uid;
socketuid_t m_uid;
bool m_call_on_connect; ///< OnConnect will be called next ISocketHandler cycle if true
bool m_b_retry_connect; ///< Try another connection attempt next ISocketHandler cycle
#ifdef _WIN32
static WSAInitializer m_winsock_init; ///< Winsock initialization singleton class
#endif
#ifdef HAVE_OPENSSL
bool m_b_enable_ssl; ///< Enable SSL for this TcpSocket
bool m_b_ssl; ///< ssl negotiation mode (TcpSocket)
bool m_b_ssl_server; ///< True if this is an incoming ssl TcpSocket connection
#endif
//#ifdef ENABLE_IPV6
bool m_ipv6; ///< This is an ipv6 socket if this one is true
//#endif
#ifdef ENABLE_POOL
int m_socket_type; ///< Type of socket, from socket() call
std::string m_socket_protocol; ///< Protocol, from socket() call
bool m_bClient; ///< only client connections are pooled
bool m_bRetain; ///< keep connection on close
#endif
#ifdef ENABLE_SOCKS4
bool m_bSocks4; ///< socks4 negotiation mode (TcpSocket)
ipaddr_t m_socks4_host; ///< socks4 server address
port_t m_socks4_port; ///< socks4 server port number
std::string m_socks4_userid; ///< socks4 server usedid
#endif
#ifdef ENABLE_DETACH
bool m_detach; ///< Socket ordered to detach flag
bool m_detached; ///< Socket has been detached
SocketThread *m_pThread; ///< Detach socket thread class pointer
ISocketHandler *m_slave_handler; ///< Actual sockethandler while detached
#endif
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_Socket_H
@@ -1,106 +0,0 @@
/**
** \file SocketAddress.h
** \date 2006-09-21
** \author grymse@alhem.net
**/
/*
Copyright (C) 2007-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_SocketAddress_H
#define _SOCKETS_SocketAddress_H
#include "sockets-config.h"
#include <string>
#include <memory>
#include "socket_include.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
/**
This class and its subclasses is intended to be used as replacement
for the internal data type 'ipaddr_t' and various implementations of
IPv6 addressing found throughout the library.
'ipaddr_t' is an IPv4 address in network byte order.
'port_t' is the portnumber in host byte order.
'struct in6_addr' is an IPv6 address.
'struct in_addr' is an IPv4 address.
\ingroup basic
*/
class SocketAddress
{
public:
virtual ~SocketAddress() {}
/** Get a pointer to the address struct. */
virtual operator struct sockaddr *() = 0;
/** Get length of address struct. */
virtual operator socklen_t() = 0;
/** Compare two addresses. */
virtual bool operator==(SocketAddress&) = 0;
/** Set port number.
\param port Port number in host byte order */
virtual void SetPort(port_t port) = 0;
/** Get port number.
\return Port number in host byte order. */
virtual port_t GetPort() = 0;
/** Set socket address.
\param sa Pointer to either 'struct sockaddr_in' or 'struct sockaddr_in6'. */
virtual void SetAddress(struct sockaddr *sa) = 0;
/** Convert address to text. */
virtual std::string Convert(bool include_port) = 0;
/** Reverse lookup of address. */
virtual std::string Reverse() = 0;
/** Get address family. */
virtual int GetFamily() = 0;
/** Address structure is valid. */
virtual bool IsValid() = 0;
/** Get a copy of this SocketAddress object. */
virtual std::auto_ptr<SocketAddress> GetCopy() = 0;
};
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // _SOCKETS_SocketAddress_H
File diff suppressed because it is too large Load Diff
@@ -1,302 +0,0 @@
/** \file SocketHandler.h
** \date 2004-02-13
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETS_SocketHandler_H
#define _SOCKETS_SocketHandler_H
#include "sockets-config.h"
#include <map>
#include <list>
#include "socket_include.h"
#include "ISocketHandler.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class Socket;
#ifdef ENABLE_RESOLVER
class ResolvServer;
#endif
class IMutex;
class SocketHandlerThread;
class UdpSocket;
/** Socket container class, event generator.
\ingroup basic */
class SocketHandler : public ISocketHandler
{
protected:
/** Map type for holding file descriptors/socket object pointers. */
typedef std::map<SOCKET,Socket *> socket_m;
public:
/** SocketHandler constructor.
\param log Optional log class pointer */
SocketHandler(StdLog *log = NULL);
/** SocketHandler threadsafe constructor.
\param mutex Externally declared mutex variable
\param log Optional log class pointer */
SocketHandler(IMutex& mutex,StdLog *log = NULL);
SocketHandler(IMutex&, ISocketHandler& parent, StdLog * = NULL);
~SocketHandler();
virtual ISocketHandler *Create(StdLog * = NULL);
virtual ISocketHandler *Create(IMutex&, ISocketHandler&, StdLog * = NULL);
virtual bool ParentHandlerIsValid();
virtual ISocketHandler& ParentHandler();
virtual ISocketHandler& GetRandomHandler();
virtual ISocketHandler& GetEffectiveHandler();
virtual void SetNumberOfThreads(size_t n);
virtual bool IsThreaded();
virtual void EnableRelease();
virtual void Release();
/** Get mutex reference for threadsafe operations. */
IMutex& GetMutex() const;
/** Register StdLog object for error callback.
\param log Pointer to log class */
void RegStdLog(StdLog *log);
/** Log error to log class for print out / storage. */
void LogError(Socket *p,const std::string& user_text,int err,const std::string& sys_err,loglevel_t t = LOG_LEVEL_WARNING);
/** Add socket instance to socket map. Removal is always automatic. */
void Add(Socket *);
/** Set read/write/exception file descriptor sets (fd_set). */
void ISocketHandler_Add(Socket *,bool bRead,bool bWrite);
void ISocketHandler_Mod(Socket *,bool bRead,bool bWrite);
void ISocketHandler_Del(Socket *);
/** Wait for events, generate callbacks. */
int Select(long sec,long usec);
/** This method will not return until an event has been detected. */
int Select();
/** Wait for events, generate callbacks. */
int Select(struct timeval *tsel);
/** Check that a socket really is handled by this socket handler. */
bool Valid(Socket *);
bool Valid(socketuid_t);
/** Return number of sockets handled by this handler. */
size_t GetCount();
size_t MaxCount() {
return FD_SETSIZE;
}
/** Override and return false to deny all incoming connections.
\param p ListenSocket class pointer (use GetPort to identify which one) */
bool OkToAccept(Socket *p);
/** Use with care, always lock with h.GetMutex() if multithreaded */
const std::map<SOCKET, Socket *>& AllSockets() {
return m_sockets;
}
size_t MaxTcpLineSize() {
return TCP_LINE_SIZE;
}
void SetCallOnConnect(bool = true);
void SetDetach(bool = true);
void SetTimeout(bool = true);
void SetRetry(bool = true);
void SetClose(bool = true);
private:
static FILE *m_event_file;
static unsigned long m_event_counter;
public:
// Connection pool
#ifdef ENABLE_POOL
/** Find available open connection (used by connection pool). */
ISocketHandler::PoolSocket *FindConnection(int type,const std::string& protocol,SocketAddress&);
/** Enable connection pool (by default disabled). */
void EnablePool(bool x = true);
/** Check pool status.
\return true if connection pool is enabled */
bool PoolEnabled();
#endif // ENABLE_POOL
// Socks4
#ifdef ENABLE_SOCKS4
/** Set socks4 server ip that all new tcp sockets should use. */
void SetSocks4Host(ipaddr_t);
/** Set socks4 server hostname that all new tcp sockets should use. */
void SetSocks4Host(const std::string& );
/** Set socks4 server port number that all new tcp sockets should use. */
void SetSocks4Port(port_t);
/** Set optional socks4 userid. */
void SetSocks4Userid(const std::string& );
/** If connection to socks4 server fails, immediately try direct connection to final host. */
void SetSocks4TryDirect(bool x = true);
/** Get socks4 server ip.
\return socks4 server ip */
ipaddr_t GetSocks4Host();
/** Get socks4 port number.
\return socks4 port number */
port_t GetSocks4Port();
/** Get socks4 userid (optional).
\return socks4 userid */
const std::string& GetSocks4Userid();
/** Check status of socks4 try direct flag.
\return true if direct connection should be tried if connection to socks4 server fails */
bool Socks4TryDirect();
#endif // ENABLE_SOCKS4
// DNS resolve server
#ifdef ENABLE_RESOLVER
/** Enable asynchronous DNS.
\param port Listen port of asynchronous dns server */
void EnableResolver(port_t port = 16667);
/** Check resolver status.
\return true if resolver is enabled */
bool ResolverEnabled();
/** Queue a dns request.
\param host Hostname to be resolved
\param port Port number will be echoed in Socket::OnResolved callback */
int Resolve(Socket *,const std::string& host,port_t port);
#ifdef ENABLE_IPV6
int Resolve6(Socket *,const std::string& host,port_t port);
#endif
/** Do a reverse dns lookup. */
int Resolve(Socket *,ipaddr_t a);
#ifdef ENABLE_IPV6
int Resolve(Socket *,in6_addr& a);
#endif
/** Get listen port of asynchronous dns server. */
port_t GetResolverPort();
/** Resolver thread ready for queries. */
bool ResolverReady();
/** Returns true if the socket is waiting for a resolve event. */
bool Resolving(Socket *);
#endif // ENABLE_RESOLVER
#ifdef ENABLE_DETACH
/** Indicates that the handler runs under SocketThread. */
void SetSlave(bool x = true);
/** Indicates that the handler runs under SocketThread. */
bool IsSlave();
#endif
protected:
socket_m m_sockets; ///< Active sockets map
std::list<Socket *> m_add; ///< Sockets to be added to sockets map
std::list<Socket *> m_delete; ///< Sockets to be deleted (failed when Add)
protected:
/** Actual call to select() */
int ISocketHandler_Select(struct timeval *);
/** Remove socket from socket map, used by Socket class. */
void Remove(Socket *);
/** Schedule socket for deletion */
void DeleteSocket(Socket *);
void AddIncoming();
void CheckErasedSockets();
void CheckCallOnConnect();
void CheckDetach();
void CheckTimeout(time_t);
void CheckRetry();
void CheckClose();
//
StdLog *m_stdlog; ///< Registered log class, or NULL
IMutex& m_mutex; ///< Thread safety mutex
bool m_b_use_mutex; ///< Mutex correctly initialized
ISocketHandler& m_parent;
bool m_b_parent_is_valid;
private:
void RebuildFdset();
void Set(Socket *,bool,bool);
//
std::list<SocketHandlerThread *> m_threads;
UdpSocket *m_release;
//
SOCKET m_maxsock; ///< Highest file descriptor + 1 in active sockets list
fd_set m_rfds; ///< file descriptor set monitored for read events
fd_set m_wfds; ///< file descriptor set monitored for write events
fd_set m_efds; ///< file descriptor set monitored for exceptions
time_t m_tlast; ///< timeout control
// state lists
std::list<socketuid_t> m_fds_erase; ///< File descriptors that are to be erased from m_sockets
bool m_b_check_callonconnect;
bool m_b_check_detach;
bool m_b_check_timeout;
bool m_b_check_retry;
bool m_b_check_close;
#ifdef ENABLE_SOCKS4
ipaddr_t m_socks4_host; ///< Socks4 server host ip
port_t m_socks4_port; ///< Socks4 server port number
std::string m_socks4_userid; ///< Socks4 userid
bool m_bTryDirect; ///< Try direct connection if socks4 server fails
#endif
#ifdef ENABLE_RESOLVER
int m_resolv_id; ///< Resolver id counter
ResolvServer *m_resolver; ///< Resolver thread pointer
port_t m_resolver_port; ///< Resolver listen port
std::map<socketuid_t, bool> m_resolve_q; ///< resolve queue
#endif
#ifdef ENABLE_POOL
bool m_b_enable_pool; ///< Connection pool enabled if true
#endif
#ifdef ENABLE_DETACH
bool m_slave; ///< Indicates that this is a ISocketHandler run in SocketThread
#endif
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETS_SocketHandler_H
@@ -1,216 +0,0 @@
/** \file SocketHandler.cpp
** \date 2010-02-13
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "SocketHandlerEp.h"
#include "Exception.h"
#include "IMutex.h"
#include "Utility.h"
#include <errno.h>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
SocketHandlerEp::SocketHandlerEp(StdLog *p)
:SocketHandler(p)
,m_epoll(-1)
{
#ifdef LINUX
m_epoll = epoll_create(FD_SETSIZE);
if (m_epoll == -1)
{
throw Exception(StrError(Errno));
}
#endif
}
SocketHandlerEp::SocketHandlerEp(IMutex& mutex, StdLog *p)
:SocketHandler(mutex, p)
,m_epoll(-1)
{
#ifdef LINUX
m_epoll = epoll_create(FD_SETSIZE);
if (m_epoll == -1)
{
throw Exception(StrError(Errno));
}
#endif
}
SocketHandlerEp::SocketHandlerEp(IMutex& mutex, ISocketHandler& parent, StdLog *p)
:SocketHandler(mutex, parent, p)
,m_epoll(-1)
{
#ifdef LINUX
m_epoll = epoll_create(FD_SETSIZE);
if (m_epoll == -1)
{
throw Exception(StrError(Errno));
}
#endif
}
SocketHandlerEp::~SocketHandlerEp()
{
#ifdef LINUX
if (m_epoll != -1)
{
close(m_epoll);
}
#endif
}
ISocketHandler *SocketHandlerEp::Create(StdLog *log)
{
return new SocketHandlerEp(log);
}
ISocketHandler *SocketHandlerEp::Create(IMutex& mutex, ISocketHandler& parent, StdLog *log)
{
return new SocketHandlerEp(mutex, parent, log);
}
#ifdef LINUX
void SocketHandlerEp::ISocketHandler_Add(Socket *p,bool bRead,bool bWrite)
{
struct epoll_event stat;
SOCKET s = p -> GetSocket();
stat.data.ptr = p;
stat.events = (bRead ? EPOLLIN : 0) | (bWrite ? EPOLLOUT : 0);
if (epoll_ctl(m_epoll, EPOLL_CTL_ADD, s, &stat) == -1)
{
LogError(NULL, "epoll_ctl: EPOLL_CTL_ADD", Errno, StrError(Errno));
}
}
void SocketHandlerEp::ISocketHandler_Mod(Socket *p,bool r,bool w)
{
struct epoll_event stat;
SOCKET s = p -> GetSocket();
stat.data.ptr = p;
stat.events = (r ? EPOLLIN : 0) | (w ? EPOLLOUT : 0);
if (epoll_ctl(m_epoll, EPOLL_CTL_MOD, s, &stat) == -1)
{
// LogError(NULL, "epoll_ctl: EPOLL_CTL_MOD", Errno, StrError(Errno));
}
}
void SocketHandlerEp::ISocketHandler_Del(Socket *p)
{
struct epoll_event stat;
stat.events = 0;
stat.data.ptr = p;
if (epoll_ctl(m_epoll, EPOLL_CTL_DEL, p -> GetSocket(), &stat) == -1)
{
// LogError(NULL, "epoll_ctl: EPOLL_CTL_DEL", Errno, StrError(Errno));
}
}
int SocketHandlerEp::ISocketHandler_Select(struct timeval *tsel)
{
int n;
if (m_b_use_mutex)
{
m_mutex.Unlock();
n = epoll_wait(m_epoll, m_events, MAX_EVENTS_EP_WAIT, tsel ? tsel -> tv_sec * 1000 + tsel -> tv_usec / 1000 : -1);
m_mutex.Lock();
}
else
{
n = epoll_wait(m_epoll, m_events, MAX_EVENTS_EP_WAIT, tsel ? tsel -> tv_sec * 1000 + tsel -> tv_usec / 1000 : -1);
}
if (n == -1)
{
LogError(NULL, "epoll_wait", Errno, StrError(Errno));
}
else
if (!n)
{
}
else
if (n > 0)
{
for (int x = 0; x < n; x++)
{
Socket *p = static_cast<Socket *>(m_events[x].data.ptr);
if ((m_events[x].events & EPOLLIN) || (m_events[x].events & EPOLLHUP))
{
#ifdef HAVE_OPENSSL
if (p -> IsSSLNegotiate())
{
p -> SSLNegotiate();
}
else
#endif
{
p -> OnRead();
}
}
if (m_events[x].events & EPOLLOUT)
{
#ifdef HAVE_OPENSSL
if (p -> IsSSLNegotiate())
{
p -> SSLNegotiate();
}
else
#endif
{
p -> OnWrite();
}
}
if (m_events[x].events & EPOLLERR)
{
p -> OnException();
}
}
}
return n;
}
#endif
#ifdef SOCKETS_NAMESPACE
}
#endif
@@ -1,96 +0,0 @@
/** \file SocketHandlerEp.h
** \date 2010-02-13
** \author grymse@alhem.net
**/
/*
Copyright (C) 2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL, with
the additional exemption that compiling, linking, and/or using OpenSSL
is allowed.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETHANDLEREP_H
#define _SOCKETHANDLEREP_H
#include "SocketHandler.h"
#ifdef LINUX
#include <sys/epoll.h>
#define MAX_EVENTS_EP_WAIT 100
#endif // LINUX
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class SocketHandlerEp : public SocketHandler
{
public:
/** SocketHandler constructor.
\param log Optional log class pointer */
SocketHandlerEp(StdLog *log = NULL);
/** SocketHandler threadsafe constructor.
\param mutex Externally declared mutex variable
\param log Optional log class pointer */
SocketHandlerEp(IMutex& mutex,StdLog *log = NULL);
SocketHandlerEp(IMutex&, ISocketHandler& parent, StdLog * = NULL);
~SocketHandlerEp();
ISocketHandler *Create(StdLog * = NULL);
ISocketHandler *Create(IMutex&, ISocketHandler&, StdLog * = NULL);
#ifdef LINUX
/** Set read/write/exception file descriptor sets (fd_set). */
void ISocketHandler_Add(Socket *,bool bRead,bool bWrite);
void ISocketHandler_Mod(Socket *,bool bRead,bool bWrite);
void ISocketHandler_Del(Socket *);
size_t MaxCount() {
return 10000; // %!
}
protected:
/** Actual call to select() */
int ISocketHandler_Select(struct timeval *);
#endif // LINUX
private:
int m_epoll; ///< epoll file descriptor
#ifdef LINUX
struct epoll_event m_events[MAX_EVENTS_EP_WAIT];
#endif // LINUX
};
#ifdef SOCKETS_NAMESPACE
}
#endif
#endif // _SOCKETHANDLEREP_H
@@ -1,81 +0,0 @@
/**
** \file SocketHandlerThread.cpp
** \date 2010-03-21
** \author grymse@alhem.net
**/
/*
Copyright (C) 2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "SocketHandlerThread.h"
#include "Mutex.h"
#include "ISocketHandler.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
SocketHandlerThread::SocketHandlerThread(ISocketHandler& parent) : Thread(false)
, m_parent(parent)
, m_handler(NULL)
{
}
SocketHandlerThread::~SocketHandlerThread()
{
}
ISocketHandler& SocketHandlerThread::Handler()
{
return *m_handler;
}
void SocketHandlerThread::Run()
{
Mutex mutex;
m_handler = m_parent.Create(mutex, m_parent);
m_sem.Post();
ISocketHandler& h = *m_handler;
h.EnableRelease();
while (IsRunning())
{
h.Select(1, 0);
}
}
void SocketHandlerThread::Wait()
{
m_sem.Wait();
}
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
@@ -1,68 +0,0 @@
/**
** \file SocketHandlerThread.h
** \date 2010-03-21
** \author grymse@alhem.net
**/
/*
Copyright (C) 2010 Anders Hedstrom
This library is made available under the terms of the GNU GPL.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SOCKETHANDLERTHREAD_H
#define _SOCKETHANDLERTHREAD_H
#include "Thread.h"
#include "Semaphore.h"
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE
{
#endif
class ISocketHandler;
class SocketHandlerThread : public Thread
{
public:
SocketHandlerThread(ISocketHandler& parent);
~SocketHandlerThread();
virtual void Run();
ISocketHandler& Handler();
void Wait();
private:
ISocketHandler& m_parent;
ISocketHandler *m_handler;
Semaphore m_sem;
};
#ifdef SOCKETS_NAMESPACE
} // namespace SOCKETS_NAMESPACE {
#endif
#endif // _SOCKETHANDLERTHREAD_H

Some files were not shown because too many files have changed in this diff Show More