mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-17 20:23:47 -04:00
A Http lite interface .. allow asynce responces.
This commit is contained in:
parent
baea170229
commit
795c46b32d
2
direct/src/http/application_log.h
Normal file
2
direct/src/http/application_log.h
Normal file
@ -0,0 +1,2 @@
|
||||
#define LOGINFO printf
|
||||
#define LOGWARNING printf
|
65
direct/src/http/baseincomingset.h
Normal file
65
direct/src/http/baseincomingset.h
Normal file
@ -0,0 +1,65 @@
|
||||
#ifndef __BASEINCOMINGSET_H__
|
||||
#define __BASEINCOMINGSET_H__
|
||||
|
||||
#include <list>
|
||||
#include "socket_base.h"
|
||||
|
||||
enum CloseState
|
||||
{
|
||||
ConnectionDoNotClose,
|
||||
ConnectionDoClose
|
||||
};
|
||||
// RHH
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Template :BaseIncomingSet
|
||||
//
|
||||
// Description : A base structre for a listening socket and a
|
||||
// set of connection that have been received with there read functions..
|
||||
//
|
||||
// Think of this like a web server with 1 listening socket and 0-n open reacting conections..
|
||||
//
|
||||
// The general operation if get connection..
|
||||
// do you have a message
|
||||
// process message
|
||||
// go back to do you have a message or close connection
|
||||
//
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template < class _INCLASS1,class _IN_LISTEN, class MESSAGE_READER_BUF, class MESSAGE_READER_UPPASS> class BaseIncomingSet : public std::list<_INCLASS1 *>
|
||||
{
|
||||
_IN_LISTEN _Listener;
|
||||
|
||||
inline void AddFromListener(void);
|
||||
inline int PumpReader(Time_Clock ¤tTime);
|
||||
inline void AddAConection(_INCLASS1 * newt);
|
||||
|
||||
public:
|
||||
|
||||
// typedef typename BaseIncomingSet<_INCLASS1, _IN_LISTEN, MESSAGE_READER_BUF, MESSAGE_READER_UPPASS>::LinkNode LinkNode;
|
||||
|
||||
// typedef SentDblLinkListNode_Gm SentDblLinkListNode_Gm;
|
||||
inline BaseIncomingSet(void);
|
||||
inline BaseIncomingSet(BaseIncomingSet &in);
|
||||
virtual ~BaseIncomingSet();
|
||||
|
||||
inline _IN_LISTEN & GetListener(void);
|
||||
inline bool init(Socket_Address &WhereFrom);
|
||||
inline void PumpAll(Time_Clock ¤tTime);
|
||||
virtual CloseState ProcessNewConnection(SOCKET socket);
|
||||
inline void AddToFDSet(Socket_fdset &set);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// inline LinkNode * GetRoot(void) { return &this->sentenal; };
|
||||
BaseIncomingSet &operator=( BaseIncomingSet &inval);
|
||||
void Reset();
|
||||
};
|
||||
|
||||
#include "baseincomingset.i"
|
||||
|
||||
#endif //__BASEINCOMINGSET_H__
|
||||
|
||||
|
||||
|
202
direct/src/http/baseincomingset.i
Normal file
202
direct/src/http/baseincomingset.i
Normal file
@ -0,0 +1,202 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::AddFromListener
|
||||
// Description : Read incoming connections off the listener
|
||||
//
|
||||
// Return type : inline void
|
||||
// Argument : void
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::AddFromListener(void)
|
||||
{
|
||||
Socket_Address Addr1;
|
||||
SOCKET newsck;
|
||||
|
||||
|
||||
while(_Listener.GetIncomingConnection(newsck,Addr1) == true)
|
||||
{
|
||||
CloseState cl= ProcessNewConnection(newsck);
|
||||
if(cl == ConnectionDoNotClose)
|
||||
{
|
||||
_INCLASS1 * newt = new _INCLASS1(newsck,Addr1);
|
||||
AddAConection(newt);
|
||||
}
|
||||
else
|
||||
DO_CLOSE(newsck);
|
||||
}
|
||||
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::PumpReader
|
||||
// Description : Tries to read a record off the incoming socket
|
||||
//
|
||||
// Return type : inline void
|
||||
// Argument : Time_Clock currentTime
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline int BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::PumpReader(Time_Clock ¤tTime)
|
||||
{
|
||||
MESSAGE_READER_BUF message;
|
||||
|
||||
iterator lpNext, lp;
|
||||
for (lpNext = lp = begin(); lp != end() ; lp = lpNext)
|
||||
{
|
||||
lpNext++;
|
||||
|
||||
int ans = (*lp)->ReadIt(message, sizeof(message),currentTime);
|
||||
if(ans < 0)
|
||||
{
|
||||
delete *lp;
|
||||
erase(lp);
|
||||
}
|
||||
if(ans > 0)
|
||||
{
|
||||
CloseState cs = (*lp)->ProcessMessage(message,currentTime);
|
||||
if( cs == ConnectionDoClose)
|
||||
{
|
||||
delete *lp;
|
||||
erase(lp);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::AddAConection
|
||||
// Description : Adds a member to the base container
|
||||
//
|
||||
// Return type : inline void
|
||||
// Argument : _INCLASS1 * newt
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::AddAConection(_INCLASS1 * newt)
|
||||
{
|
||||
push_back(newt);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::BaseIncomingSet
|
||||
// Description : core constructor
|
||||
//
|
||||
// Return type : inline
|
||||
// Argument : void
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::BaseIncomingSet(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::BaseIncomingSet(BaseIncomingSet &in)
|
||||
{
|
||||
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::~BaseIncomingSet
|
||||
// Description : The Destructot .. will delete all members.. ??
|
||||
//
|
||||
// Return type :
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::~BaseIncomingSet()
|
||||
{
|
||||
for(iterator ii = begin(); ii != end(); ii++)
|
||||
delete *ii;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : & BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::GetListener
|
||||
// Description : Retyurns a pointer to the listener in this class
|
||||
//
|
||||
// Return type : inline _IN_LISTEN
|
||||
// Argument : void
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline _IN_LISTEN & BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::GetListener(void)
|
||||
{
|
||||
return this->Listener;
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::init
|
||||
// Description : the second part of the 2 phase power up.. Opends the listener
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : Socket_Address &WhereFrom
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline bool BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::init(Socket_Address &WhereFrom)
|
||||
{
|
||||
if(_Listener.OpenForListen(WhereFrom,true) != true)
|
||||
return false;
|
||||
_Listener.SetNonBlocking();
|
||||
return true;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::PumpAll
|
||||
// Description : THis is the polled interface to this class
|
||||
//
|
||||
// Return type : inline void
|
||||
// Argument : Time_Clock ¤tTime
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::PumpAll(Time_Clock ¤tTime)
|
||||
{
|
||||
PumpReader(currentTime); // I MOVED ORDER TO FINE TUNE THE READ OPERATIONS
|
||||
AddFromListener();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::ProcessNewConnection
|
||||
// Description : this is the vertual function call when a new connection is created
|
||||
// manly here for loging if needed...
|
||||
//
|
||||
// Return type : CloseState
|
||||
// Argument : SOCKET socket
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
CloseState BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::ProcessNewConnection(SOCKET socket)
|
||||
{
|
||||
return ConnectionDoNotClose;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::AddToFDSet
|
||||
// Description : Add LIstener and Client to the FD set for polled reading
|
||||
//
|
||||
// Return type : inline
|
||||
// Argument : Socket_Selector &set
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::AddToFDSet(Socket_fdset &set1)
|
||||
{
|
||||
if(_Listener.Active())
|
||||
set1.setForSocket(_Listener);
|
||||
iterator lp;
|
||||
|
||||
for (lp = begin(); lp != end(); lp = lp++)
|
||||
set1.setForSocket((*lp)->val);
|
||||
}
|
||||
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS> &BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::operator=
|
||||
(BaseIncomingSet &inval)
|
||||
{
|
||||
if (&inval == this) return *this;
|
||||
_Listener = inval._Listener;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
|
||||
inline void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::Reset()
|
||||
{
|
||||
_Listener.Close();
|
||||
iterator lpNext, lp;
|
||||
for (lpNext = lp = begin(); lp != end() ; lp = lpNext)
|
||||
{
|
||||
lpNext++;
|
||||
(*lp)->Reset();
|
||||
delete *lp;
|
||||
erase(lp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
117
direct/src/http/bufferedwriter_growable.h
Normal file
117
direct/src/http/bufferedwriter_growable.h
Normal file
@ -0,0 +1,117 @@
|
||||
#ifndef __BufferedWriter_Growable_H__
|
||||
#define __BufferedWriter_Growable_H__
|
||||
///////////////////////////////////////////////////////
|
||||
// this class is for the usage of growable output...
|
||||
// it is slower than buffered writer but more robust..
|
||||
// it also allows for writes to take more time to the out putt..
|
||||
// ie.. Write buffering.. Not just one write..
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
class BufferedWriter_Growable : public std::string
|
||||
{
|
||||
int _write_offset;
|
||||
public:
|
||||
|
||||
BufferedWriter_Growable(void);
|
||||
~BufferedWriter_Growable(void);
|
||||
int AmountBuffered(void);
|
||||
void AppendData(const char * buf, int len);
|
||||
void Reset() { clear(); _write_offset = 0; };
|
||||
const char * GetMessageHead(void);
|
||||
int Flush(Socket_TCP &sck) ; // this is the ugly part
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : BufferedWriter_Growable::BufferedWriter_Growable
|
||||
// Description :
|
||||
// Return type : inline
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline BufferedWriter_Growable::BufferedWriter_Growable(void)
|
||||
{
|
||||
_write_offset = 0;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : ~BufferedWriter_Growable::BufferedWriter_Growable
|
||||
// Description :
|
||||
// Return type : inline
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline BufferedWriter_Growable::~BufferedWriter_Growable(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : BufferedWriter_Growable::AmountBuffered
|
||||
// Description :
|
||||
// Return type : inline int
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int BufferedWriter_Growable::AmountBuffered(void)
|
||||
{
|
||||
return (int) (size() - _write_offset);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : BufferedWriter_Growable::AppendData
|
||||
// Description :
|
||||
// Return type : inline void
|
||||
// Argument : const char * buf
|
||||
// Argument : int len
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline void BufferedWriter_Growable::AppendData(const char * buf, int len)
|
||||
{
|
||||
append(buf, len);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : char * BufferedWriter_Growable::GetMessageHead
|
||||
// Description :
|
||||
// Return type : inline const
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline const char * BufferedWriter_Growable::GetMessageHead(void)
|
||||
{
|
||||
return data() + _write_offset;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : BufferedWriter_Growable::Flush
|
||||
// Description :
|
||||
// Return type : inline int
|
||||
// Argument : SocketTCP_Gm &sck
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int BufferedWriter_Growable::Flush(Socket_TCP &sck) // this is the ugly part
|
||||
{
|
||||
int answer = 0;
|
||||
int Writesize = AmountBuffered();
|
||||
|
||||
if(Writesize > 0)
|
||||
{
|
||||
const char * out1 = GetMessageHead();
|
||||
int Writen = sck.SendData(out1,Writesize);
|
||||
if(Writen > 0)
|
||||
{
|
||||
_write_offset += Writen;
|
||||
answer = 1;
|
||||
}
|
||||
else if(Writen < 0)
|
||||
{
|
||||
if(GETERROR() != LOCAL_BLOCKING_ERROR)
|
||||
answer = -1;
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
#endif //__BufferedWriter_Growable_H__
|
||||
|
||||
|
96
direct/src/http/http_bufferedreader.h
Normal file
96
direct/src/http/http_bufferedreader.h
Normal file
@ -0,0 +1,96 @@
|
||||
#ifndef __WEBBUFFEREDREADER_GM_H__
|
||||
#define __WEBBUFFEREDREADER_GM_H__
|
||||
// RHH
|
||||
|
||||
#include <string>
|
||||
#include "strtargetbuffer.h"
|
||||
#include "ringbuffer_slide.h"
|
||||
#include "application_log.h"
|
||||
|
||||
|
||||
class Http_BufferedReader : protected RingBuffer_Slide
|
||||
{
|
||||
inline bool GetTermedString(char * outdata, size_t maxlen,char termchar1, char termchar2);
|
||||
inline bool GetDoubleTermedString(char * outdata, int maxlen,char termchar1, char termchar2);
|
||||
inline bool GetTermedStringInPLace(char ** outdata,char termchars);
|
||||
inline bool GetTermedString(char * outdata, int maxlen,char * termchars);
|
||||
inline bool GetSizeString(StrTargetBuffer & outdata);
|
||||
public:
|
||||
inline Http_BufferedReader(int in_size = 8192) ;
|
||||
//
|
||||
// The Read Message Interface
|
||||
//
|
||||
inline void ReSet(void);
|
||||
inline int PumpCRRead(char * data, int maxdata, Socket_TCP &sck);
|
||||
inline int PumpHTTPHeaderRead(char * data, int maxdata, Socket_TCP &sck);
|
||||
inline int PumpSizeRead(StrTargetBuffer & outdata,Socket_TCP &sck);
|
||||
inline int PumpEofRead(StrTargetBuffer & outdata,Socket_TCP &sck);
|
||||
//inline int PumpMessageReader(CoreMessage &inmsg, Socket_TCP &sck);
|
||||
|
||||
|
||||
template < class SOCK_TYPE>
|
||||
inline int ReadPump(SOCK_TYPE &sck)
|
||||
{
|
||||
int answer = 0;
|
||||
size_t readsize = BufferAvailabe();
|
||||
|
||||
if(readsize < 1)
|
||||
{
|
||||
FullCompress();
|
||||
readsize = BufferAvailabe();
|
||||
}
|
||||
|
||||
|
||||
if(readsize > 0)
|
||||
{
|
||||
char * ff = GetBufferOpen();
|
||||
int gotbytes = sck.RecvData(ff,(int)readsize);
|
||||
|
||||
|
||||
if(gotbytes < 0) // some error
|
||||
{
|
||||
int er = GETERROR();
|
||||
// if(err != LOCAL_BLOCKING_ERROR )
|
||||
if(!sck.ErrorIs_WouldBlocking(gotbytes) )
|
||||
{
|
||||
answer = -3;
|
||||
LOGINFO("Http_BufferedReader::ReadPump->Socket Level Read Error %d %d %d %s",er,gotbytes,errno,sck.GetPeerName().get_ip_port().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
answer = 0; // try again nothing to read
|
||||
}
|
||||
}
|
||||
else if(gotbytes > 0) // ok got some lets process it
|
||||
{
|
||||
|
||||
_EndPos += gotbytes;
|
||||
answer = 1;
|
||||
}
|
||||
else // 0 mean other end disconect arggggg
|
||||
{
|
||||
answer = -1;
|
||||
LOGWARNING("Http_BufferedReader::ReadPump->Other End Closed Normal [%s]",sck.GetPeerName().get_ip_port().c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string addstr = sck.GetPeerName().get_ip_port();
|
||||
LOGWARNING("Http_BufferedReader::ReadPump->** Very Important** No Internal buffer left for read[%s] BufferSIze=[%d][%d]",
|
||||
addstr.c_str(),
|
||||
AmountBuffered(),
|
||||
BufferAvailabe()
|
||||
);
|
||||
|
||||
answer = -2;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#include "http_bufferedreader.i"
|
||||
|
||||
#endif //__BUFFEREDREADER_GM_H__
|
||||
|
||||
|
296
direct/src/http/http_bufferedreader.i
Normal file
296
direct/src/http/http_bufferedreader.i
Normal file
@ -0,0 +1,296 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Http_BufferedReader::GetTermedString
|
||||
// Description : a function that will peal a terminated string from the buffer
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : char * outdata
|
||||
// Argument : int maxlen
|
||||
// Argument : char termchar1
|
||||
// Argument : char termchar2
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Http_BufferedReader::GetTermedString(char * outdata, size_t maxlen,char termchar1, char termchar2)
|
||||
{
|
||||
bool answer = false;
|
||||
size_t DataAvail = FastAmountBeffered();
|
||||
size_t MaxRead = maxlen;
|
||||
if(MaxRead > DataAvail)
|
||||
MaxRead = DataAvail;
|
||||
|
||||
char * wrk = FastGetMessageHead();
|
||||
for(size_t x=0; x< MaxRead; x++)
|
||||
{
|
||||
if(wrk[x] == termchar1 || wrk[x] == termchar2)
|
||||
{
|
||||
memcpy(outdata,wrk,x);
|
||||
outdata[x] = '\0';
|
||||
_StartPos += x+1;
|
||||
Compress();
|
||||
answer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Http_BufferedReader::GetDoubleTermedString
|
||||
// Description : a function that will peal a terminated string from the buffer
|
||||
//
|
||||
// This is the interface for a web request....
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : char * outdata
|
||||
// Argument : int maxlen
|
||||
// Argument : char termchar1
|
||||
// Argument : char termchar2
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Http_BufferedReader::GetDoubleTermedString(char * outdata, int maxlen,char termchar1, char termchar2)
|
||||
{
|
||||
bool answer = false;
|
||||
size_t DataAvail = FastAmountBeffered();
|
||||
size_t MaxRead = maxlen;
|
||||
if(MaxRead > DataAvail)
|
||||
MaxRead = DataAvail;
|
||||
|
||||
char * wrk = FastGetMessageHead();
|
||||
for(size_t x=1; x< MaxRead; x++)
|
||||
{
|
||||
if(
|
||||
(wrk[x] == termchar1 && wrk[x-1] == termchar1) ||
|
||||
(wrk[x] == termchar2 && wrk[x-1] == termchar2) ||
|
||||
( x >= 3 && wrk[x] == termchar1 && wrk[x-2] == termchar1 && wrk[x-1] == termchar2 && wrk[x-3] == termchar2 ) ||
|
||||
( x >= 3 && wrk[x] == termchar2 && wrk[x-2] == termchar2 && wrk[x-1] == termchar1 && wrk[x-3] == termchar1 )
|
||||
)
|
||||
{
|
||||
memcpy(outdata,wrk,x);
|
||||
outdata[x] = '\0';
|
||||
_StartPos += x+1;
|
||||
Compress();
|
||||
answer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Http_BufferedReader::GetTermedStringInPLace
|
||||
// Description : Will peal a string inplace for reading
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : char ** outdata
|
||||
// Argument : char termchars
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Http_BufferedReader::GetTermedStringInPLace(char ** outdata,char termchars)
|
||||
{
|
||||
bool answer = false;
|
||||
Compress();
|
||||
size_t MaxRead = FastAmountBeffered();
|
||||
char * wrk = FastGetMessageHead();
|
||||
for(size_t x=0; x< MaxRead; x++)
|
||||
{
|
||||
if(wrk[x] == termchars)
|
||||
{
|
||||
*outdata = wrk;
|
||||
wrk[x] = '\0';
|
||||
_StartPos += x+1;
|
||||
answer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Http_BufferedReader::GetTermedString
|
||||
// Description : do a read of a termed string not in place
|
||||
//
|
||||
// Return type : bool
|
||||
// Argument : char * outdata
|
||||
// Argument : int maxlen
|
||||
// Argument : char * termchars
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Http_BufferedReader::GetTermedString(char * outdata, int maxlen,char * termchars)
|
||||
{
|
||||
bool answer = false;
|
||||
size_t DataAvail = FastAmountBeffered();
|
||||
size_t MaxRead = maxlen;
|
||||
if(MaxRead > DataAvail)
|
||||
MaxRead = DataAvail;
|
||||
int tstrsize = (int)strlen(termchars);
|
||||
|
||||
char * wrk = FastGetMessageHead();
|
||||
for(size_t x=0; x< MaxRead; x++)
|
||||
{
|
||||
if(memcmp(&wrk[x],termchars,tstrsize) == 0)
|
||||
{
|
||||
memcpy(outdata,wrk,x);
|
||||
outdata[x] = '\0';
|
||||
_StartPos += x+tstrsize;
|
||||
Compress();
|
||||
answer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Http_BufferedReader::Http_BufferedReader
|
||||
// Description : constructore .. passes size up to ring buffer
|
||||
//
|
||||
// Return type : inline
|
||||
// Argument : int in_size
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline Http_BufferedReader::Http_BufferedReader(int in_size) : RingBuffer_Slide(in_size)
|
||||
{
|
||||
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Http_BufferedReader::ReSet
|
||||
// Description : Reaset all read content.. IE zero's out buffer...
|
||||
//
|
||||
// If you lose framing this will not help
|
||||
//
|
||||
// Return type : inline void
|
||||
// Argument : void
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline void Http_BufferedReader::ReSet(void)
|
||||
{
|
||||
ResetContent();
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Http_BufferedReader::PumpCRRead
|
||||
// Description : a upcall function to read a CR object off buffer
|
||||
//
|
||||
// Return type : inline int
|
||||
// Argument : char * data
|
||||
// Argument : int maxdata
|
||||
// Argument : Socket_TCP &sck
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline int Http_BufferedReader::PumpCRRead(char * data, int maxdata, Socket_TCP &sck)
|
||||
{
|
||||
if(GetTermedString(data,maxdata,'\r','\n') == true)
|
||||
return 1;
|
||||
|
||||
int rp = ReadPump(sck);
|
||||
if(rp == 0)
|
||||
return 0;
|
||||
|
||||
if(rp < 1)
|
||||
return -1;
|
||||
|
||||
if(GetTermedString(data,maxdata,'\r','\n') == true)
|
||||
return 1;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Http_BufferedReader::PumpHTTPHeaderRead
|
||||
// Description : Will read a HTTP head ,, GET ..... or responce from web server
|
||||
//
|
||||
// Return type : inline int
|
||||
// Argument : char * data
|
||||
// Argument : int maxdata
|
||||
// Argument : Socket_TCP &sck
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline int Http_BufferedReader::PumpHTTPHeaderRead(char * data, int maxdata, Socket_TCP &sck)
|
||||
{
|
||||
|
||||
if(GetDoubleTermedString(data,maxdata,'\r','\n') == true)
|
||||
return 1;
|
||||
|
||||
|
||||
int rp = ReadPump(sck);
|
||||
if(rp == 0)
|
||||
return 0;
|
||||
|
||||
if(rp < 1)
|
||||
return -1;
|
||||
|
||||
if(GetDoubleTermedString(data,maxdata,'\r','\n') == true)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline int Http_BufferedReader::PumpSizeRead(StrTargetBuffer & outdata,Socket_TCP &sck)
|
||||
{
|
||||
if(GetSizeString(outdata) == true)
|
||||
return 1;
|
||||
|
||||
int rp = ReadPump(sck);
|
||||
if(rp == 0)
|
||||
return 0;
|
||||
|
||||
if(rp < 1)
|
||||
return -1;
|
||||
|
||||
if(GetSizeString(outdata) == true)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline int Http_BufferedReader::PumpEofRead(StrTargetBuffer & outdata,Socket_TCP &sck)
|
||||
{
|
||||
// do a quick read
|
||||
{
|
||||
size_t MaxRead = FastAmountBeffered();
|
||||
if(MaxRead > 0)
|
||||
{
|
||||
char *ff = FastGetMessageHead();
|
||||
outdata.append(ff,MaxRead);
|
||||
_StartPos += MaxRead;
|
||||
Compress();
|
||||
}
|
||||
}
|
||||
|
||||
// pump the reader
|
||||
int rp = ReadPump(sck);
|
||||
if(rp == 0)
|
||||
return 0;
|
||||
|
||||
if(rp== -1) // eof
|
||||
{
|
||||
// if eof clean the mess
|
||||
size_t MaxRead = FastAmountBeffered();
|
||||
if(MaxRead > 0)
|
||||
{
|
||||
char *ff = FastGetMessageHead();
|
||||
outdata.append(ff,MaxRead);
|
||||
_StartPos += MaxRead;
|
||||
Compress();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if(rp < 1)
|
||||
return -1;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
inline bool Http_BufferedReader::GetSizeString(StrTargetBuffer & outdata)
|
||||
{
|
||||
size_t DataAvail = FastAmountBeffered();
|
||||
size_t MaxRead = outdata.left_to_fill();
|
||||
if(MaxRead > DataAvail)
|
||||
MaxRead = DataAvail;
|
||||
|
||||
char * wrk = FastGetMessageHead();
|
||||
if(MaxRead > 0)
|
||||
{
|
||||
|
||||
char *ff = FastGetMessageHead();
|
||||
outdata.append(ff,MaxRead);
|
||||
_StartPos += MaxRead;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
4
direct/src/http/http_composite1.cxx
Normal file
4
direct/src/http/http_composite1.cxx
Normal file
@ -0,0 +1,4 @@
|
||||
#include "http_connection.cxx"
|
||||
#include "parsedhttprequest.cxx"
|
||||
#include "http_request.cxx"
|
||||
|
166
direct/src/http/http_connection.cxx
Normal file
166
direct/src/http/http_connection.cxx
Normal file
@ -0,0 +1,166 @@
|
||||
#include "http_connection.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
HttpConnection::HttpConnection(SOCKET sck,Socket_Address &inaddr) :
|
||||
_Timer(Time_Span(10,0)) ,
|
||||
_MyAddress(inaddr),
|
||||
_state(READING_HEADER)
|
||||
{
|
||||
SetSocket(sck);
|
||||
SetNonBlocking();
|
||||
SetReuseAddress();
|
||||
|
||||
_writer.reserve(102400);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
HttpConnection::~HttpConnection(void)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const Socket_Address & HttpConnection::GetMyAddress(void)
|
||||
{
|
||||
return _MyAddress;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int HttpConnection::DoReadHeader(char * message, int buffersize,Time_Clock ¤tTime)
|
||||
{
|
||||
int ans = _Reader.PumpHTTPHeaderRead(message,buffersize,*this);
|
||||
|
||||
if(ans != 0)
|
||||
{
|
||||
if(ans > 0)
|
||||
_headerDetail.assign(message,buffersize);
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
if(_Timer.Expired(currentTime) == true)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int HttpConnection::DoReadBody(char * message1, int buffersize,Time_Clock ¤tTime)
|
||||
{
|
||||
int ans = _Reader.PumpSizeRead(_bodyDetail,*this);
|
||||
|
||||
if(ans != 0)
|
||||
{
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
if(_Timer.Expired(currentTime) == true)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ok lets process this thing..
|
||||
_state = WAITING_TO_FINALIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int HttpConnection::ReadIt(char * message, int buffersize,Time_Clock ¤tTime)
|
||||
{
|
||||
switch (_state)
|
||||
{
|
||||
case(READING_HEADER):
|
||||
return DoReadHeader(message, buffersize,currentTime);
|
||||
break;
|
||||
|
||||
case(READING_POST):
|
||||
return DoReadBody(message, buffersize,currentTime);
|
||||
break;
|
||||
|
||||
case(WAITING_TO_FINALIZE):
|
||||
return TryAndFinalize();
|
||||
break;
|
||||
|
||||
case(WRITING_DATA):
|
||||
return CloseStateWriter(currentTime);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
};
|
||||
return ConnectionDoClose;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
CloseState HttpConnection::ProcessMessage(char * message,Time_Clock ¤tTime)
|
||||
{
|
||||
if(_state == READING_POST )
|
||||
{
|
||||
_state = WAITING_TO_FINALIZE;
|
||||
return ConnectionDoClose;
|
||||
}
|
||||
|
||||
|
||||
if(_parser.ParseThis(message) != true)
|
||||
{
|
||||
Reset();
|
||||
return ConnectionDoClose;
|
||||
}
|
||||
// if it is a post go into read details mode and
|
||||
// wait to get the post data..
|
||||
// we do not support any other methoid today
|
||||
if(_parser.GetRequestType() == "POST")
|
||||
{
|
||||
int context_length = _parser.getContentLength();
|
||||
if(context_length > 0)
|
||||
{
|
||||
//_DoingExtraRead = true;
|
||||
_state = READING_POST;
|
||||
_bodyDetail.SetDataSize(context_length);
|
||||
return ConnectionDoNotClose;
|
||||
}
|
||||
}
|
||||
|
||||
_state = WAITING_TO_FINALIZE;
|
||||
|
||||
_parser.SetBodyText(_bodyDetail);
|
||||
_Timer.ResetTime(currentTime);
|
||||
|
||||
if(BuildPage(_writer,_parser) != true)
|
||||
return ConnectionDoClose;
|
||||
|
||||
if(_state == WRITING_DATA)
|
||||
{
|
||||
if(CloseStateWriter(currentTime) <0)
|
||||
return ConnectionDoClose;
|
||||
}
|
||||
|
||||
return ConnectionDoNotClose;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int HttpConnection::CloseStateWriter(Time_Clock ¤tTime)
|
||||
{
|
||||
int fans = _writer.Flush(*this); // write error
|
||||
if(fans < 0)
|
||||
return -1;
|
||||
|
||||
if(_writer.AmountBuffered() <= 0) // all done
|
||||
return -1;
|
||||
|
||||
if(_Timer.Expired(currentTime) == true) // too long
|
||||
return -1;
|
||||
|
||||
return 0; // keep trying
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void HttpConnection::Reset()
|
||||
{
|
||||
_state = ABORTING;
|
||||
Close();
|
||||
_Timer.ForceToExpired();
|
||||
}
|
||||
|
||||
|
61
direct/src/http/http_connection.h
Normal file
61
direct/src/http/http_connection.h
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef HttpConnection_H
|
||||
#define HttpConnection_H
|
||||
////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#include "parsedhttprequest.h"
|
||||
#include "baseincomingset.h"
|
||||
|
||||
#include "bufferedwriter_growable.h"
|
||||
#include "http_bufferedreader.h"
|
||||
|
||||
|
||||
class HttpConnection : public Socket_TCP
|
||||
{
|
||||
protected:
|
||||
Http_BufferedReader _Reader;
|
||||
BufferedWriter_Growable _writer;
|
||||
Socket_Address _MyAddress;
|
||||
|
||||
Time_Out _Timer;
|
||||
|
||||
enum STATE_CONNECTIONS {
|
||||
READING_HEADER =1,
|
||||
READING_POST =2,
|
||||
WAITING_TO_FINALIZE =3,
|
||||
WRITING_DATA =4,
|
||||
ABORTING = 5,
|
||||
};
|
||||
|
||||
|
||||
STATE_CONNECTIONS _state;
|
||||
|
||||
|
||||
ParsedHttpRequest _parser;
|
||||
|
||||
StrTargetBuffer _bodyDetail;
|
||||
std::string _headerDetail;
|
||||
|
||||
int CloseStateWriter(Time_Clock ¤tTime);
|
||||
|
||||
public:
|
||||
virtual ~HttpConnection(void);
|
||||
const Socket_Address & GetMyAddress(void);
|
||||
virtual bool BuildPage( BufferedWriter_Growable &_writer, ParsedHttpRequest &parser) = 0;
|
||||
HttpConnection(SOCKET sck,Socket_Address &inaddr) ;
|
||||
|
||||
CloseState ProcessMessage(char * message,Time_Clock ¤tTime);
|
||||
int DoReadHeader(char * message, int buffersize,Time_Clock ¤tTime);
|
||||
int DoReadBody(char * message, int buffersize,Time_Clock ¤tTime);
|
||||
int ReadIt(char * message, int buffersize,Time_Clock ¤tTime);
|
||||
void Reset();
|
||||
|
||||
virtual CloseState TryAndFinalize() { _state = WRITING_DATA; ;return ConnectionDoNotClose; };
|
||||
|
||||
std::string GetFullmessage() { return _headerDetail + _bodyDetail; };
|
||||
};
|
||||
|
||||
|
||||
#endif // HttpConnection_H
|
||||
|
||||
|
||||
|
37
direct/src/http/http_request.cxx
Normal file
37
direct/src/http/http_request.cxx
Normal file
@ -0,0 +1,37 @@
|
||||
#include "socket_base.h"
|
||||
|
||||
|
||||
#include "http_connection.h"
|
||||
#include "baseincomingset.h"
|
||||
#include "socket_base.h"
|
||||
|
||||
|
||||
#include "http_request.h"
|
||||
|
||||
|
||||
typedef BaseIncomingSet< Http_Request , Socket_TCP_Listen , char [10240], char *> Http_Source_BaseIncomingSet;
|
||||
static std::set< Http_Request * > Global_WebRequests_pendingNotify;
|
||||
static Http_Source_BaseIncomingSet Global_HttpManager;
|
||||
|
||||
bool Http_Request::HttpManager_Initialize( unsigned short port)
|
||||
{
|
||||
init_network();
|
||||
Socket_Address address;
|
||||
address.set_port(port);
|
||||
return Global_HttpManager.init(address);
|
||||
}
|
||||
|
||||
Http_Request * Http_Request::HttpManager_GetARequest()
|
||||
{
|
||||
Time_Clock Know;
|
||||
Global_HttpManager.PumpAll(Know);
|
||||
Http_Request * answer = NULL;
|
||||
std::set< Http_Request * >::iterator ii = Global_WebRequests_pendingNotify.begin();
|
||||
if(ii != Global_WebRequests_pendingNotify.end())
|
||||
{
|
||||
answer = *ii;
|
||||
Global_WebRequests_pendingNotify.erase(ii);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
108
direct/src/http/http_request.h
Normal file
108
direct/src/http/http_request.h
Normal file
@ -0,0 +1,108 @@
|
||||
#ifndef Http_Request_H_
|
||||
#define Http_Request_H_
|
||||
|
||||
class Http_Request;
|
||||
extern std::set< Http_Request * > Global_WebRequests_pendingNotify;
|
||||
|
||||
class Http_Request : public HttpConnection
|
||||
{
|
||||
public:
|
||||
Http_Request(SOCKET sck,Socket_Address &inaddr) : HttpConnection(sck,inaddr)
|
||||
{
|
||||
};
|
||||
|
||||
~Http_Request()
|
||||
{
|
||||
Global_WebRequests_pendingNotify.erase(this);
|
||||
};
|
||||
bool BuildPage( BufferedWriter_Growable &_writer, ParsedHttpRequest &parser)
|
||||
{
|
||||
Global_WebRequests_pendingNotify.insert((Http_Request *)this);
|
||||
|
||||
_state = WAITING_TO_FINALIZE;
|
||||
_Timer.ResetAll(Time_Clock::GetCurrentTime(),Time_Span(9999999,0));
|
||||
return true;
|
||||
};
|
||||
|
||||
CloseState TryAndFinalize()
|
||||
{
|
||||
return ConnectionDoNotClose;
|
||||
};
|
||||
|
||||
PUBLISHED:
|
||||
|
||||
std::string GetRequestType()
|
||||
{
|
||||
return _parser.GetRequestType();
|
||||
}
|
||||
|
||||
std::string GetRawRequest()
|
||||
{
|
||||
return _parser.GetRawRequest();
|
||||
}
|
||||
|
||||
std::string GetRequestURL()
|
||||
{
|
||||
return _parser.GetRequestURL();
|
||||
}
|
||||
|
||||
std::string GetSourceAddress()
|
||||
{
|
||||
return _MyAddress.get_ip_port();
|
||||
}
|
||||
|
||||
void AppendToResponce(const std::string &in)
|
||||
{
|
||||
_writer+=in;
|
||||
}
|
||||
|
||||
|
||||
void SendThisResponce(const std::string &in)
|
||||
{
|
||||
_writer+=in;
|
||||
Finish();
|
||||
}
|
||||
|
||||
void Finish()
|
||||
{
|
||||
_Timer.ResetAll(Time_Clock::GetCurrentTime(),Time_Span(10,0));
|
||||
_state = WRITING_DATA;
|
||||
};
|
||||
void Abort()
|
||||
{
|
||||
_state = ABORTING;
|
||||
};
|
||||
|
||||
|
||||
bool HasOption(std::string in)
|
||||
{
|
||||
const std::string * answer = _parser.GetOption(in);
|
||||
if(answer != NULL)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
char * GetOption(std::string in)
|
||||
{
|
||||
const std::string * answer = _parser.GetOption(in);
|
||||
if(answer != NULL)
|
||||
return (char *)answer->c_str();
|
||||
return "";
|
||||
}
|
||||
std::string GetRequestOptionString()
|
||||
{
|
||||
return _parser.GetRequestOptionString();
|
||||
}
|
||||
|
||||
static bool HttpManager_Initialize( unsigned short port);
|
||||
static Http_Request * HttpManager_GetARequest();
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // Http_Request_H_
|
214
direct/src/http/parsedhttprequest.cxx
Normal file
214
direct/src/http/parsedhttprequest.cxx
Normal file
@ -0,0 +1,214 @@
|
||||
#pragma warning(disable : 4789)
|
||||
#pragma warning(disable : 4786)
|
||||
|
||||
#include "parsedhttprequest.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline std::string & trimleft_inplace(std::string & s)
|
||||
{
|
||||
s.erase(0, s.find_first_not_of(" \t\n\r"));
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline std::string & trimright_inplace(std::string & s)
|
||||
{
|
||||
size_t idx = s.find_last_not_of(" \t\n\r");
|
||||
|
||||
if (std::string::npos == idx)
|
||||
{
|
||||
s.erase();
|
||||
}
|
||||
else
|
||||
{
|
||||
char c = s.at(idx);
|
||||
s.erase(idx, std::string::npos);
|
||||
s.append(1, c);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline std::string & trim_inplace(std::string & s)
|
||||
{
|
||||
trimleft_inplace(s);
|
||||
trimright_inplace(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
inline std::string trim_tonew(const std::string &in)
|
||||
{
|
||||
std::string ss = in;
|
||||
return trim_inplace(ss);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::string ParsedHttpRequest::deCanonicalize(std::string &inval)
|
||||
{
|
||||
std::string work("");
|
||||
unsigned int x=0;
|
||||
while (x < inval.size())
|
||||
{
|
||||
switch(inval[x])
|
||||
{
|
||||
case('+'):
|
||||
work+=' ';
|
||||
x++;
|
||||
break;
|
||||
|
||||
case('%'):
|
||||
if(x+2 < inval.size())
|
||||
{
|
||||
x++;
|
||||
char aa[5];
|
||||
char * end;
|
||||
aa[0] = inval[x++];
|
||||
aa[1] = inval[x++];
|
||||
aa[2] = '\0';
|
||||
char c = ( char ) strtoul(aa,&end,16);
|
||||
work+=c;
|
||||
}
|
||||
else
|
||||
x+=3;
|
||||
break;
|
||||
|
||||
default:
|
||||
work+=inval[x++];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return work;
|
||||
}
|
||||
|
||||
size_t ParsedHttpRequest::PullCR(std::string &src, std::string &dst)
|
||||
{
|
||||
size_t offset = src.find(' ');
|
||||
if(offset >= 0 )
|
||||
{
|
||||
dst = src.substr(0,offset);
|
||||
src = src.substr(offset+1);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
void ParsedHttpRequest::clear(void)
|
||||
{
|
||||
_RequestType = "";
|
||||
_parameters.clear();
|
||||
}
|
||||
|
||||
const std::string * ParsedHttpRequest::GetOption(const std::string & query)
|
||||
{
|
||||
std::map<std::string,std::string>::iterator ii;
|
||||
ii = _parameters.find(query);
|
||||
if(ii == _parameters.end())
|
||||
return NULL;
|
||||
|
||||
return &ii->second;
|
||||
}
|
||||
|
||||
|
||||
bool ParsedHttpRequest::GetOption(const std::string & query, std::string & out_value)
|
||||
{
|
||||
std::map<std::string,std::string>::iterator ii;
|
||||
ii = _parameters.find(query);
|
||||
if(ii == _parameters.end())
|
||||
{
|
||||
out_value = "";
|
||||
return false;
|
||||
}
|
||||
out_value = ii->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParsedHttpRequest::ParseThis(char * request)
|
||||
{
|
||||
_Raw_Text = request;
|
||||
// printf("%s\n\n",request);
|
||||
|
||||
|
||||
std::string work1(_Raw_Text);
|
||||
for(size_t pos = work1.find_first_of("\n\r\0") ; pos != std::string::npos ; pos = work1.find_first_of("\n\r\0") )
|
||||
{
|
||||
std::string line1 = work1.substr(0,pos);
|
||||
work1 = work1.substr(pos+1);
|
||||
if(line1.size() > 2)
|
||||
{
|
||||
// printf(" Line[%s]\n",line1.c_str());
|
||||
size_t i_pos = line1.find(':');
|
||||
if(i_pos != std::string::npos && i_pos > 1)
|
||||
{
|
||||
std::string noune = trim_tonew(line1.substr(0,i_pos));
|
||||
std::string verb = trim_tonew(line1.substr(i_pos+1));
|
||||
|
||||
//printf(" Noune [%s][%s]\n",noune.c_str(),verb.c_str());
|
||||
_header_Lines[noune] = verb;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Get the url for the request ..
|
||||
//
|
||||
std::string work(request);
|
||||
std::string line1 = work.substr(0,work.find_first_of("\n\r\0"));
|
||||
if(line1.size() < 4)
|
||||
return false;
|
||||
|
||||
if(PullCR(line1,_RequestType) < 3)
|
||||
return false;
|
||||
|
||||
if(PullCR(line1,_RequestText) < 1)
|
||||
return false;
|
||||
|
||||
size_t loc = (int)_RequestText.find('?');
|
||||
if(loc != std::string::npos)
|
||||
{
|
||||
_Requestoptions = _RequestText.substr(loc+1);
|
||||
_RequestText = _RequestText.substr(0,loc);
|
||||
}
|
||||
|
||||
return ProcessOptionString(_Requestoptions);
|
||||
}
|
||||
|
||||
std::string & ParsedHttpRequest::GetRequestURL(void)
|
||||
{
|
||||
return _RequestText;
|
||||
};
|
||||
|
||||
bool ParsedHttpRequest::ProcessOptionString(std::string str)
|
||||
{
|
||||
size_t loc;
|
||||
for(loc = str.find('&'); loc != std::string::npos; loc = str.find('&'))
|
||||
{
|
||||
std::string valset = str.substr(0,loc);
|
||||
str = str.substr(loc+1);
|
||||
if(ProcessParamSet(valset) != true)
|
||||
return false;
|
||||
}
|
||||
return ProcessParamSet(str);
|
||||
};
|
||||
|
||||
bool ParsedHttpRequest::ProcessParamSet(std::string &str)
|
||||
{
|
||||
std::string val("");
|
||||
size_t loc = str.find('=');
|
||||
|
||||
if(loc != std::string::npos)
|
||||
{
|
||||
val = str.substr(loc+1);
|
||||
str = str.substr(0,loc);
|
||||
|
||||
std::string ind1 = deCanonicalize(str);
|
||||
_parameters[ind1] = deCanonicalize(val);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
143
direct/src/http/parsedhttprequest.h
Normal file
143
direct/src/http/parsedhttprequest.h
Normal file
@ -0,0 +1,143 @@
|
||||
#ifndef __PARSEDHTTPREQUEST_GM_H__
|
||||
#define __PARSEDHTTPREQUEST_GM_H__
|
||||
|
||||
#include "string"
|
||||
#include "map"
|
||||
|
||||
|
||||
class ParsedHttpRequest
|
||||
{
|
||||
protected:
|
||||
std::string _Raw_Text;
|
||||
std::string _RequestType;
|
||||
std::string _RequestText;
|
||||
std::string _Requestoptions;
|
||||
std::string _BodyText;
|
||||
|
||||
|
||||
std::map<std::string,std::string> _parameters;
|
||||
std::map<std::string,std::string> _header_Lines;
|
||||
|
||||
std::string deCanonicalize(std::string &inval);
|
||||
size_t PullCR(std::string &src, std::string &dst);
|
||||
|
||||
public:
|
||||
void clear(void);
|
||||
const std::string GetRequestOptionString() { return _Requestoptions; };
|
||||
const std::string * GetOption(const std::string & query);
|
||||
bool GetOption(const std::string & query, std::string & out_value);
|
||||
bool ParseThis(char * request);
|
||||
std::string & GetRequestURL(void);
|
||||
const std::string & GetRawRequest(void) const { return _Raw_Text; };
|
||||
const std::string & GetRequestType(void) const { return _RequestType; };
|
||||
bool ProcessOptionString(std::string str);
|
||||
bool ProcessParamSet(std::string &str);
|
||||
|
||||
|
||||
void SetBodyText(const std::string & text)
|
||||
{
|
||||
_BodyText = text;
|
||||
}
|
||||
|
||||
const std::string & getBodyText() { return _BodyText; };
|
||||
|
||||
int getContentLength()
|
||||
{
|
||||
int answer = 0;
|
||||
std::map<std::string,std::string>::iterator ii = _header_Lines.find("Content-Length");
|
||||
if(ii != _header_Lines.end())
|
||||
answer = atol(ii->second.c_str());
|
||||
|
||||
return answer;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
class ParsedHttpResponce
|
||||
{
|
||||
std::string _Raw_Text;
|
||||
std::string _responce_header;
|
||||
|
||||
std::map<std::string,std::string> _header_Lines;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
std::string GetresponceCode()
|
||||
{
|
||||
std::string answer;
|
||||
|
||||
size_t pos = _responce_header.find_first_of(" ");
|
||||
if(pos != std::string::npos)
|
||||
answer = support::trim_tonew(_responce_header.substr(pos,100));
|
||||
|
||||
|
||||
pos = answer.find_first_of(" \t\n\r\0");
|
||||
if(pos != std::string::npos)
|
||||
answer = support::trim_tonew(answer.substr(0,pos));
|
||||
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
bool ParseThis(const std::string &responce)
|
||||
{
|
||||
_Raw_Text = responce;
|
||||
|
||||
int line_number = 0;
|
||||
std::string work1(_Raw_Text);
|
||||
for(size_t pos = work1.find_first_of("\n\r\0") ; pos != std::string::npos ; pos = work1.find_first_of("\n\r\0") )
|
||||
{
|
||||
std::string line1 = work1.substr(0,pos);
|
||||
work1 = work1.substr(pos+1);
|
||||
if(line1.size() > 2)
|
||||
{
|
||||
|
||||
if(line_number == 0 && line1.substr(0,4) == "HTTP")
|
||||
{
|
||||
// the first line...
|
||||
_responce_header = line1;
|
||||
// printf("[%s]\n",line1.c_str());
|
||||
}
|
||||
|
||||
size_t i_pos = line1.find(':');
|
||||
if(i_pos != std::string::npos && i_pos > 1)
|
||||
{
|
||||
std::string noune = support::trim_tonew(line1.substr(0,i_pos));
|
||||
std::string verb = support::trim_tonew(line1.substr(i_pos+1));
|
||||
_header_Lines[noune] = verb;
|
||||
}
|
||||
line_number++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return !_responce_header.empty();
|
||||
}
|
||||
|
||||
size_t PullCR(std::string &src, std::string &dst)
|
||||
{
|
||||
size_t offset = src.find(' ');
|
||||
if(offset >= 0 )
|
||||
{
|
||||
dst = src.substr(0,offset);
|
||||
src = src.substr(offset+1);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
int getContentLength()
|
||||
{
|
||||
int answer = 0;
|
||||
std::map<std::string,std::string>::iterator ii = _header_Lines.find("Content-Length");
|
||||
if(ii != _header_Lines.end())
|
||||
answer = atol(ii->second.c_str());
|
||||
|
||||
return answer;
|
||||
};
|
||||
|
||||
};
|
||||
*/
|
||||
|
||||
#endif //__PARSEDHTTPREQUEST_GM_H__
|
||||
|
48
direct/src/http/ringbuffer_slide.h
Normal file
48
direct/src/http/ringbuffer_slide.h
Normal file
@ -0,0 +1,48 @@
|
||||
#ifndef __RINGBUFFER_GM_H__
|
||||
#define __RINGBUFFER_GM_H__
|
||||
////////////////////////////////////////////
|
||||
|
||||
// RHH
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : GmRingBuffer
|
||||
// Description : This is an implemention of the membuffer with ring
|
||||
// buffer interface on it....
|
||||
//
|
||||
// Main target right know is base class for network
|
||||
// stream buffering both input and output
|
||||
//
|
||||
// see BufferedReader_Gm
|
||||
// BufferedWriter_Gm
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#include "membuffer.h"
|
||||
class RingBuffer_Slide : protected MemBuffer
|
||||
{
|
||||
protected:
|
||||
size_t _StartPos;
|
||||
size_t _EndPos;
|
||||
inline char * GetMessageHead(void);
|
||||
inline char * GetBufferOpen(void);
|
||||
inline void ForceWindowSlide(void);
|
||||
#define FastGetMessageHead() (_Buffer+_StartPos)
|
||||
#define FastAmountBeffered() (_EndPos - _StartPos)
|
||||
|
||||
inline bool PutFast(const char * data, size_t len);
|
||||
|
||||
public:
|
||||
inline size_t AmountBuffered(void);
|
||||
inline size_t BufferAvailabe(void);
|
||||
inline void ResetContent(void);
|
||||
|
||||
inline RingBuffer_Slide(size_t in_size = 4096);
|
||||
inline void FullCompress(void);
|
||||
inline void Compress(void);
|
||||
inline bool Put(const char * data, size_t len);
|
||||
inline bool Get(char * data, size_t len);
|
||||
};
|
||||
|
||||
#include "ringbuffer_slide.i"
|
||||
|
||||
#endif //__RINGBUFFER_GM_H__
|
||||
|
||||
|
187
direct/src/http/ringbuffer_slide.i
Normal file
187
direct/src/http/ringbuffer_slide.i
Normal file
@ -0,0 +1,187 @@
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::GetMessageHead
|
||||
// Description : This will get a pointer to the fist undelivered data in buffer
|
||||
// Return type : char *
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline char * RingBuffer_Slide::GetMessageHead(void)
|
||||
{
|
||||
return _Buffer+_StartPos;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::GetBufferOpen
|
||||
// Description : This will get the first writabe section of the buffer space
|
||||
// Return type :
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline char * RingBuffer_Slide::GetBufferOpen(void)
|
||||
{
|
||||
return _Buffer+_EndPos;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::ForceWindowSlide
|
||||
// Description : Will force a compression of data // shift left to start position
|
||||
// Return type : inline void
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline void RingBuffer_Slide::ForceWindowSlide(void)
|
||||
{
|
||||
size_t len = AmountBuffered();
|
||||
if(len > 0 && _StartPos != 0) // basic flush left..
|
||||
{
|
||||
memmove(_Buffer,GetMessageHead(),len);
|
||||
_StartPos = 0;
|
||||
_EndPos = len;
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::AmountBuffered
|
||||
// Description : Will report the number of unread chars in buffer
|
||||
// Return type : int
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline size_t RingBuffer_Slide::AmountBuffered(void)
|
||||
{
|
||||
return _EndPos - _StartPos;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::BufferAvailabe
|
||||
// Description : Will report amount of data that is contiguas that can be writen at
|
||||
// the location returned by GetBufferOpen
|
||||
// Return type : inline int
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline size_t RingBuffer_Slide::BufferAvailabe(void)
|
||||
{
|
||||
return GetBufferSize() - _EndPos;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::ResetContent
|
||||
// Description : Throw away all inread information
|
||||
// Return type : void
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
void RingBuffer_Slide::ResetContent(void)
|
||||
{
|
||||
_StartPos = 0;
|
||||
_EndPos = 0;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::RingBuffer_Slide
|
||||
// Description :
|
||||
// Return type : inline
|
||||
// Argument : int in_size
|
||||
//////////////////////////////////////////////////////////
|
||||
inline RingBuffer_Slide::RingBuffer_Slide(size_t in_size) : MemBuffer(in_size)
|
||||
{
|
||||
_EndPos = 0;
|
||||
_StartPos = 0;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::FullCompress
|
||||
// Description : Force a compress of the data
|
||||
// Return type : inline void
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline void RingBuffer_Slide::FullCompress(void)
|
||||
{
|
||||
if(_StartPos == _EndPos)
|
||||
{
|
||||
_StartPos = 0;
|
||||
_EndPos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ForceWindowSlide();
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::Compress
|
||||
// Description : Try and do a intelegent compress of the data space
|
||||
// the algorithem is really stupid right know.. just say if i have
|
||||
// read past 1/2 my space do a compress...Im open for sugestions
|
||||
//
|
||||
//
|
||||
// Return type : inline void
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline void RingBuffer_Slide::Compress(void)
|
||||
{
|
||||
if(_StartPos == _EndPos)
|
||||
{
|
||||
_StartPos = 0;
|
||||
_EndPos = 0;
|
||||
}
|
||||
else if(_StartPos >= GetBufferSize() / 2)
|
||||
{
|
||||
ForceWindowSlide();
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::Put
|
||||
// Description : Adds Data to a ring Buffer
|
||||
// Will do a compress if needed so pointers suplied by Get Call are no longer valide
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : char * data
|
||||
// Argument : int len
|
||||
//////////////////////////////////////////////////////////
|
||||
inline bool RingBuffer_Slide::Put(const char * data, size_t len)
|
||||
{
|
||||
bool answer = false;
|
||||
|
||||
if(len > BufferAvailabe() )
|
||||
Compress();
|
||||
|
||||
if(len <= BufferAvailabe() )
|
||||
{
|
||||
memcpy(GetBufferOpen(),data,len);
|
||||
_EndPos += len;
|
||||
answer = true;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::PutFast
|
||||
// Description :
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : const char * data
|
||||
// Argument : int len
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool RingBuffer_Slide::PutFast(const char * data, size_t len)
|
||||
{
|
||||
// no checking be carefull
|
||||
memcpy(GetBufferOpen(),data,len); // should i be using memcopy..
|
||||
_EndPos += len;
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer_Slide::Get
|
||||
// Description : will copy the data ..
|
||||
// false indicates not enogh data to read .. sorry...
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : char * data
|
||||
// Argument : int len
|
||||
//////////////////////////////////////////////////////////
|
||||
inline bool RingBuffer_Slide::Get(char * data, size_t len)
|
||||
{
|
||||
bool answer = false;
|
||||
|
||||
if(len <= AmountBuffered() )
|
||||
{
|
||||
memcpy(data,GetMessageHead(),len);
|
||||
_StartPos += len;
|
||||
Compress();
|
||||
answer = true;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
31
direct/src/http/strtargetbuffer.h
Normal file
31
direct/src/http/strtargetbuffer.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef StrTargetBuffer_h_
|
||||
#define StrTargetBuffer_h_
|
||||
|
||||
#include <string>
|
||||
|
||||
class StrTargetBuffer : public std::string
|
||||
{
|
||||
size_t _target_size;
|
||||
public:
|
||||
StrTargetBuffer() : std::string(), _target_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
size_t left_to_fill()
|
||||
{
|
||||
if(_target_size < size())
|
||||
return 0;
|
||||
|
||||
return _target_size - size();
|
||||
};
|
||||
|
||||
void SetDataSize(size_t target)
|
||||
{
|
||||
_target_size = target;
|
||||
}
|
||||
|
||||
size_t GetTargetSize() { return _target_size; };
|
||||
};
|
||||
|
||||
#endif // StrTargetBuffer_h_
|
||||
|
Loading…
x
Reference in New Issue
Block a user