mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-20 14:10:39 -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