New nativenet stuff .. expermental
This commit is contained in:
parent
e49cc9f973
commit
aa95cc3aff
|
|
@ -172,6 +172,36 @@ append_data(const void *data, size_t size) {
|
|||
}
|
||||
}
|
||||
|
||||
void Datagram::assign(const void *data, size_t size)
|
||||
{
|
||||
nassertv((int)size >= 0);
|
||||
|
||||
if (_data == (uchar *)NULL) {
|
||||
// Create a new array.
|
||||
_data = PTA_uchar::empty_array(0);
|
||||
|
||||
} else if (_data.get_ref_count() != 1) {
|
||||
// Copy on write.
|
||||
PTA_uchar new_data = PTA_uchar::empty_array(0);
|
||||
new_data.v() = _data.v();
|
||||
_data = new_data;
|
||||
}
|
||||
|
||||
// Now append the data.
|
||||
|
||||
// It is very important that we *don't* do this reserve() operation.
|
||||
// This actually slows it down on Windows, which takes the reserve()
|
||||
// request as a fixed size the array should be set to (!) instead of
|
||||
// as a minimum size to guarantee. This forces the array to
|
||||
// reallocate itself with *every* call to append_data!
|
||||
// _data.reserve(_data.size() + size);
|
||||
|
||||
_data.clear();
|
||||
const uchar *source = (const uchar *)data;
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
_data.v().push_back(source[i]);
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function : output
|
||||
// Access : Public
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ PUBLISHED:
|
|||
void append_data(const void *data, size_t size);
|
||||
INLINE void append_data(const string &data);
|
||||
|
||||
void assign(const void *data, size_t size);
|
||||
|
||||
INLINE string get_message() const;
|
||||
INLINE const void *get_data() const;
|
||||
INLINE size_t get_length() const;
|
||||
|
|
@ -112,6 +114,7 @@ private:
|
|||
|
||||
|
||||
public:
|
||||
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
|
|
@ -125,6 +128,7 @@ public:
|
|||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -69,3 +69,55 @@ INLINE const void *NativeNumericData::
|
|||
get_data() const {
|
||||
return _source;
|
||||
}
|
||||
|
||||
/////////////////////
|
||||
// this is for a intel compile .. it is native format and it is
|
||||
// readable off word boundries
|
||||
/////////////////////////
|
||||
inline void TS_SetVal1(const PN_int8 * src, PN_int8 *dst)
|
||||
{
|
||||
*dst = *src;
|
||||
}
|
||||
inline void TS_SetVal2(const char * src, char *dst)
|
||||
{
|
||||
*(reinterpret_cast<PN_int16 *>(dst)) = *(reinterpret_cast <const PN_int16 *>(src));
|
||||
}
|
||||
|
||||
inline void TS_SetVal4(const char * src, char *dst)
|
||||
{
|
||||
*(reinterpret_cast <PN_int32 *>(dst)) = *(reinterpret_cast <const PN_int32 *>(src));
|
||||
}
|
||||
|
||||
|
||||
inline void TS_SetVal8(const char * src, char *dst)
|
||||
{
|
||||
*(reinterpret_cast<PN_int64 *>(dst)) = *(reinterpret_cast<const PN_int64 *>(src));
|
||||
}
|
||||
|
||||
template<class type> inline type TS_GetInteger(type &val,const char * _src)
|
||||
{
|
||||
val = *(reinterpret_cast <const type *>(_src));
|
||||
return val;
|
||||
}
|
||||
|
||||
template<class type> inline type TS_GetIntegerIncPtr(type &val,char *& _src)
|
||||
{
|
||||
val = *(reinterpret_cast <const type *>(_src));
|
||||
_src+= sizeof(type);
|
||||
return val;
|
||||
}
|
||||
|
||||
template<class type> inline void TS_AddIntegerIncPtr(type val, char *& _dst)
|
||||
{
|
||||
*(reinterpret_cast <type *>(_dst)) = val;
|
||||
_dst+= sizeof(type);
|
||||
}
|
||||
|
||||
template<class type> inline void TS_AddInteger(type val, char * _dst)
|
||||
{
|
||||
*(reinterpret_cast <type *>(_dst)) = val;
|
||||
}
|
||||
|
||||
#define TS_GetDirect(TT,SS) *((TT *)(SS))
|
||||
#define TS_GetDirectIncPtr(TT,SS) { _ptr += sizeof(TT); return *((TT *)(SS -sizeof(TT))); }
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
#define LOCAL_LIBS express pandabase
|
||||
|
||||
#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
|
||||
dtoolutil:c dtoolbase:c dtool:m
|
||||
|
||||
#define USE_PACKAGES net
|
||||
|
||||
#begin lib_target
|
||||
#define TARGET net1
|
||||
|
||||
#define COMBINED_SOURCES $[TARGET]_composite1.cxx
|
||||
|
||||
#define SOURCES \
|
||||
buffered_datagramconnection.h ringbuffer.h socket_ip.h socket_tcp_listen.h \
|
||||
time_accumulator.h time_out.h buffered_datagramreader.h socket_address.h \
|
||||
socket_portable.h time_base.h time_span.h buffered_datagramwriter.h \
|
||||
socket_base.h socket_selector.h socket_udp_incoming.h time_clock.h \
|
||||
membuffer.h socket_fdset.h socket_tcp.h socket_udp_outgoing.h time_general.h
|
||||
|
||||
|
||||
#define INCLUDED_SOURCES \
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
buffered_datagramconnection.h ringbuffer.h socket_ip.h socket_tcp_listen.h \
|
||||
time_accumulator.h time_out.h buffered_datagramreader.h socket_address.h \
|
||||
socket_portable.h time_base.h time_span.h buffered_datagramwriter.h \
|
||||
socket_base.h socket_selector.h socket_udp_incoming.h time_clock.h \
|
||||
membuffer.h socket_fdset.h socket_tcp.h socket_udp_outgoing.h time_general.h
|
||||
|
||||
|
||||
#define IGATESCAN all
|
||||
|
||||
#end lib_target
|
||||
|
||||
|
|
@ -0,0 +1,325 @@
|
|||
#ifndef __NONECLOCKING_CONNECTTION_H_
|
||||
#define __NONECLOCKING_CONNECTTION_H_
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Ok here is the base behavior..
|
||||
// A message IO engin that is Smart enough to Do
|
||||
//
|
||||
// 1. Non Blocking Connect .. and Buffer the writes if needed
|
||||
// 2. Handle 1 to N targets for the connection..
|
||||
//
|
||||
// 3. Handle Framing and Unframing properly ..
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#include "dtoolbase.h"
|
||||
#include <vector>
|
||||
#include "socket_base.h"
|
||||
//#include "../express/datagram.h"
|
||||
#include "datagram.h"
|
||||
|
||||
#include "buffered_datagramreader.h"
|
||||
#include "buffered_datagramwriter.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// there are 3 states
|
||||
//
|
||||
// 1. Socket not even assigned,,,,
|
||||
// 2. Socket Assigned and trying to get a active connect open
|
||||
// 3. Socket is open and writable.. ( Fully powered up )...
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
class Buffered_DatagramConnection : protected Socket_TCP
|
||||
{
|
||||
private:
|
||||
struct AddressQueue : private std::vector<Socket_Address> // this is used to do a round robin for addres to connect to ..
|
||||
{
|
||||
size_t _active_index;
|
||||
bool GetNext(Socket_Address &out)
|
||||
{
|
||||
size_t the_size = size();
|
||||
if(the_size == 0)
|
||||
return false;
|
||||
|
||||
if(_active_index >= the_size || _active_index < 0)
|
||||
_active_index = 0;
|
||||
out = (*this)[_active_index++];
|
||||
return true;
|
||||
}
|
||||
|
||||
void clear() { std::vector<Socket_Address>::clear(); };
|
||||
void push_back(Socket_Address &address)
|
||||
{
|
||||
iterator ii;
|
||||
for(ii = begin(); ii != end(); ii++)
|
||||
if(*ii == address)
|
||||
return;
|
||||
std::vector<Socket_Address>::push_back(address);
|
||||
}
|
||||
|
||||
size_t size() { return std::vector<Socket_Address>::size(); };
|
||||
};
|
||||
protected:
|
||||
// c++ upcals for
|
||||
virtual void PostConnect(void) { };
|
||||
virtual void NewWriteBuffer(void) { };
|
||||
///////////////////////////////////////////
|
||||
inline void ClearAll(void);
|
||||
inline bool DoConnect(void); // all the real state magic is in here ...
|
||||
inline bool SendMessageBufferOnly(Datagram &msg); // do not use this .. this is a way for the the COnnecting UPcall to drop messages in queue first..
|
||||
public:
|
||||
PUBLISHED:
|
||||
inline Buffered_DatagramConnection(bool do_blocking_writes, int rbufsize, int wbufsize, int write_flush_point) ;
|
||||
virtual ~Buffered_DatagramConnection(void) ;
|
||||
// the reason thsi all exists
|
||||
inline bool SendMessage(Datagram &msg);
|
||||
inline bool GetMessage(Datagram **val);
|
||||
inline Datagram * GetMessage();
|
||||
inline bool Flush(void);
|
||||
inline void Reset(void);
|
||||
|
||||
// address queue stuff
|
||||
inline size_t AddressQueueSize() { return _Addresslist.size(); };
|
||||
inline void AddAddress(Socket_Address &inadr);
|
||||
inline void ClearAddresses(void);
|
||||
private:
|
||||
Buffered_DatagramWriter _Writer; // buffered writing
|
||||
Buffered_DatagramReader _Reader; // buffered reader
|
||||
AddressQueue _Addresslist; // the location of the round robin address list
|
||||
Socket_Address _Adddress; // the conection address ( active one from list being used)
|
||||
// the local datagram store..
|
||||
Datagram _Msg; // The temp storage for a upcalled message
|
||||
////////////////////////////////
|
||||
// connection state engine /////
|
||||
Time_Out _LastConnectTry; // A Recycle Timer to Stop Connection/spaming..
|
||||
bool _tryingToOpen; // this is a flag that say we are in state 2
|
||||
// state 1 = Active() == false,,
|
||||
// state 2 = Active() == true and _tryingToOpen == true;
|
||||
// state 3 = Active() == true and _tryingToOpen == flase;
|
||||
|
||||
friend class Buffered_DatagramReader;
|
||||
friend class Buffered_DatagramWriter;
|
||||
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Buffered_DatagramConnection::ClearAll
|
||||
// Description : used to do a full reset of buffers
|
||||
//
|
||||
// Return type : inline void
|
||||
// Argument : void
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline void Buffered_DatagramConnection::ClearAll(void)
|
||||
{
|
||||
Close();
|
||||
_tryingToOpen = false;
|
||||
_Writer.ReSet();
|
||||
_Reader.ReSet();
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Buffered_DatagramConnection::DoConnect
|
||||
// Description : This is the function thah does the conection for us
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : void
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Buffered_DatagramConnection::DoConnect(void)
|
||||
{
|
||||
if(Active() != true)
|
||||
{
|
||||
if(_LastConnectTry.Expired() != true)
|
||||
return false;
|
||||
|
||||
if(!_Addresslist.GetNext(_Adddress)) // lookup the proper value...
|
||||
return false;
|
||||
|
||||
if(ActiveOpenNonBlocking(_Adddress) == true)
|
||||
{
|
||||
_LastConnectTry.ReStart();
|
||||
_tryingToOpen = true; // set the flag indicating we are trying to open up
|
||||
SetNonBlocking(); // maybe should be blocking?
|
||||
SetSendBufferSize(1024*50); // we need to hand tune these for the os we are using
|
||||
SetRecvBufferSize(1024*50);
|
||||
NewWriteBuffer();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(_tryingToOpen) // okay handle the i am connecting state....
|
||||
{
|
||||
Socket_fdset fdset;
|
||||
fdset.setForSocket(*this);
|
||||
Socket_Selector selector;
|
||||
if(selector.WaitFor_All(fdset,0) >0)
|
||||
{
|
||||
_tryingToOpen = false;
|
||||
if(selector._error.IsSetFor(*this) == true) // means we are in errorconnected. else writable
|
||||
{
|
||||
ClearAll();
|
||||
return false; // error on connect
|
||||
}
|
||||
PostConnect();
|
||||
return true; // just got connected
|
||||
}
|
||||
return true; // still connecting
|
||||
}
|
||||
return true;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Buffered_DatagramConnection::~Buffered_DatagramConnection
|
||||
// Description :
|
||||
//
|
||||
// Return type : inline
|
||||
// Argument : void
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline Buffered_DatagramConnection::~Buffered_DatagramConnection(void)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Buffered_DatagramConnection::Buffered_DatagramConnection
|
||||
// Description :
|
||||
//
|
||||
// Return type : inline
|
||||
// Argument : bool do_blocking_writes
|
||||
// Argument : int rbufsize
|
||||
// Argument : int wbufsize
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline Buffered_DatagramConnection::Buffered_DatagramConnection(bool do_blocking_writes, int rbufsize, int wbufsize, int write_flush_point)
|
||||
: _Writer(do_blocking_writes,wbufsize,write_flush_point) , _Reader(rbufsize), _Msg() , _LastConnectTry(Time_Span(0,0,0,1,0))
|
||||
{
|
||||
_LastConnectTry.ForceToExpired();
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Buffered_DatagramConnection::SendMessage
|
||||
// Description : send the message
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : DataGram &msg
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Buffered_DatagramConnection::SendMessage(Datagram &msg)
|
||||
{
|
||||
if(DoConnect() == true)
|
||||
{
|
||||
// printf(" DO SendMessage %d\n",msg.get_length());
|
||||
int val = 0;
|
||||
if(_tryingToOpen) // indicates we are in the process of opening the connection ....just buffer
|
||||
{
|
||||
val = _Writer.AddData(msg.get_data(),msg.get_length());
|
||||
}
|
||||
else
|
||||
{
|
||||
val = _Writer.AddData(msg.get_data(),msg.get_length(),*this);
|
||||
}
|
||||
if(val >= 0)
|
||||
return true;
|
||||
|
||||
// LOGWARNING("Buffered_DatagramConnection::SendMessage->Error On Write--Out Buffer = %d",_Writer.AmountBuffered());
|
||||
ClearAll();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool Buffered_DatagramConnection::SendMessageBufferOnly(Datagram &msg)
|
||||
{
|
||||
int val = _Writer.AddData(msg.get_data(),msg.get_length());
|
||||
if(val >= 0)
|
||||
return true;
|
||||
|
||||
// LOGWARNING("Buffered_DatagramConnection::SendMessageBufferOnly->Error On Write--Out Buffer = %d",_Writer.AmountBuffered());
|
||||
ClearAll();
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Buffered_DatagramConnection::Init
|
||||
// Description : must be called to set value to the server
|
||||
//
|
||||
// Return type : inline void
|
||||
// Argument : Socket_Address &inadr
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline void Buffered_DatagramConnection::AddAddress(Socket_Address &inadr)
|
||||
{
|
||||
_Addresslist.push_back(inadr);
|
||||
}
|
||||
|
||||
inline void Buffered_DatagramConnection::ClearAddresses(void)
|
||||
{
|
||||
_Addresslist.clear();
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Buffered_DatagramConnection::GetMessage
|
||||
// Description : read a message
|
||||
//
|
||||
// false means something bad happened..
|
||||
//
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : DataGram **val
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Buffered_DatagramConnection::GetMessage(Datagram **val)
|
||||
{
|
||||
*val = NULL;
|
||||
if(DoConnect() == true && _tryingToOpen != true)
|
||||
{
|
||||
int ans1 = _Reader.PumpMessageReader(_Msg,*this);
|
||||
if(ans1 <0)
|
||||
{
|
||||
// LOGWARNING("Buffered_DatagramConnection::GetMessage->Error On PumpMessageReader--Out Buffer = %d",_Writer.AmountBuffered());
|
||||
ClearAll();
|
||||
return false;
|
||||
}
|
||||
else if (ans1 == 1)
|
||||
{
|
||||
*val = &_Msg;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline Datagram * Buffered_DatagramConnection::GetMessage()
|
||||
{
|
||||
Datagram *out = NULL;
|
||||
GetMessage(&out);
|
||||
return out;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Buffered_DatagramConnection::Flush
|
||||
// Description : flush all wrightes
|
||||
//
|
||||
// Return type : bool
|
||||
// Argument : void
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Buffered_DatagramConnection::Flush(void)
|
||||
{
|
||||
if(Active() == true && _tryingToOpen != true )
|
||||
{
|
||||
int flush_resp = _Writer.FlushNoBlock(*this);
|
||||
if(flush_resp < 0)
|
||||
{
|
||||
// LOGWARNING("Buffered_DatagramConnection::Flush->Error On Flush [%d]",GetLastError());
|
||||
// LOGWARNING("Buffered_DatagramConnection::Flush->Error ..Write--Out Buffer = %d",_Writer.AmountBuffered());
|
||||
ClearAll();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Buffered_DatagramConnection::Flush
|
||||
// Description : Reset
|
||||
//
|
||||
// Return type : void
|
||||
// Argument : void
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline void Buffered_DatagramConnection::Reset()
|
||||
{
|
||||
ClearAll();
|
||||
};
|
||||
|
||||
|
||||
#endif //__NONECLOCKING_CONNECTTION_H_
|
||||
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
#ifndef __BUFFEREDREADER_GM_H__
|
||||
#define __BUFFEREDREADER_GM_H__
|
||||
|
||||
#include "ringbuffer.h"
|
||||
#include "datagram.h"
|
||||
|
||||
inline unsigned short GetUnsignedShort(char * in)
|
||||
{
|
||||
return *((unsigned short *)in);
|
||||
};
|
||||
|
||||
|
||||
class Buffered_DatagramReader : protected RingBuffer
|
||||
{
|
||||
inline bool GetMessageFromBuffer(Datagram &inmsg);
|
||||
public:
|
||||
inline Buffered_DatagramReader(int in_size = 8192) ;
|
||||
inline void ReSet(void);
|
||||
//
|
||||
// SOCK_TYPE is used to allow for
|
||||
// abstract socket type to be used ..
|
||||
// see socket_tcp and socket_ssl
|
||||
|
||||
template < class SOCK_TYPE>
|
||||
inline int PumpMessageReader(Datagram &inmsg, SOCK_TYPE &sck)
|
||||
{
|
||||
if(GetMessageFromBuffer(inmsg) == true)
|
||||
return 1;
|
||||
int rp = ReadPump(sck);
|
||||
if(rp == 0)
|
||||
return 0;
|
||||
|
||||
if(rp < 1)
|
||||
return -1;
|
||||
if(GetMessageFromBuffer(inmsg) == true)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
template < class SOCK_TYPE>
|
||||
inline int ReadPump(SOCK_TYPE &sck)
|
||||
{
|
||||
int answer = 0;
|
||||
size_t readsize = BufferAvailabe();
|
||||
|
||||
if(readsize < 1)
|
||||
{
|
||||
Compress();
|
||||
readsize = BufferAvailabe();
|
||||
}
|
||||
|
||||
if(readsize > 0)
|
||||
{
|
||||
char * ff = GetBufferOpen();
|
||||
int gotbytes = sck.RecvData(ff,(int)readsize);
|
||||
if(gotbytes < 0) // some error
|
||||
{
|
||||
int er = GETERROR();
|
||||
if(!sck.ErrorIs_WouldBlocking(gotbytes) )
|
||||
{
|
||||
answer = -3; // hard error ?
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
answer = -2;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
};
|
||||
|
||||
#include "buffered_datagramreader.i"
|
||||
|
||||
#endif //__BUFFEREDREADER_GM_H__
|
||||
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Buffered_DatagramReader::GetMessageInplace
|
||||
// Description : A function that will peal a core message of the input buffer
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : CoreMessage &inmsg
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Buffered_DatagramReader::GetMessageFromBuffer(Datagram &inmsg)
|
||||
{
|
||||
bool answer = false;
|
||||
size_t DataAvail = FastAmountBeffered();
|
||||
if(DataAvail >= sizeof(short))
|
||||
{
|
||||
char *ff = FastGetMessageHead();
|
||||
unsigned short len=GetUnsignedShort(ff);
|
||||
len += sizeof(unsigned short);
|
||||
if(len <= DataAvail)
|
||||
{
|
||||
inmsg.assign(ff,len-2);
|
||||
_StartPos += len;
|
||||
answer = true;
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Buffered_DatagramReader::Buffered_DatagramReader
|
||||
// Description : constructore .. passes size up to ring buffer
|
||||
//
|
||||
// Return type : inline
|
||||
// Argument : int in_size
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline Buffered_DatagramReader::Buffered_DatagramReader(int in_size) : RingBuffer(in_size)
|
||||
{
|
||||
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Buffered_DatagramReader::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 Buffered_DatagramReader::ReSet(void)
|
||||
{
|
||||
ResetContent();
|
||||
}
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
#ifndef __BufferedWriter_H__
|
||||
#define __BufferedWriter_H__
|
||||
|
||||
#include "ringbuffer.h"
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : Buffered_DatagramWriter
|
||||
// Description : This is the buffered writer.. it is used to buffer up
|
||||
// Coremessages and arbitrary data..
|
||||
//
|
||||
// GmCoreMessage
|
||||
//
|
||||
//
|
||||
// You must commit all rights to a socket with flush and
|
||||
// flush may be called internall if the buffersize is about
|
||||
// to overrun.. This class does guaranty no partial message
|
||||
// rights at least to the TCP layer..
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class Buffered_DatagramWriter : public RingBuffer
|
||||
{
|
||||
bool _are_we_going_to_block_on_write;
|
||||
int _flush_point;
|
||||
public:
|
||||
inline void ReSet(void); // destroy all buffered data
|
||||
|
||||
Buffered_DatagramWriter(bool do_blocking, size_t in_size , int in_flush_point = -1);
|
||||
inline int AddData(const void * data, size_t len, Socket_TCP &sck);
|
||||
inline int AddData(const void * data, size_t len);
|
||||
// THE FUNCTIONS THAT TAKE A SOCKET NEED TO BE TEMPLATED TO WORK..
|
||||
|
||||
template < class SOCK_TYPE>
|
||||
int FlushNoBlock(SOCK_TYPE &sck) // this is the ugly part
|
||||
{
|
||||
int answer = 0;
|
||||
size_t Writesize = AmountBuffered();
|
||||
|
||||
if(Writesize > 0)
|
||||
{
|
||||
int Writen = sck.SendData(GetMessageHead(),(int)Writesize);
|
||||
if(Writen > 0)
|
||||
{
|
||||
_StartPos += Writen;
|
||||
FullCompress();
|
||||
if(AmountBuffered() > 0) // send 0 if empty else send 1 for more to do
|
||||
answer = 1;
|
||||
}
|
||||
else if(Writen < 0)
|
||||
{
|
||||
if(!sck.ErrorIs_WouldBlocking(Writen))
|
||||
answer = -1;
|
||||
else
|
||||
answer = 1; // 1 = more to do.....
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
};
|
||||
|
||||
|
||||
template < class SOCK_TYPE>
|
||||
inline int Flush(SOCK_TYPE &sck)
|
||||
{
|
||||
int answer = 0;
|
||||
size_t Writesize = AmountBuffered();
|
||||
|
||||
if(Writesize > 0)
|
||||
{
|
||||
int Writen = sck.SendData(GetMessageHead(),(int)Writesize);
|
||||
if(_are_we_going_to_block_on_write == true && Writen < 0 && sck.ErrorIs_WouldBlocking(Writen) == TRUE)
|
||||
{
|
||||
//sck.SetBlocking();
|
||||
Writen = sck.SendData(GetMessageHead(),(int)Writesize);
|
||||
//sck.SetNonBlocking();
|
||||
}
|
||||
|
||||
|
||||
if(Writen > 0)
|
||||
{
|
||||
_StartPos += Writen;
|
||||
FullCompress();
|
||||
if(AmountBuffered() > 0) // send 0 if empty else send 1 for more to do
|
||||
answer = 1;
|
||||
}
|
||||
else if(Writen < 0)
|
||||
{
|
||||
if(sck.ErrorIs_WouldBlocking(Writen) != TRUE)
|
||||
answer = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return answer;
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// Function name : Buffered_DatagramWriter::ReSet
|
||||
// Description : used to clear the buffrers ...
|
||||
// use of this in mid stream is a very bad thing as
|
||||
// you can not guarany network writes are message alligned
|
||||
// Return type : void
|
||||
///////////////////////////////////////////////////////
|
||||
inline void Buffered_DatagramWriter::ReSet(void)
|
||||
{
|
||||
ResetContent();
|
||||
}
|
||||
////////////////////////////////////////////////
|
||||
// Buffered_DatagramWriter::Buffered_DatagramWriter
|
||||
//
|
||||
//
|
||||
////////////////////////////////////////////////
|
||||
inline Buffered_DatagramWriter::Buffered_DatagramWriter(bool do_blocking, size_t in_size , int in_flush_point) : RingBuffer(in_size)
|
||||
{
|
||||
_flush_point = in_flush_point;
|
||||
_are_we_going_to_block_on_write = do_blocking;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Buffered_DatagramWriter::AddData
|
||||
// Description :
|
||||
// Return type : inline int
|
||||
// Argument : const void * data
|
||||
// Argument : int len
|
||||
// Argument : Socket_TCP &sck
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int Buffered_DatagramWriter::AddData(const void * data, size_t len, Socket_TCP &sck)
|
||||
{
|
||||
int answer = 0;
|
||||
|
||||
if(len > BufferAvailabe())
|
||||
answer = Flush(sck);
|
||||
|
||||
if(answer >= 0)
|
||||
answer = AddData(data,len);
|
||||
|
||||
if(answer >= 0 && _flush_point != -1)
|
||||
if(_flush_point < (int)AmountBuffered())
|
||||
if(Flush(sck) < 0)
|
||||
answer = -1;
|
||||
|
||||
return answer;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Buffered_DatagramWriter::AddData
|
||||
// Description :
|
||||
// Return type : inline int
|
||||
// Argument : const char * data
|
||||
// Argument : int len
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int Buffered_DatagramWriter::AddData(const void * data, size_t len)
|
||||
{
|
||||
int answer = -1;
|
||||
if(BufferAvailabe() > len+2)
|
||||
{
|
||||
unsigned short len1(len);
|
||||
TS_GetInteger(len1,(char *)&len1);
|
||||
if(Put((char *)&len1,sizeof(len1)) == true)
|
||||
{
|
||||
if(Put((char *)data,len) == true)
|
||||
{
|
||||
answer = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return answer;
|
||||
}
|
||||
#endif //__BufferedWriter_H__
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
#ifndef __MEMBUFFER_GM_H__
|
||||
#define __MEMBUFFER_GM_H__
|
||||
// RHH
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : GmMemBuf
|
||||
// Description : this a base class designed to be used to for items that will
|
||||
// share portions of a memorty buufer and want to avoid copying the data
|
||||
//
|
||||
// Use if the class wants ot allow for refrence in place of data arrays..
|
||||
// ** be carefull could be dangerous **
|
||||
//
|
||||
// GmCoreMessage
|
||||
// GmRingBuffer
|
||||
//
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class MemBuffer
|
||||
{
|
||||
public:
|
||||
inline MemBuffer(void);
|
||||
inline MemBuffer(size_t len);
|
||||
inline MemBuffer(char * data, size_t len);
|
||||
virtual ~MemBuffer();
|
||||
inline void SetBuffer(char * data, size_t len);
|
||||
inline void GrowBuffer(size_t len);
|
||||
inline size_t GetBufferSize(void ) const;
|
||||
inline char * GetBuffer(void);
|
||||
inline const char * GetBuffer(void) const;
|
||||
inline bool InBufferRange(char * );
|
||||
protected:
|
||||
bool _BufferLocal; // indicates responsibility of managment of the data
|
||||
size_t _BufferLen; // the length of the data
|
||||
char * _Buffer; // the data
|
||||
|
||||
inline void ClearBuffer(void);
|
||||
inline void AllocBuffer(size_t len);
|
||||
};
|
||||
|
||||
|
||||
#include "membuffer.i"
|
||||
|
||||
|
||||
#endif //__MEMBUFFER_GM_H__
|
||||
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
#define MEMBUF_THRASH_SIZE 25
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : MemBuffer::ClearBuffer
|
||||
// Description : Releases all resources(Memory USed) is locally allocated
|
||||
// Return type : inline void
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline void MemBuffer::ClearBuffer(void)
|
||||
{
|
||||
if(_BufferLocal == true)
|
||||
{
|
||||
if(_Buffer != NULL)
|
||||
delete [] _Buffer;
|
||||
|
||||
_Buffer = NULL;
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : MemBuffer::AllocBuffer
|
||||
// Description : Locally allocate a new buffer
|
||||
// Return type : inline void
|
||||
// Argument : int len
|
||||
//////////////////////////////////////////////////////////
|
||||
inline void MemBuffer::AllocBuffer(size_t len)
|
||||
{
|
||||
_Buffer = new char[len];
|
||||
_BufferLocal = true;
|
||||
_BufferLen = len;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : MemBuffer::MemBuffer
|
||||
// Description : default constructor
|
||||
// Return type :
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline MemBuffer::MemBuffer(void)
|
||||
{
|
||||
_Buffer = NULL;
|
||||
_BufferLocal = false;
|
||||
_BufferLen = 0;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : MemBuffer::MemBuffer
|
||||
// Description : Constructure to locall allocate a buffer
|
||||
// Return type :
|
||||
// Argument : int len
|
||||
//////////////////////////////////////////////////////////
|
||||
inline MemBuffer::MemBuffer(size_t len)
|
||||
{
|
||||
AllocBuffer(len);
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : MemBuffer::MemBuffer
|
||||
// Description : Constructure to use an external buffer
|
||||
// Return type :
|
||||
// Argument : char * data
|
||||
// Argument : int len
|
||||
//////////////////////////////////////////////////////////
|
||||
inline MemBuffer::MemBuffer(char * data, size_t len)
|
||||
{
|
||||
_BufferLocal = false;
|
||||
_BufferLen = len;
|
||||
_Buffer = data;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : MemBuffer::~MemBuffer
|
||||
// Description : CLean UP a mess on Deletetion
|
||||
// Return type :
|
||||
//////////////////////////////////////////////////////////
|
||||
inline MemBuffer::~MemBuffer()
|
||||
{
|
||||
ClearBuffer();
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : MemBuffer::SetBuffer
|
||||
// Description : Assigne a buffer
|
||||
// Return type : inline void
|
||||
// Argument : char * data
|
||||
// Argument : int len
|
||||
//////////////////////////////////////////////////////////
|
||||
inline void MemBuffer::SetBuffer(char * data, size_t len)
|
||||
{
|
||||
if(_BufferLocal == true)
|
||||
ClearBuffer();
|
||||
|
||||
_BufferLocal = false;
|
||||
_BufferLen = len;
|
||||
_Buffer = data;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : MemBuffer::GrowBuffer
|
||||
// Description : Grow a buffer is needed to get to a sertion size
|
||||
// No care is made here to preserve convtent unlike a vector of chars
|
||||
//
|
||||
// Return type : inline void
|
||||
// Argument : int len
|
||||
//////////////////////////////////////////////////////////
|
||||
inline void MemBuffer::GrowBuffer(size_t new_len)
|
||||
{
|
||||
if(new_len >= _BufferLen)
|
||||
{
|
||||
size_t len = new_len + MEMBUF_THRASH_SIZE;
|
||||
len = len +len;
|
||||
|
||||
char * tmp = new char[len];
|
||||
|
||||
if(_Buffer != NULL)
|
||||
memcpy(tmp,_Buffer,_BufferLen);
|
||||
|
||||
ClearBuffer();
|
||||
|
||||
_Buffer = tmp;
|
||||
_BufferLocal = true;
|
||||
_BufferLen = len;
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : MemBuffer::GetBufferSize
|
||||
// Description : Access to the BUffer Size Information
|
||||
// Return type : inline int
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline size_t MemBuffer::GetBufferSize(void ) const
|
||||
{
|
||||
return _BufferLen;
|
||||
};
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : * MemBuffer::GetBuffer
|
||||
// Description : Access to the actual BUffer
|
||||
// Return type : inline char
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline char * MemBuffer::GetBuffer(void)
|
||||
{
|
||||
return _Buffer;
|
||||
};
|
||||
inline const char * MemBuffer::GetBuffer(void) const
|
||||
{
|
||||
return _Buffer;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : MemBuffer::InBufferRange
|
||||
// Description :
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : char * inpos
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool MemBuffer::InBufferRange(char * inpos)
|
||||
{
|
||||
return (inpos >= _Buffer && inpos <= (_Buffer + _BufferLen));
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
#include "socket_base.h"
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
#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 : 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(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.i"
|
||||
|
||||
#endif //__RINGBUFFER_GM_H__
|
||||
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer::GetMessageHead
|
||||
// Description : This will get a pointer to the fist undelivered data in buffer
|
||||
// Return type : char *
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline char * RingBuffer::GetMessageHead(void)
|
||||
{
|
||||
return _Buffer+_StartPos;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer::GetBufferOpen
|
||||
// Description : This will get the first writabe section of the buffer space
|
||||
// Return type :
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline char * RingBuffer::GetBufferOpen(void)
|
||||
{
|
||||
return _Buffer+_EndPos;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer::ForceWindowSlide
|
||||
// Description : Will force a compression of data // shift left to start position
|
||||
// Return type : inline void
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline void RingBuffer::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::AmountBuffered
|
||||
// Description : Will report the number of unread chars in buffer
|
||||
// Return type : int
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline size_t RingBuffer::AmountBuffered(void)
|
||||
{
|
||||
return _EndPos - _StartPos;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer::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::BufferAvailabe(void)
|
||||
{
|
||||
return GetBufferSize() - _EndPos;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer::ResetContent
|
||||
// Description : Throw away all inread information
|
||||
// Return type : void
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
void RingBuffer::ResetContent(void)
|
||||
{
|
||||
_StartPos = 0;
|
||||
_EndPos = 0;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer::RingBuffer
|
||||
// Description :
|
||||
// Return type : inline
|
||||
// Argument : int in_size
|
||||
//////////////////////////////////////////////////////////
|
||||
inline RingBuffer::RingBuffer(size_t in_size) : MemBuffer(in_size)
|
||||
{
|
||||
_EndPos = 0;
|
||||
_StartPos = 0;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer::FullCompress
|
||||
// Description : Force a compress of the data
|
||||
// Return type : inline void
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////
|
||||
inline void RingBuffer::FullCompress(void)
|
||||
{
|
||||
if(_StartPos == _EndPos)
|
||||
{
|
||||
_StartPos = 0;
|
||||
_EndPos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ForceWindowSlide();
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer::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::Compress(void)
|
||||
{
|
||||
if(_StartPos == _EndPos)
|
||||
{
|
||||
_StartPos = 0;
|
||||
_EndPos = 0;
|
||||
}
|
||||
else if(_StartPos >= GetBufferSize() / 2)
|
||||
{
|
||||
ForceWindowSlide();
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : RingBuffer::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::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::PutFast
|
||||
// Description :
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : const char * data
|
||||
// Argument : int len
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool RingBuffer::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::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::Get(char * data, size_t len)
|
||||
{
|
||||
bool answer = false;
|
||||
|
||||
if(len <= AmountBuffered() )
|
||||
{
|
||||
memcpy(data,GetMessageHead(),len);
|
||||
_StartPos += len;
|
||||
Compress();
|
||||
answer = true;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
|
@ -0,0 +1,287 @@
|
|||
#ifndef __SOCKET_ADDRESS_H__
|
||||
#define __SOCKET_ADDRESS_H__
|
||||
|
||||
#include <string>
|
||||
#include "dtoolbase.h"
|
||||
|
||||
///////////////////////////////////
|
||||
// Class : Socket_Address
|
||||
//
|
||||
// Description: A simple place to store and munipulate tcp and port address for
|
||||
// communication layer
|
||||
//
|
||||
//////////////////////////////
|
||||
class Socket_Address
|
||||
{
|
||||
public:
|
||||
typedef struct sockaddr_in AddressType;
|
||||
Socket_Address(const AddressType &inaddr);
|
||||
AddressType & GetAddressInfo() { return _addr; }
|
||||
const AddressType & GetAddressInfo() const { return _addr; }
|
||||
PUBLISHED:
|
||||
|
||||
Socket_Address(short port = 0);
|
||||
Socket_Address(const Socket_Address &inaddr);
|
||||
|
||||
virtual ~Socket_Address();
|
||||
|
||||
bool set_any_IP(int port);
|
||||
bool set_port(int port);
|
||||
bool set_broadcast(int port);
|
||||
|
||||
bool set_host(const std::string &hostname, int port) ;
|
||||
bool set_host(const std::string &hostname) ;
|
||||
bool set_host(unsigned int ip4adr, int port);
|
||||
void clear();
|
||||
|
||||
unsigned short get_port() const;
|
||||
std::string get_ip() const ;
|
||||
std::string get_ip_port() const;
|
||||
unsigned long GetIPAddressRaw() const;
|
||||
|
||||
inline bool operator== (const Socket_Address &in) const;
|
||||
inline bool operator < (const Socket_Address &in) const;
|
||||
|
||||
|
||||
inline bool isMcastRange();
|
||||
|
||||
private:
|
||||
AddressType _addr;
|
||||
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_Address::GetIPAdddressRaw
|
||||
// Description : Return a RAW sockaddr_in
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline unsigned long Socket_Address::GetIPAddressRaw() const
|
||||
{
|
||||
return _addr.sin_addr.s_addr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_Address
|
||||
// Description : Constructor that lets us set a port value
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline Socket_Address::Socket_Address(short port)
|
||||
{
|
||||
_addr.sin_family = AF_INET;
|
||||
_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
_addr.sin_port = htons(port);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_Address Constructor
|
||||
// Description : Copy Constructor
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline Socket_Address::Socket_Address(const Socket_Address &inaddr)
|
||||
{
|
||||
_addr.sin_family = inaddr._addr.sin_family;
|
||||
_addr.sin_addr.s_addr = inaddr._addr.sin_addr.s_addr;
|
||||
_addr.sin_port = inaddr._addr.sin_port;
|
||||
}
|
||||
|
||||
inline Socket_Address::Socket_Address(const AddressType &inaddr)
|
||||
{
|
||||
_addr.sin_family = inaddr.sin_family;
|
||||
_addr.sin_addr.s_addr = inaddr.sin_addr.s_addr;
|
||||
_addr.sin_port = inaddr.sin_port;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : ~Socket_Address::Socket_Address
|
||||
// Description : Normal Destructor
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline Socket_Address::~Socket_Address()
|
||||
{}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_Address::operator==
|
||||
// Description : Allow for normal == operation on a address item..
|
||||
// Will simplify the use in sorted containers..
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Socket_Address::operator==(const Socket_Address &in) const
|
||||
{
|
||||
return ((_addr.sin_family == in._addr.sin_family) &&
|
||||
(_addr.sin_addr.s_addr == in._addr.sin_addr.s_addr) &&
|
||||
(_addr.sin_port == in._addr.sin_port)
|
||||
);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : set_broadcast
|
||||
// Description : Set to the broadcast address and a specified port
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_Address::set_broadcast(int port)
|
||||
{
|
||||
_addr.sin_family = AF_INET;
|
||||
_addr.sin_addr.s_addr = 0xffffffff;
|
||||
_addr.sin_port = htons(port);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : set_any_IP
|
||||
// Description : Set to any address and a specified port
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_Address::set_any_IP(int port)
|
||||
{
|
||||
_addr.sin_family = AF_INET;
|
||||
_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
_addr.sin_port = htons(port);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : set_port
|
||||
// Description : Set to a specified port
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_Address::set_port(int port)
|
||||
{
|
||||
_addr.sin_port = htons(port);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : clear
|
||||
// Description : Set the internal values to a suitable known value
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline void Socket_Address::clear()
|
||||
{
|
||||
_addr.sin_family = AF_INET;
|
||||
_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
_addr.sin_port = htons(0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : get_port
|
||||
// Description : Get the port portion as an integer
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline unsigned short Socket_Address::get_port() const
|
||||
{
|
||||
return ntohs(_addr.sin_port);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : get_ip
|
||||
// Description : Return the ip address portion in dot notation string
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline std::string Socket_Address::get_ip() const
|
||||
{
|
||||
return std::string(inet_ntoa(_addr.sin_addr));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : get_ip_port
|
||||
// Description : Return the ip address/port in dot notation string
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline std::string Socket_Address::get_ip_port() const
|
||||
{
|
||||
char buf1[100]; // 100 is more than enough for any ip address:port combo..
|
||||
sprintf(buf1, "%s:%d", inet_ntoa(_addr.sin_addr), get_port());
|
||||
return std::string(buf1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : set_host
|
||||
// Description : this function will take a port and string-based tcp address and initialize
|
||||
// the address with the information
|
||||
//
|
||||
// Return type : bool (address is undefined after an error)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_Address::set_host(const std::string &hostname, int port)
|
||||
{
|
||||
struct hostent *hp = NULL;
|
||||
|
||||
//
|
||||
// hmm inet_addr does not resolve 255.255.255.255 on ME/98 ??
|
||||
//
|
||||
// * HACK * ??
|
||||
if(hostname == "255.255.255.255")
|
||||
return set_broadcast(port);
|
||||
//
|
||||
//
|
||||
|
||||
UINT32 addr = (long)inet_addr (hostname.c_str());
|
||||
if(addr == INADDR_NONE)
|
||||
{
|
||||
hp = gethostbyname(hostname.c_str());
|
||||
if(hp== NULL)
|
||||
return false;
|
||||
else
|
||||
memcpy(&(_addr.sin_addr),hp->h_addr_list[0] , (unsigned int) hp->h_length);
|
||||
}
|
||||
else
|
||||
(void) memcpy(&_addr.sin_addr,&addr,sizeof(addr));
|
||||
|
||||
_addr.sin_port = htons(port);
|
||||
_addr.sin_family = AF_INET;
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_Address::set_host
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Socket_Address::set_host(const std::string &hostname)
|
||||
{
|
||||
std::string::size_type pos = hostname.find(':');
|
||||
if (pos == std::string::npos)
|
||||
return false;
|
||||
|
||||
std::string host = hostname.substr(0, pos);
|
||||
std::string port = hostname.substr(pos + 1, 100);;
|
||||
|
||||
int port_dig = atoi(port.c_str());
|
||||
|
||||
return set_host(host, port_dig);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_Address::set_host
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Socket_Address::set_host(UINT32 in_hostname, int port)
|
||||
{
|
||||
memcpy(&_addr.sin_addr, &in_hostname, sizeof(in_hostname));
|
||||
_addr.sin_port = htons(port);
|
||||
_addr.sin_family = AF_INET;
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : <
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Socket_Address::operator < (const Socket_Address &in) const
|
||||
{
|
||||
if (_addr.sin_port < in._addr.sin_port)
|
||||
return true;
|
||||
|
||||
if (_addr.sin_port > in._addr.sin_port)
|
||||
return false;
|
||||
|
||||
if (_addr.sin_addr.s_addr < in._addr.sin_addr.s_addr)
|
||||
return true;
|
||||
|
||||
if (_addr.sin_addr.s_addr > in._addr.sin_addr.s_addr)
|
||||
return false;
|
||||
|
||||
|
||||
return (_addr.sin_family < in._addr.sin_family);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : isMcastRange
|
||||
// Description : return true if the address is in the mcast range.
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Socket_Address::isMcastRange(void)
|
||||
{
|
||||
UINT32 address = ntohl(_addr.sin_addr.s_addr);
|
||||
//224.0.0.0-239.255.255.255 .. e0,ef
|
||||
if(address >= 0xe0000000 && address < 0xefffffff)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#endif //__SOCKET_ADDRESS_H__
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef __SOCKET_BASE_H__
|
||||
#define __SOCKET_BASE_H__
|
||||
////////////////////////////////////////////
|
||||
// Quick way to get all the network code defined
|
||||
////////////////////////////////////////////
|
||||
#include "socket_portable.h"
|
||||
#include "socket_address.h"
|
||||
#include "socket_ip.h"
|
||||
#include "socket_tcp.h"
|
||||
#include "socket_tcp_listen.h"
|
||||
#include "socket_udp_incoming.h"
|
||||
#include "socket_udp_outgoing.h"
|
||||
#include "socket_fdset.h"
|
||||
#include "socket_selector.h"
|
||||
|
||||
#endif //__SOCKET_BASE_H__
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
#ifndef __SOCKET_FDSET_H__
|
||||
#define __SOCKET_FDSET_H__
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//
|
||||
//rhh
|
||||
// This class needs to be broken into 2 classes: the gathering class and the processing functions.
|
||||
// The functions should be set up as template functions
|
||||
//
|
||||
// Add a helper class socket_select. May want to totally separate the select and collect functionality
|
||||
// fits more with the normal Berkeley mind set... ** Not ** Should think about using POLL() on BSD-based systems
|
||||
//
|
||||
//////////////////////////////////////////////////////////
|
||||
#include "time_base.h"
|
||||
|
||||
class Socket_fdset
|
||||
{
|
||||
public:
|
||||
|
||||
inline Socket_fdset();
|
||||
inline void setForSocket(const Socket_IP &incon);
|
||||
inline bool IsSetFor(const Socket_IP & incon) const;
|
||||
inline int WaitForRead(bool zeroFds, UINT32 sleep_time = 0xffffffff);
|
||||
inline int WaitForWrite(bool zeroFds, UINT32 sleep_time = 0xffffffff);
|
||||
inline int WaitForError(bool zeroFds, UINT32 sleep_time = 0xffffffff);
|
||||
|
||||
|
||||
inline int WaitForRead(bool zeroFds, const Time_Span & timeout);
|
||||
inline void clear();
|
||||
private:
|
||||
inline void setForSocketNative(const SOCKET inid);
|
||||
inline bool isSetForNative(const SOCKET inid) const;
|
||||
|
||||
friend struct Socket_Selector;
|
||||
SOCKET _maxid;
|
||||
fd_set _the_set;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_fdset::Socket_fdset
|
||||
// Description : The constructor
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline Socket_fdset::Socket_fdset()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_fdset::setForSocketNative
|
||||
// Description : This does the physical manipulation of the set getting read for the base call
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline void Socket_fdset::setForSocketNative(SOCKET inid)
|
||||
{
|
||||
assert( inid >= 0);
|
||||
#ifndef WIN32
|
||||
assert(inid < FD_SETSIZE);
|
||||
#endif
|
||||
|
||||
FD_SET(inid, &_the_set);
|
||||
if (_maxid < inid)
|
||||
_maxid = inid;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_fdset::isSetForNative
|
||||
// Description : Answer the question: was the socket marked for reading
|
||||
// there's a subtle difference in the NSPR version: it will respond if
|
||||
// the socket had an error
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_fdset::isSetForNative(SOCKET inid) const
|
||||
{
|
||||
assert( inid >= 0);
|
||||
#ifndef WIN32
|
||||
assert(inid < FD_SETSIZE);
|
||||
#endif
|
||||
|
||||
return (FD_ISSET(inid, &_the_set) != 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_fdset::IsSetFor
|
||||
// Description : check to see if a socket object has been marked for reading
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_fdset::IsSetFor(const Socket_IP & incon) const
|
||||
{
|
||||
return isSetForNative(incon.GetSocket());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : WaitForRead
|
||||
// Description :
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline int Socket_fdset::WaitForRead(bool zeroFds, UINT32 sleep_time)
|
||||
{
|
||||
int retVal = 0;
|
||||
if (sleep_time == 0xffffffff)
|
||||
{
|
||||
retVal = DO_SELECT(_maxid + 1, &_the_set, NULL, NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
timeval timeoutValue;
|
||||
timeoutValue.tv_sec = sleep_time / 1000;
|
||||
timeoutValue.tv_usec = (sleep_time % 1000) * 1000;
|
||||
|
||||
retVal = DO_SELECT(_maxid + 1, &_the_set, NULL, NULL, &timeoutValue);
|
||||
}
|
||||
if (zeroFds)
|
||||
clear();
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_fdset::WaitForRead
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int Socket_fdset::WaitForRead(bool zeroFds, const Time_Span & timeout)
|
||||
{
|
||||
timeval localtv = timeout.GetTval();
|
||||
|
||||
int retVal = DO_SELECT(_maxid + 1, &_the_set, NULL, NULL, &localtv);
|
||||
if (zeroFds)
|
||||
clear();
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_fdset::zeroOut
|
||||
// Description : Marks the content as empty
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline void Socket_fdset::clear()
|
||||
{
|
||||
_maxid = 0;
|
||||
FD_ZERO(&_the_set);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_fdset::setForSocket
|
||||
// Description :
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline void Socket_fdset::setForSocket(const Socket_IP &incon)
|
||||
{
|
||||
setForSocketNative(incon.GetSocket());
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_fdset::WaitForWrite
|
||||
// Description : This is the function that will wait till
|
||||
// one of the sockets is ready for writing
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline int Socket_fdset::WaitForWrite(bool zeroFds, UINT32 sleep_time)
|
||||
{
|
||||
int retVal = 0;
|
||||
if (sleep_time == 0xffffffff)
|
||||
{
|
||||
retVal = DO_SELECT(_maxid + 1, NULL, &_the_set, NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
timeval timeoutValue;
|
||||
timeoutValue.tv_sec = sleep_time / 1000;
|
||||
timeoutValue.tv_usec = (sleep_time % 1000) * 1000;
|
||||
|
||||
retVal = DO_SELECT(_maxid + 1, NULL, &_the_set, NULL, &timeoutValue);
|
||||
}
|
||||
if (zeroFds)
|
||||
clear();
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_fdset::WaitForError
|
||||
// Description : This is the function that will wait till
|
||||
// one of the sockets is in error state
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int Socket_fdset::WaitForError(bool zeroFds, UINT32 sleep_time)
|
||||
{
|
||||
int retVal = 0;
|
||||
if (sleep_time == 0xffffffff)
|
||||
{
|
||||
retVal = DO_SELECT(_maxid + 1, NULL, NULL, &_the_set, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
timeval timeoutValue;
|
||||
timeoutValue.tv_sec = sleep_time / 1000;
|
||||
timeoutValue.tv_usec = (sleep_time % 1000) * 1000;
|
||||
|
||||
retVal = DO_SELECT(_maxid + 1, NULL, NULL, &_the_set, &timeoutValue);
|
||||
}
|
||||
if (zeroFds)
|
||||
clear();
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
#endif //__SOCKET_FDSET_H__
|
||||
|
|
@ -0,0 +1,247 @@
|
|||
#ifndef __SOCKET_IP_H__
|
||||
#define __SOCKET_IP_H__
|
||||
|
||||
// forward declarations for friends...
|
||||
class Socket_TCP;
|
||||
class Socket_UDP;
|
||||
class Socket_TCP_Listen;
|
||||
class Socket_UDP_Incoming;
|
||||
class Socket_UDP_Outgoing;
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Class : Socket_IP
|
||||
//
|
||||
// Description : Base functionality for a INET domain Socket
|
||||
// this call should be the starting point for all other
|
||||
// unix domain sockets
|
||||
//
|
||||
//
|
||||
// SocketIP
|
||||
// |
|
||||
// -------------------------------------------------------------------
|
||||
// | | | |
|
||||
// SocketTCP SocketTCP_Listen SocketUDP_Incoming SocketUDP_OutBound
|
||||
//
|
||||
//
|
||||
//
|
||||
// socket_fdset
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
class Socket_IP
|
||||
{
|
||||
public:
|
||||
PUBLISHED:
|
||||
|
||||
inline Socket_IP();
|
||||
inline Socket_IP(SOCKET in);
|
||||
virtual ~Socket_IP();
|
||||
|
||||
inline void Close();
|
||||
inline static int GetLastError();
|
||||
inline int SetNonBlocking();
|
||||
inline int SetBlocking();
|
||||
inline bool SetReuseAddress();
|
||||
inline bool Active();
|
||||
inline int SetRecvBufferSize(int size);
|
||||
inline void SetSocket(SOCKET ins);
|
||||
inline SOCKET GetSocket();
|
||||
inline SOCKET GetSocket() const;
|
||||
inline Socket_Address GetPeerName(void) const;
|
||||
|
||||
|
||||
inline static int InitNetworkDriver() { return init_network(); };
|
||||
|
||||
public:
|
||||
private:
|
||||
inline bool ErrorClose();
|
||||
|
||||
SOCKET _socket; // see socket_portable.h
|
||||
|
||||
friend class Socket_TCP;
|
||||
friend class Socket_UDP;
|
||||
friend class Socket_TCP_Listen;
|
||||
friend class Socket_UDP_Incoming;
|
||||
friend class Socket_UDP_Outgoing;
|
||||
friend class Socket_TCP_SSL;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_IP::ErrorClose
|
||||
// Description : Used by internal to force a close
|
||||
// note that it always returns a false
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_IP::ErrorClose()
|
||||
{
|
||||
if (Active())
|
||||
DO_CLOSE(_socket);
|
||||
_socket = BAD_SOCKET;
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_IP::Active
|
||||
// Description : Ask if the socket is open (allocated)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_IP::Active()
|
||||
{
|
||||
return (_socket != BAD_SOCKET);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_IP::Socket_IP
|
||||
// Description : Def Constructor
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline Socket_IP::Socket_IP()
|
||||
{
|
||||
_socket = BAD_SOCKET;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_IP::SetSocket
|
||||
// Description : Assigns an existing socket to this class
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline Socket_IP::Socket_IP(SOCKET ins)
|
||||
{
|
||||
_socket = ins;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_IP::~Socket_IP
|
||||
// Description : Destructor
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline Socket_IP::~Socket_IP()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_IP::Close
|
||||
// Description : closes a socket if it is open (allocated)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline void Socket_IP::Close()
|
||||
{
|
||||
if (Active())
|
||||
DO_CLOSE(_socket);
|
||||
_socket = BAD_SOCKET;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_IP::GetLastError
|
||||
// Description : gets the last errcode from a socket operation
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline int Socket_IP::GetLastError()
|
||||
{
|
||||
return GETERROR();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_IP::SetSocket
|
||||
// Description : Assigns an existing socket to this class
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline void Socket_IP::SetSocket(SOCKET ins)
|
||||
{
|
||||
Close();
|
||||
_socket = ins;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_IP::SetRecvBufferSize
|
||||
// Description : Ok it sets the recv buffer size for both tcp and UDP
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int Socket_IP::SetRecvBufferSize(int insize)
|
||||
{
|
||||
if (setsockopt(_socket, (int) SOL_SOCKET, (int) SO_RCVBUF, (char *) &insize, sizeof(int)))
|
||||
return BASIC_ERROR;
|
||||
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : SetNonBlocking
|
||||
// Description : this function will throw a socket into non-blocking mode
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline int Socket_IP::SetNonBlocking()
|
||||
{
|
||||
#ifdef BSDBLOCK
|
||||
|
||||
int flags = fcntl(_socket, F_GETFL, 0);
|
||||
flags = flags | O_NONBLOCK;
|
||||
fcntl(_socket, F_SETFL, flags);
|
||||
return ALL_OK;
|
||||
#else
|
||||
unsigned long val = LOCAL_NONBLOCK;
|
||||
unsigned lanswer = 0;
|
||||
lanswer = SOCKIOCTL(_socket, LOCAL_FL_SET, &val);
|
||||
if (lanswer != 0)
|
||||
return BASIC_ERROR;
|
||||
return ALL_OK;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_IP::SetBlocking
|
||||
// Description : Set the socket to block on subsequent calls to
|
||||
// socket functions that address this socket
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline int Socket_IP::SetBlocking()
|
||||
{
|
||||
#ifdef BSDBLOCK
|
||||
int flags = fcntl(_socket, F_GETFL, 0);
|
||||
flags &= ~O_NONBLOCK;
|
||||
fcntl(_socket, F_SETFL, flags);
|
||||
return ALL_OK;
|
||||
#else
|
||||
unsigned long val = 0;
|
||||
unsigned lanswer = 0;
|
||||
lanswer = SOCKIOCTL(_socket, LOCAL_FL_SET, &val);
|
||||
if (lanswer != 0)
|
||||
return BASIC_ERROR;
|
||||
return ALL_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : SetReuseAddress
|
||||
// Description : Informs a socket to reuse IP address as needed
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_IP::SetReuseAddress()
|
||||
{
|
||||
int bOption = 1;
|
||||
if (setsockopt(_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&bOption, sizeof(bOption)) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_IP::GetSocket
|
||||
// Description : Gets the base socket type
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline SOCKET Socket_IP::GetSocket()
|
||||
{
|
||||
return _socket;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_IP::GetSocket
|
||||
// Description : Get The RAW file id of the socket
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline SOCKET Socket_IP::GetSocket() const
|
||||
{
|
||||
return _socket;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_IP::GetPeerName
|
||||
// Description : Wrapper on berkly getpeername...
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Socket_Address Socket_IP::GetPeerName(void) const
|
||||
{
|
||||
sockaddr_in name;
|
||||
socklen_t name_len = sizeof(name);
|
||||
memset(&name,0,name_len);
|
||||
|
||||
getpeername(_socket,(sockaddr * )&name,&name_len);
|
||||
return Socket_Address(name);
|
||||
}
|
||||
|
||||
|
||||
#endif //__SOCKET_IP_H__
|
||||
|
|
@ -0,0 +1,366 @@
|
|||
#ifndef __SOCKET_PORTABLE_H__
|
||||
#define __SOCKET_PORTABLE_H__
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Lots of stuff to make network socket-based io transparent across multiple
|
||||
// platforms
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
const int ALL_OK = 0;
|
||||
const int BASIC_ERROR = -1;
|
||||
|
||||
/************************************************************************
|
||||
* HP SOCKET LIBRARY STUFF
|
||||
************************************************************************/
|
||||
#if defined(HP_SOCK)
|
||||
|
||||
#ifndef _INCLUDE_HPUX_SOURCE
|
||||
#define _INCLUDE_HPUX_SOURCE
|
||||
#define _INCLUDE_POSIX_SOURCE
|
||||
#define _INCLUDE_XOPEN_SOURCE
|
||||
#endif
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define socket_read read
|
||||
#define socket_write write
|
||||
#define socket_close close
|
||||
|
||||
#define DO_CONNECT(a,b,c) connect(a,b,c)
|
||||
#define DO_SOCKET_READ(a,b,c,d) socket_read(a,b,c)
|
||||
#define DO_SOCKET_WRITE(a,b,c,d) socket_write(a,b,c)
|
||||
|
||||
#define GETERROR() errno
|
||||
|
||||
|
||||
#define SOCKIOCTL ioctl
|
||||
typedef unsigned long SOCKET;
|
||||
#define BAD_SOCKET 0xffffffff
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* WINSOCK 32 bit STUFF
|
||||
************************************************************************/
|
||||
#elif defined(WIN32) || defined(WIN32_VC)
|
||||
#include <winsock2.h>
|
||||
#include <Ws2tcpip.h>
|
||||
|
||||
|
||||
inline int DO_SELECT(SOCKET n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,struct timeval *timeout)
|
||||
{
|
||||
return select((int) n, readfds, writefds, exceptfds,timeout);
|
||||
}
|
||||
|
||||
inline int DO_CONNECT( const SOCKET a, const struct sockaddr_in *b)
|
||||
{
|
||||
return connect(a, reinterpret_cast<const struct ::sockaddr *>(b), sizeof(sockaddr));
|
||||
}
|
||||
inline int DO_SOCKET_READ(const SOCKET a, char * buf, const int size)
|
||||
{
|
||||
return recv(a, buf, size, 0);
|
||||
}
|
||||
inline int DO_SOCKET_WRITE(const SOCKET a, const char * buff, const int len)
|
||||
{
|
||||
return send(a, buff, len, 0);
|
||||
}
|
||||
inline int DO_SOCKET_WRITE_TO(const SOCKET a, const char * buffer, const int buf_len, const sockaddr_in * addr)
|
||||
{
|
||||
return sendto(a, buffer, buf_len, 0, reinterpret_cast<const struct ::sockaddr *>(addr), sizeof(sockaddr));
|
||||
}
|
||||
inline SOCKET DO_NEWUDP()
|
||||
{
|
||||
return socket(AF_INET, SOCK_DGRAM, 0);
|
||||
}
|
||||
inline SOCKET DO_NEWTCP()
|
||||
{
|
||||
return socket(AF_INET, SOCK_STREAM, 0);
|
||||
}
|
||||
inline int DO_BIND(const SOCKET a, const sockaddr_in *b)
|
||||
{
|
||||
return bind(a, reinterpret_cast<const struct ::sockaddr *>(b), sizeof(sockaddr));
|
||||
}
|
||||
inline int DO_CLOSE(const SOCKET a)
|
||||
{
|
||||
return closesocket(a);
|
||||
}
|
||||
inline SOCKET DO_ACCEPT(SOCKET sck, sockaddr_in * adr)
|
||||
{
|
||||
int adrlen = sizeof(sockaddr);
|
||||
return accept(sck, reinterpret_cast<sockaddr *>(adr), &adrlen);
|
||||
};
|
||||
inline int DO_RECV_FROM(SOCKET sck, char * data, int len, sockaddr_in * addr)
|
||||
{
|
||||
int plen = sizeof(sockaddr);
|
||||
return recvfrom(sck, data, len, 0, reinterpret_cast<sockaddr *>(addr), &plen);
|
||||
}
|
||||
inline int DO_LISTEN(const SOCKET a, const int size)
|
||||
{
|
||||
return listen(a, size);
|
||||
}
|
||||
|
||||
inline int GETERROR()
|
||||
{
|
||||
return WSAGetLastError();
|
||||
}
|
||||
|
||||
inline int SOCKIOCTL(const SOCKET s, const long flags, unsigned long * val)
|
||||
{
|
||||
return ioctlsocket(s, flags, val);
|
||||
}
|
||||
|
||||
inline int init_network()
|
||||
{
|
||||
static struct WSAData mydata;
|
||||
int answer = WSAStartup(0x0101, &mydata);
|
||||
if (answer != 0)
|
||||
return BASIC_ERROR;
|
||||
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
inline bool do_shutdown_send(SOCKET s)
|
||||
{
|
||||
return (shutdown(s,SD_SEND) == 0);
|
||||
};
|
||||
|
||||
typedef int socklen_t ;
|
||||
const long LOCAL_NONBLOCK = 1;
|
||||
const long LOCAL_FL_SET = FIONBIO ;
|
||||
const int LOCAL_BLOCKING_ERROR = WSAEWOULDBLOCK;
|
||||
const int LOCAL_CONNECT_BLOCKING = WSAEWOULDBLOCK;
|
||||
const int LOCAL_NOTCONNECTED_ERROR = WSAENOTCONN;
|
||||
const int LOCAL_TIMEOUT_ERROR = WSAETIMEDOUT;
|
||||
const SOCKET BAD_SOCKET = 0xffffffff;
|
||||
|
||||
/************************************************************************
|
||||
* Solaris 2.6 and Irix 6.4 STUFF
|
||||
************************************************************************/
|
||||
#elif defined(SunOS) || defined(SUNNEW) || defined(IRIX64)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/filio.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
typedef int SOCKET;
|
||||
const SOCKET BAD_SOCKET = 0xffffffff;
|
||||
|
||||
//#define DO_CONNECT(a,b) connect(a,(sockaddr *)b,sizeof(sockaddr))
|
||||
//#define DO_SOCKET_READ(a,b,c) recv(a,b,c,0)
|
||||
//#define DO_SOCKET_WRITE(a,b,c) send(a,b,c,0)
|
||||
|
||||
inline int DO_CONNECT(const SOCKET a, const sockaddr_in *b)
|
||||
{
|
||||
return connect(a, reinterpret_cast<const struct ::sockaddr *>(b), sizeof(sockaddr));
|
||||
}
|
||||
inline int DO_SOCKET_READ(const SOCKET a, char * buf, const int size)
|
||||
{
|
||||
return recv(a, buf, size, 0);
|
||||
}
|
||||
inline int DO_SOCKET_WRITE(const SOCKET a, const char * buff, const int len)
|
||||
{
|
||||
return send(a, buff, len, 0);
|
||||
}
|
||||
|
||||
//#define DO_SOCKET_WRITE_TO(a,b,c,d) sendto(a,b,c,0,(sockaddr *)d,sizeof(sockaddr))
|
||||
//#define DO_NEWUDP() socket(AF_INET, SOCK_DGRAM, 0)
|
||||
//#define DO_NEWTCP() socket(AF_INET, SOCK_STREAM, 0)
|
||||
//#define DO_BIND(a,b) bind(a,(sockaddr *)b,sizeof(sockaddr))
|
||||
//#/define DO_CLOSE(a) close(a)
|
||||
inline int DO_SOCKET_WRITE_TO(const SOCKET a, const char * buffer, const int buf_len, const sockaddr_in * addr)
|
||||
{
|
||||
return sendto(a, buffer, buf_len, 0, reinterpret_cast<const struct ::sockaddr *>(addr), sizeof(sockaddr));
|
||||
}
|
||||
inline SOCKET DO_NEWUDP()
|
||||
{
|
||||
return socket(AF_INET, SOCK_DGRAM, 0);
|
||||
}
|
||||
inline SOCKET DO_NEWTCP()
|
||||
{
|
||||
return socket(AF_INET, SOCK_STREAM, 0);
|
||||
}
|
||||
inline int DO_BIND(const SOCKET a, const sockaddr_in *b)
|
||||
{
|
||||
return bind(a, reinterpret_cast<const struct ::sockaddr *>(b), sizeof(sockaddr));
|
||||
}
|
||||
inline int DO_CLOSE(const SOCKET a)
|
||||
{
|
||||
return close(a);
|
||||
}
|
||||
inline int DO_ACCEPT(SOCKET sck, sockaddr_in * adr)
|
||||
{
|
||||
int adrlen = sizeof(sockaddr);
|
||||
return accept(sck, ( sockaddr *)adr, &adrlen);
|
||||
};
|
||||
|
||||
inline int DO_RECV_FROM(SOCKET sck, char * data, int len, sockaddr_in * addr)
|
||||
{
|
||||
int plen = sizeof(sockaddr);
|
||||
return recvfrom(sck, data, len, 0, (sockaddr *)addr, &plen);
|
||||
}
|
||||
inline int DO_LISTEN(const SOCKET a, const int size)
|
||||
{
|
||||
return listen(a, size);
|
||||
}
|
||||
|
||||
inline int GETERROR()
|
||||
{
|
||||
return errno;
|
||||
}
|
||||
|
||||
inline int SOCKIOCTL(const SOCKET s, const long flags, void * val)
|
||||
{
|
||||
return ioctl(s, flags, val);
|
||||
}
|
||||
|
||||
inline int init_network()
|
||||
{
|
||||
return ALL_OK;
|
||||
}
|
||||
#ifndef INADDR_NONE
|
||||
const INADDR_NONE = -1;
|
||||
#endif
|
||||
|
||||
const long LOCAL_NONBLOCK = 1;
|
||||
const long LOCAL_FL_SET = FIONBIO ;
|
||||
const int LOCAL_BLOCKING_ERROR = EAGAIN;
|
||||
const int LOCAL_CONNECT_BLOCKING = EINPROGRESS;
|
||||
|
||||
/************************************************************************
|
||||
* LINUX and FreeBSD STUFF
|
||||
************************************************************************/
|
||||
|
||||
#elif defined(Linux) || defined(FreeBSD) ||defined(LINUX)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef int SOCKET;
|
||||
const SOCKET BAD_SOCKET = -1;
|
||||
inline int DO_SELECT(SOCKET n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,struct timeval *timeout)
|
||||
{
|
||||
return select((int) n, readfds, writefds, exceptfds,timeout);
|
||||
}
|
||||
|
||||
inline int DO_CONNECT(const SOCKET a, const sockaddr_in *b)
|
||||
{
|
||||
return connect(a, reinterpret_cast<const struct ::sockaddr *>(b), sizeof(sockaddr));
|
||||
}
|
||||
inline int DO_SOCKET_READ(const SOCKET a, char * buf, const int size)
|
||||
{
|
||||
return recv(a, buf, size, 0);
|
||||
}
|
||||
inline int DO_SOCKET_WRITE(const SOCKET a, const char * buff, const int len)
|
||||
{
|
||||
return send(a, buff, len, 0);
|
||||
}
|
||||
///////////////////////////////////////////////
|
||||
inline int DO_SOCKET_WRITE_TO(const SOCKET a, const char * buffer, const int buf_len, const sockaddr_in * addr)
|
||||
{
|
||||
return sendto(a, buffer, buf_len, 0, reinterpret_cast<const struct ::sockaddr *>(addr), sizeof(sockaddr));
|
||||
}
|
||||
inline SOCKET DO_NEWUDP()
|
||||
{
|
||||
return socket(AF_INET, SOCK_DGRAM, 0);
|
||||
}
|
||||
inline SOCKET DO_NEWTCP()
|
||||
{
|
||||
return socket(AF_INET, SOCK_STREAM, 0);
|
||||
}
|
||||
inline int DO_BIND(const SOCKET a, const sockaddr_in *b)
|
||||
{
|
||||
return bind(a, reinterpret_cast<const struct ::sockaddr *>(b), sizeof(sockaddr));
|
||||
}
|
||||
inline int DO_CLOSE(const SOCKET a)
|
||||
{
|
||||
return close(a);
|
||||
}
|
||||
|
||||
inline int DO_ACCEPT(SOCKET sck, sockaddr_in * adr)
|
||||
{
|
||||
unsigned int adrlen = sizeof(sockaddr);
|
||||
return accept(sck, ( sockaddr *)adr, &adrlen);
|
||||
};
|
||||
|
||||
inline int DO_RECV_FROM(SOCKET sck, char * data, int len, sockaddr_in * addr)
|
||||
{
|
||||
unsigned int plen = sizeof(sockaddr);
|
||||
return recvfrom(sck, data, len, 0, (sockaddr *)addr, &plen);
|
||||
}
|
||||
|
||||
|
||||
inline int init_network()
|
||||
{
|
||||
signal(SIGPIPE, SIG_IGN); // hmm do i still need this ...
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
inline int DO_LISTEN(const SOCKET a, const int size)
|
||||
{
|
||||
return listen(a, size);
|
||||
}
|
||||
|
||||
inline int GETERROR()
|
||||
{
|
||||
return errno;
|
||||
}
|
||||
|
||||
inline int SOCKIOCTL(const SOCKET s, const long flags, void * val)
|
||||
{
|
||||
return ioctl(s, flags, val);
|
||||
}
|
||||
|
||||
inline bool do_shutdown_send(SOCKET s)
|
||||
{
|
||||
return (shutdown(s,SHUT_WR) == 0);
|
||||
};
|
||||
|
||||
|
||||
#define BSDBLOCK
|
||||
|
||||
|
||||
const long LOCAL_NONBLOCK = 1;
|
||||
const long LOCAL_FL_SET = FIONBIO ;
|
||||
const int LOCAL_BLOCKING_ERROR = EAGAIN;
|
||||
const int LOCAL_CONNECT_BLOCKING = EINPROGRESS;
|
||||
|
||||
#else
|
||||
/************************************************************************
|
||||
* NO DEFINITION => GIVE COMPILATION ERROR
|
||||
************************************************************************/
|
||||
No Host Type defined !!
|
||||
#error Fatal
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif //__SOCKET_PORTABLE_H__
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
#ifndef __SOCKET_SELECTOR_H__
|
||||
#define __SOCKET_SELECTOR_H__
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// This is a structure on purpose. only used as a helper class to save on typing
|
||||
//
|
||||
////////////////////////////////////////////////////
|
||||
struct Socket_Selector
|
||||
{
|
||||
Socket_fdset _read;
|
||||
Socket_fdset _write;
|
||||
Socket_fdset _error;
|
||||
int _answer;
|
||||
|
||||
Socket_Selector() : _answer( -1)
|
||||
{
|
||||
}
|
||||
|
||||
Socket_Selector(const Socket_fdset &fd) : _read(fd), _write(fd), _error(fd) , _answer( -1)
|
||||
{
|
||||
}
|
||||
|
||||
int WaitFor(const Time_Span &timeout);
|
||||
int WaitFor_All(const Socket_fdset & fd, const Time_Span & timeout);
|
||||
int WaitFor_Read_Error(const Socket_fdset & fd, const Time_Span & timeout);
|
||||
int WaitFor_Write_Error(const Socket_fdset & fd, const Time_Span & timeout);
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_Selector::WaitFor
|
||||
// Description : This function is the reason this call exists..
|
||||
// It will wait for a read, write or error condition
|
||||
// on a socket or it will time out
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int Socket_Selector::WaitFor(const Time_Span &timeout)
|
||||
{
|
||||
SOCKET local_max = 0;
|
||||
if (local_max < _read._maxid)
|
||||
local_max = _read._maxid;
|
||||
if (local_max < _write._maxid)
|
||||
local_max = _write._maxid;
|
||||
if (local_max < _error._maxid)
|
||||
local_max = _error._maxid;
|
||||
|
||||
timeval localtv = timeout.GetTval();
|
||||
_answer = DO_SELECT(local_max + 1, &_read._the_set, &_write._the_set, &_error._the_set, &localtv);
|
||||
return _answer;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_Selector::WaitFor_All
|
||||
// Description : Helper function to utilize the WaitFor function
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int Socket_Selector::WaitFor_All(const Socket_fdset & fd, const Time_Span & timeout)
|
||||
{
|
||||
_read = fd;
|
||||
_write = fd;
|
||||
_error = fd;
|
||||
return WaitFor(timeout);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_Selector::WaitFor_Read_Error
|
||||
// Description : Helper function for WaitFor
|
||||
// Only looks for readability and errors
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int Socket_Selector::WaitFor_Read_Error(const Socket_fdset & fd, const Time_Span & timeout)
|
||||
{
|
||||
_read = fd;
|
||||
_write.clear();
|
||||
_error = fd;
|
||||
return WaitFor(timeout);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_Selector::WaitFor_Write_Error
|
||||
// Description : Helper function for WaitFor
|
||||
// Only looks for writability and errors
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int Socket_Selector::WaitFor_Write_Error(const Socket_fdset & fd, const Time_Span & timeout)
|
||||
{
|
||||
_read.clear();
|
||||
_write = fd;
|
||||
_error = fd;
|
||||
return WaitFor(timeout);
|
||||
}
|
||||
|
||||
#endif //__SOCKET_SELECTOR_H__
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
#ifndef __SOCKET_TCP_H__
|
||||
#define __SOCKET_TCP_H__
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Class : Socket_TCP
|
||||
//
|
||||
// Description : Base functionality for a TCP connected socket
|
||||
// This class is pretty useless by itself but it does hide some of the
|
||||
// platform differences from machine to machine
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
class Socket_TCP : public Socket_IP
|
||||
{
|
||||
public:
|
||||
PUBLISHED:
|
||||
inline Socket_TCP(SOCKET);
|
||||
inline Socket_TCP() { };
|
||||
inline int SetNoDelay();
|
||||
inline int SetLinger(int interval_seconds = 0);
|
||||
inline int DontLinger();
|
||||
inline int SetSendBufferSize(int insize);
|
||||
inline bool ActiveOpen(const Socket_Address & theaddress);
|
||||
inline bool ActiveOpenNonBlocking(const Socket_Address & theaddress);
|
||||
inline bool ErrorIs_WouldBlocking(int err);
|
||||
inline bool ShutdownSend();
|
||||
inline int SendData(const std::string &str);
|
||||
// inline int RecvData( std::string &str, int max_len);
|
||||
|
||||
std::string RecvData(int max_len);
|
||||
public:
|
||||
inline int SendData(const char * data, int size);
|
||||
inline int RecvData(char * data, int size);
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_TCP::Socket_TCP
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Socket_TCP::Socket_TCP(SOCKET sck) : ::Socket_IP(sck)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : SetNoDelay
|
||||
// Description : Disable Nagle algorithm. Don't delay send to coalesce packets
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline int Socket_TCP::SetNoDelay()
|
||||
{
|
||||
int nodel = 1;
|
||||
int ret1;
|
||||
ret1 = setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (char *) & nodel, sizeof(nodel));
|
||||
|
||||
if (ret1 != 0)
|
||||
return BASIC_ERROR;
|
||||
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : SetLinger
|
||||
// Description : will control the behavior of SO_LINGER for a TCP socket
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int Socket_TCP::SetLinger(int interval_seconds)
|
||||
{
|
||||
linger ll;
|
||||
ll.l_linger = interval_seconds;
|
||||
ll.l_onoff = 1;
|
||||
int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *) & ll, sizeof(linger));
|
||||
if (ret1 != 0)
|
||||
return BASIC_ERROR;
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_TCP::DontLinger
|
||||
// Description : Turn off the linger flag. The socket will quickly release
|
||||
// buffered items and free up OS resources. You may lose
|
||||
// a stream if you use this flag and do not negotiate the close
|
||||
// at the application layer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int Socket_TCP::DontLinger()
|
||||
{
|
||||
linger ll;
|
||||
ll.l_linger = 0;
|
||||
ll.l_onoff = 0;
|
||||
int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *) & ll, sizeof(linger));
|
||||
if (ret1 != 0)
|
||||
return BASIC_ERROR;
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : SetSendBufferSize
|
||||
// Description : Just like it sounds. Sets a buffered socket recv buffer size.
|
||||
// This function does not refuse ranges outside hard-coded OS
|
||||
// limits
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int Socket_TCP::SetSendBufferSize(int insize)
|
||||
{
|
||||
if (setsockopt(_socket, (int) SOL_SOCKET, (int) SO_SNDBUF, (char *) &insize, sizeof(int)))
|
||||
return BASIC_ERROR;
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : ActiveOpen
|
||||
// Description : This function will try and set the socket up for active open to a specified
|
||||
// address and port provided by the input parameter
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Socket_TCP::ActiveOpen(const Socket_Address & theaddress)
|
||||
{
|
||||
_socket = DO_NEWTCP();
|
||||
if (_socket == BAD_SOCKET)
|
||||
return false;
|
||||
|
||||
if (DO_CONNECT(_socket, &theaddress.GetAddressInfo()) != 0)
|
||||
return ErrorClose();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : ActiveOpenNonBlocking
|
||||
// Description : This function will try and set the socket up for active open to a specified
|
||||
// address and port provided by the input parameter (non-blocking version)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Socket_TCP::ActiveOpenNonBlocking(const Socket_Address & theaddress)
|
||||
{
|
||||
_socket = DO_NEWTCP();
|
||||
if (_socket == BAD_SOCKET)
|
||||
return false;
|
||||
|
||||
SetNonBlocking();
|
||||
SetReuseAddress();
|
||||
|
||||
if (DO_CONNECT(_socket, &theaddress.GetAddressInfo()) != 0)
|
||||
if (GETERROR() != LOCAL_CONNECT_BLOCKING)
|
||||
{
|
||||
printf(" None Blockign Connect Error %d",GETERROR());
|
||||
return ErrorClose();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_TCP::SendData
|
||||
// Description : Ok Lets Send the Data
|
||||
//
|
||||
// Return type : int
|
||||
// - if error
|
||||
// 0 if socket closed for write or lengh is 0
|
||||
// + bytes writen ( May be smaller than requested)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline int Socket_TCP::SendData(const char * data, int size)
|
||||
{
|
||||
return DO_SOCKET_WRITE(_socket, data, size);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_TCP::RecvData
|
||||
// Description : Read the data from the connection
|
||||
//
|
||||
// Return type : int
|
||||
// - if error
|
||||
// 0 if socket closed for read or length is 0
|
||||
// + bytes read ( May be smaller than requested)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline int Socket_TCP::RecvData(char * data, int len)
|
||||
{
|
||||
int ecode = DO_SOCKET_READ(_socket, data, len);
|
||||
return ecode;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_TCP::RecvData
|
||||
// Description : Read the data from the connection
|
||||
//
|
||||
// Return type : int
|
||||
// - if error
|
||||
// 0 if socket closed for read or length is 0
|
||||
// + bytes read ( May be smaller than requested)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline std::string Socket_TCP::RecvData(int max_len)
|
||||
{
|
||||
std::string str;
|
||||
char *buffer = (char *) malloc(max_len+1);
|
||||
int ecode = RecvData(buffer,max_len);
|
||||
if(ecode > 0)
|
||||
str.assign(buffer,ecode);
|
||||
|
||||
free(buffer);
|
||||
return str;
|
||||
};
|
||||
|
||||
|
||||
inline bool Socket_TCP::ErrorIs_WouldBlocking(int err)
|
||||
{
|
||||
return (GETERROR() == LOCAL_BLOCKING_ERROR);
|
||||
}
|
||||
|
||||
inline bool Socket_TCP::ShutdownSend()
|
||||
{
|
||||
return do_shutdown_send(_socket);
|
||||
};
|
||||
|
||||
/*
|
||||
inline bool Socket_TCP::DoNotLinger()
|
||||
{
|
||||
int bOption = 1;
|
||||
if (setsockopt(_socket, SOL_SOCKET, SO_DONTLINGER, (const char *)&bOption, sizeof(bOption)) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
inline int Socket_TCP::SendData(const std::string &str)
|
||||
{
|
||||
return SendData(str.data(), str.size());
|
||||
};
|
||||
|
||||
#endif //__SOCKET_TCP_H__
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
#ifndef __SOCKET_TCP_LISTEN_H__
|
||||
#define __SOCKET_TCP_LISTEN_H__
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Class : Socket_TCP_Listen
|
||||
// Description : Base functionality for a TCP rendezvous socket
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
class Socket_TCP_Listen : public Socket_IP
|
||||
{
|
||||
public:
|
||||
PUBLISHED:
|
||||
Socket_TCP_Listen() {};
|
||||
~Socket_TCP_Listen() {};
|
||||
inline bool OpenForListen(Socket_Address & Inaddess, int backlog_size = 1024);
|
||||
inline bool GetIncomingConnection(Socket_TCP & newsession, Socket_Address &address);
|
||||
public:
|
||||
inline bool GetIncomingConnection(SOCKET & newsession, Socket_Address &address);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : OpenForListen
|
||||
// Description : This function will initialize a listening Socket
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_TCP_Listen::OpenForListen(Socket_Address & Inaddess, int backlog_size )
|
||||
{
|
||||
ErrorClose();
|
||||
_socket = DO_NEWTCP();
|
||||
|
||||
SetReuseAddress();
|
||||
|
||||
if (DO_BIND(_socket, &Inaddess.GetAddressInfo()) != 0)
|
||||
return ErrorClose();
|
||||
|
||||
if (DO_LISTEN(_socket, backlog_size) != 0)
|
||||
return ErrorClose();
|
||||
|
||||
return true;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : GetIncomingConnection
|
||||
// Description : This function is used to accept new connections
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_TCP_Listen::GetIncomingConnection(SOCKET & newsession, Socket_Address &address)
|
||||
{
|
||||
newsession = DO_ACCEPT(_socket, &address.GetAddressInfo());
|
||||
if (newsession == BAD_SOCKET)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline bool Socket_TCP_Listen::GetIncomingConnection(Socket_TCP & newsession, Socket_Address &address)
|
||||
{
|
||||
SOCKET sck;
|
||||
if(!GetIncomingConnection(sck,address))
|
||||
return false;
|
||||
|
||||
newsession.SetSocket(sck);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif //__SOCKET_TCP_LISTEN_H__
|
||||
|
|
@ -0,0 +1,304 @@
|
|||
#ifndef __SOCKET_TCP_SSL_H__
|
||||
#define __SOCKET_TCP_SSL_H__
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Class : Socket_TCP
|
||||
//
|
||||
// Description : Base functionality for a TCP connected socket
|
||||
// This class is pretty useless by itself but it does hide some of the
|
||||
// platform differences from machine to machine
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
#include <openssl/rsa.h> /* SSLeay stuff */
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
|
||||
|
||||
extern SSL_CTX *global_ssl_ctx;
|
||||
|
||||
|
||||
struct SSlStartup
|
||||
{
|
||||
SSlStartup()
|
||||
{
|
||||
SSL_METHOD *meth;
|
||||
SSLeay_add_ssl_algorithms();
|
||||
//meth = SSLv23_server_method();
|
||||
meth = SSLv23_method();
|
||||
SSL_load_error_strings();
|
||||
global_ssl_ctx = SSL_CTX_new (meth);
|
||||
}
|
||||
|
||||
~SSlStartup()
|
||||
{
|
||||
SSL_CTX_free (global_ssl_ctx);
|
||||
global_ssl_ctx = NULL;
|
||||
}
|
||||
|
||||
|
||||
bool isactive() { return global_ssl_ctx != NULL; };
|
||||
};
|
||||
|
||||
|
||||
class Socket_TCP_SSL : public Socket_IP
|
||||
{
|
||||
public:
|
||||
|
||||
inline Socket_TCP_SSL(SOCKET);
|
||||
inline Socket_TCP_SSL() : _ssl(NULL) {}
|
||||
|
||||
virtual inline ~Socket_TCP_SSL()
|
||||
{
|
||||
CleanSslUp();
|
||||
}
|
||||
|
||||
inline int SetNoDelay();
|
||||
inline int SetLinger(int interval_seconds = 0);
|
||||
inline int DontLinger();
|
||||
|
||||
inline int SetSendBufferSize(int insize);
|
||||
inline bool ActiveOpen(const Socket_Address & theaddress);
|
||||
inline int SendData(const char * data, int size);
|
||||
inline int RecvData(char * data, int size);
|
||||
inline bool ErrorIs_WouldBlocking(int err);
|
||||
|
||||
inline SSL * get_ssl() { return _ssl; };
|
||||
|
||||
inline void DetailErrorFormat(void);
|
||||
private:
|
||||
SSL* _ssl;
|
||||
|
||||
void CleanSslUp()
|
||||
{
|
||||
if(_ssl != NULL)
|
||||
{
|
||||
SSL_shutdown(_ssl);
|
||||
SSL_free(_ssl);
|
||||
_ssl = NULL;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_TCP_SSL::Socket_TCP_SSL
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
// right know this will only work for a
|
||||
// accepted ie a server socket ??
|
||||
inline Socket_TCP_SSL::Socket_TCP_SSL(SOCKET sck) : ::Socket_IP(sck)
|
||||
{
|
||||
SetNonBlocking(); // maybe should be blocking?
|
||||
|
||||
_ssl = SSL_new (global_ssl_ctx);
|
||||
if(_ssl == NULL)
|
||||
return;
|
||||
SSL_set_fd (_ssl,(int)GetSocket() );
|
||||
|
||||
int err = SSL_accept(_ssl);
|
||||
ERR_clear_error();
|
||||
|
||||
// printf(" Ssl Accept = %d \n",err);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : SetNoDelay
|
||||
// Description : Disable Nagle algorithm. Don't delay send to coalesce packets
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline int Socket_TCP_SSL::SetNoDelay()
|
||||
{
|
||||
int nodel = 1;
|
||||
int ret1;
|
||||
ret1 = setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (char *) & nodel, sizeof(nodel));
|
||||
|
||||
if (ret1 != 0)
|
||||
return BASIC_ERROR;
|
||||
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : SetLinger
|
||||
// Description : will control the behavior of SO_LINGER for a TCP socket
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int Socket_TCP_SSL::SetLinger(int interval_seconds)
|
||||
{
|
||||
linger ll;
|
||||
ll.l_linger = interval_seconds;
|
||||
ll.l_onoff = 1;
|
||||
int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *) & ll, sizeof(linger));
|
||||
if (ret1 != 0)
|
||||
return BASIC_ERROR;
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_TCP_SSL::DontLinger
|
||||
// Description : Turn off the linger flag. The socket will quickly release
|
||||
// buffered items and free up OS resources. You may lose
|
||||
// a stream if you use this flag and do not negotiate the close
|
||||
// at the application layer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int Socket_TCP_SSL::DontLinger()
|
||||
{
|
||||
linger ll;
|
||||
ll.l_linger = 0;
|
||||
ll.l_onoff = 0;
|
||||
int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *) & ll, sizeof(linger));
|
||||
if (ret1 != 0)
|
||||
return BASIC_ERROR;
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : SetSendBufferSize
|
||||
// Description : Just like it sounds. Sets a buffered socket recv buffer size.
|
||||
// This function does not refuse ranges outside hard-coded OS
|
||||
// limits
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int Socket_TCP_SSL::SetSendBufferSize(int insize)
|
||||
{
|
||||
if (setsockopt(_socket, (int) SOL_SOCKET, (int) SO_SNDBUF, (char *) &insize, sizeof(int)))
|
||||
return BASIC_ERROR;
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : ActiveOpen
|
||||
// Description : This function will try and set the socket up for active open to a specified
|
||||
// address and port provided by the input parameter
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Socket_TCP_SSL::ActiveOpen(const Socket_Address & theaddress)
|
||||
{
|
||||
_socket = DO_NEWTCP();
|
||||
if (_socket == BAD_SOCKET)
|
||||
return false;
|
||||
|
||||
if (DO_CONNECT(_socket, &theaddress.GetAddressInfo()) != 0)
|
||||
return ErrorClose();
|
||||
|
||||
|
||||
_ssl = SSL_new (global_ssl_ctx);
|
||||
if(_ssl == NULL)
|
||||
return false;
|
||||
SSL_set_fd (_ssl,(int)GetSocket() );
|
||||
if(SSL_connect(_ssl) == -1)
|
||||
return false;
|
||||
return true;
|
||||
|
||||
//return SetSslUp();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_TCP_SSL::SendData
|
||||
// Description : Ok Lets Send the Data
|
||||
//
|
||||
// Return type : int
|
||||
// - if error
|
||||
// 0 if socket closed for write or lengh is 0
|
||||
// + bytes writen ( May be smaller than requested)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline int Socket_TCP_SSL::SendData(const char * data, int size)
|
||||
{
|
||||
if(_ssl == NULL)
|
||||
return -1;
|
||||
|
||||
// ERR_clear_error();
|
||||
|
||||
return SSL_write(_ssl, data, size);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_TCP_SSL::RecvData
|
||||
// Description : Read the data from the connection
|
||||
//
|
||||
// Return type : int
|
||||
// - if error
|
||||
// 0 if socket closed for read or length is 0
|
||||
// + bytes read ( May be smaller than requested)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline int Socket_TCP_SSL::RecvData(char * data, int len)
|
||||
{
|
||||
if(_ssl == NULL)
|
||||
return -1;
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
return SSL_read(_ssl, data, len);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : ErrorIs_WouldBlocking
|
||||
// Description : Is last error a blocking error ??
|
||||
//
|
||||
// Return type : Bool
|
||||
// True is last error was a blocking error
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_TCP_SSL::ErrorIs_WouldBlocking(int err)
|
||||
{
|
||||
if(_ssl == NULL || err >= 0)
|
||||
{
|
||||
LOGWARNING("Socket_TCP_SSL::ErrorIs_WouldBlocking->Called With Error numebr %d or _ssl is NULL",err);
|
||||
return false;
|
||||
}
|
||||
|
||||
int ssl_error_code = SSL_get_error(_ssl,err);
|
||||
bool answer = false;
|
||||
|
||||
switch(ssl_error_code)
|
||||
{
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
case SSL_ERROR_WANT_CONNECT:
|
||||
// case SSL_ERROR_WANT_ACCEPT:
|
||||
answer = true;
|
||||
break;
|
||||
// hmm not sure we need this .. hmmmm
|
||||
case SSL_ERROR_SYSCALL:
|
||||
if(GETERROR() == LOCAL_BLOCKING_ERROR)
|
||||
answer = true;
|
||||
else
|
||||
{
|
||||
DetailErrorFormat();
|
||||
// LOGWARNING("Socket_TCP_SSL::ErrorIs_WouldBlocking-> Not A blocking Error1 SSl_CODe=[%d] OS=[%d]",ssl_error_code,GETERROR());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DetailErrorFormat();
|
||||
// LOGWARNING("Socket_TCP_SSL::ErrorIs_WouldBlocking-> Not A blocking Error2 SSl_CODe=[%d] OS=[%d]",ssl_error_code,GETERROR());
|
||||
answer = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// ERR_clear_error();
|
||||
return answer;
|
||||
}
|
||||
|
||||
inline void Socket_TCP_SSL::DetailErrorFormat(void)
|
||||
{
|
||||
return; // turn on fir debuging
|
||||
|
||||
UINT32 l;
|
||||
char buf[256];
|
||||
char buf2[4096];
|
||||
const char *file,*data;
|
||||
int line,flags;
|
||||
UINT32 es;
|
||||
|
||||
es=CRYPTO_thread_id();
|
||||
while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0)
|
||||
{
|
||||
ERR_error_string_n(l, buf, sizeof( buf) );
|
||||
BIO_snprintf(buf2, sizeof(buf2), "***%lu:%s:%s:%d:%s\n", es, buf,file, line, (flags & ERR_TXT_STRING) ? data : "NoText");
|
||||
LOGWARNING("Socket_TCP_SSL::DetailErrorFormat->[%s]",buf2);
|
||||
}
|
||||
}
|
||||
#endif //__SOCKET_TCP_SSL_H__
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
#ifndef __SOCKET_UDP_INCOMING_H__
|
||||
#define __SOCKET_UDP_INCOMING_H__
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Class : Socket_UDP_Incoming
|
||||
//
|
||||
// Description : Base functionality for a UDP Reader
|
||||
//
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
class Socket_UDP_Incoming : public Socket_IP
|
||||
{
|
||||
public:
|
||||
PUBLISHED:
|
||||
inline bool OpenForInput(Socket_Address & address);
|
||||
inline bool OpenForInputMCast(Socket_Address & address );
|
||||
inline bool GetPacket(char * data, int *max_len, Socket_Address & address);
|
||||
inline bool SendTo(const char * data, int len, const Socket_Address & address);
|
||||
inline bool InitNoAddress();
|
||||
inline bool SetToBroadCast();
|
||||
};
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_UDP_Incoming::tToBroadCast
|
||||
// Description : Flips the OS bits that allow for brodcast
|
||||
// packets to com in on this port
|
||||
//
|
||||
// Return type : bool
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Socket_UDP_Incoming::SetToBroadCast()
|
||||
{
|
||||
int optval = 1;
|
||||
|
||||
if (setsockopt(_socket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_UDP_Incoming::InitNoAddress
|
||||
// Description : Set this socket to work with out a bound external address..
|
||||
// Return type : inline bool
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Socket_UDP_Incoming::InitNoAddress()
|
||||
{
|
||||
Close();
|
||||
_socket = DO_NEWUDP();
|
||||
if (_socket == BAD_SOCKET)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_UDP_Incoming::OpenForInput
|
||||
// Description : Starts a UDP socket listening on a port
|
||||
//
|
||||
// Return type : bool
|
||||
// Argument : NetAddress & address
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_UDP_Incoming::OpenForInput(Socket_Address & address)
|
||||
{
|
||||
Close();
|
||||
_socket = DO_NEWUDP();
|
||||
if (_socket == BAD_SOCKET)
|
||||
return ErrorClose();
|
||||
|
||||
if (DO_BIND(_socket, &address.GetAddressInfo()) != 0)
|
||||
return ErrorClose();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_UDP_Incoming::OpenForInput
|
||||
// Description : Starts a UDP socket listening on a port
|
||||
//
|
||||
// Return type : bool
|
||||
// Argument : NetAddress & address
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_UDP_Incoming::OpenForInputMCast(Socket_Address & address)
|
||||
{
|
||||
Close();
|
||||
_socket = DO_NEWUDP();
|
||||
if (_socket == BAD_SOCKET)
|
||||
return ErrorClose();
|
||||
|
||||
Socket_Address wa1(address.get_port());
|
||||
if (DO_BIND(_socket, &wa1.GetAddressInfo()) != 0)
|
||||
return ErrorClose();
|
||||
|
||||
struct ip_mreq imreq;
|
||||
memset(&imreq,0,sizeof(imreq));
|
||||
imreq.imr_multiaddr.s_addr = address.GetAddressInfo().sin_addr.s_addr;
|
||||
imreq.imr_interface.s_addr = INADDR_ANY; // use DEFAULT interface
|
||||
|
||||
int status = setsockopt(GetSocket(), IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||
(const char *)&imreq, sizeof(struct ip_mreq));
|
||||
|
||||
if(status != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_UDP_Incoming::GetPacket
|
||||
// Description : Grabs a dataset off the listening UDP socket
|
||||
// and fills in the source address information
|
||||
//
|
||||
// Return type : bool
|
||||
// Argument : char * data
|
||||
// Argument : int *max_len
|
||||
// Argument : NetAddress & address
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_UDP_Incoming::GetPacket(char * data, int *max_len, Socket_Address & address)
|
||||
{
|
||||
int val = DO_RECV_FROM(_socket, data, *max_len, &address.GetAddressInfo());
|
||||
*max_len = 0;
|
||||
|
||||
if (val <= 0)
|
||||
{
|
||||
if (GetLastError() != LOCAL_BLOCKING_ERROR) // im treating a blocking error as a 0 lenght read
|
||||
return false;
|
||||
} else
|
||||
*max_len = val;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : SocketUDP_Outgoing::SendTo
|
||||
// Description : Send data to specified address
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : char * data
|
||||
// Argument : int len
|
||||
// Argument : NetAddress & address
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_UDP_Incoming::SendTo(const char * data, int len, const Socket_Address & address)
|
||||
{
|
||||
return (DO_SOCKET_WRITE_TO(_socket, data, len, &address.GetAddressInfo()) == len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //__SOCKET_UDP_INCOMING_H__
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
#ifndef __SOCKET_UDP_OUTGOING_H__
|
||||
#define __SOCKET_UDP_OUTGOING_H__
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Class : Socket_UDP_Outgoing
|
||||
//
|
||||
// Description : Base functionality for a UDP Sending Socket
|
||||
//
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
class Socket_UDP_Outgoing : public Socket_IP
|
||||
{
|
||||
public:
|
||||
PUBLISHED:
|
||||
// use this interface for a tagreted UDP connection
|
||||
inline bool InitToAddress(Socket_Address & address);
|
||||
inline bool Send(const char * data, int len);
|
||||
// use this interface for a none tagreted UDP connection
|
||||
inline bool InitNoAddress();
|
||||
inline bool SendTo(const char * data, int len, const Socket_Address & address);
|
||||
inline bool SetToBroadCast();
|
||||
};
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_UDP_Outgoing:SetToBroadCast
|
||||
// Description : Ask the OS to let us receive BROADCASt packets on this port..
|
||||
// Return type : bool
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Socket_UDP_Outgoing::SetToBroadCast()
|
||||
{
|
||||
int optval = 1;
|
||||
|
||||
if (setsockopt(_socket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_UDP_Outgoing::InitToAddress
|
||||
// Description : Connects the Socket to a Specified address
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : NetAddress & address
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_UDP_Outgoing::InitToAddress(Socket_Address & address)
|
||||
{
|
||||
if (InitNoAddress() != true)
|
||||
return false;
|
||||
|
||||
if (DO_CONNECT(_socket, &address.GetAddressInfo()) != 0)
|
||||
return ErrorClose();
|
||||
|
||||
return true;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_UDP_Outgoing::InitNoAddress
|
||||
// Description : This will set a udp up for targeted sends..
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : void
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_UDP_Outgoing::InitNoAddress()
|
||||
{
|
||||
Close();
|
||||
_socket = DO_NEWUDP();
|
||||
if (_socket == BAD_SOCKET)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_UDP_Outgoing::Send
|
||||
// Description : Send data to connected address
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : char * data
|
||||
// Argument : int len
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_UDP_Outgoing::Send(const char * data, int len)
|
||||
{
|
||||
return (DO_SOCKET_WRITE(_socket, data, len) == len);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Socket_UDP_Outgoing::SendTo
|
||||
// Description : Send data to specified address
|
||||
//
|
||||
// Return type : inline bool
|
||||
// Argument : char * data
|
||||
// Argument : int len
|
||||
// Argument : NetAddress & address
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool Socket_UDP_Outgoing::SendTo(const char * data, int len, const Socket_Address & address)
|
||||
{
|
||||
return (DO_SOCKET_WRITE_TO(_socket, data, len, &address.GetAddressInfo()) == len);
|
||||
}
|
||||
|
||||
#endif //__SOCKET_UDP_OUTGOING_H__
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
#ifndef __TIME_ACCUMULATOR_H__
|
||||
#define __TIME_ACCUMULATOR_H__
|
||||
///////////////////////////////////////////
|
||||
//
|
||||
// Think of this as a stopwatch that can be restarted.
|
||||
//
|
||||
///////////////////////////////////////////
|
||||
class Time_Accumulator
|
||||
{
|
||||
public:
|
||||
Time_Accumulator();
|
||||
~Time_Accumulator();
|
||||
|
||||
void Start();
|
||||
void Stop();
|
||||
void Reset();
|
||||
void Set(const Time_Span & in);
|
||||
|
||||
Time_Span Report();
|
||||
private:
|
||||
|
||||
Time_Span _total_time; // the collected time from previous start/stops
|
||||
Time_Clock *_accum_start; // the time of day the clock started
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// you can set the internal accumilator to a value..
|
||||
////////////////////////////////////////////////////////
|
||||
inline void Time_Accumulator::Set(const Time_Span & in)
|
||||
{
|
||||
_total_time = in;
|
||||
//
|
||||
// this seems to make the most since ..
|
||||
// if you are running the clock right know... assume the timespane you
|
||||
// are passing in is inclusive.. but keep clock running..
|
||||
//
|
||||
// May need to rethink this...
|
||||
//
|
||||
if(_accum_start != NULL)
|
||||
{
|
||||
Stop();
|
||||
Start();
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Accumulator::Time_Accumulator
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Accumulator::Time_Accumulator() : _total_time(0,0,0,0,0), _accum_start(NULL)
|
||||
{
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Accumulator::~Time_Accumulator
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Accumulator::~Time_Accumulator()
|
||||
{
|
||||
if(_accum_start != NULL)
|
||||
delete _accum_start;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : void Time_Accumulator::Start
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline void Time_Accumulator::Start()
|
||||
{
|
||||
if(_accum_start == NULL)
|
||||
_accum_start = new Time_Clock();
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : void Time_Accumulator::Stop
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline void Time_Accumulator::Stop()
|
||||
{
|
||||
if(_accum_start != NULL)
|
||||
{
|
||||
Time_Span work1(Time_Clock::GetCurrentTime() - *_accum_start);
|
||||
_total_time += work1;
|
||||
delete _accum_start;
|
||||
_accum_start = NULL;
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Accumulator::Reset
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
void Time_Accumulator::Reset()
|
||||
{
|
||||
if(_accum_start != NULL)
|
||||
{
|
||||
delete _accum_start;
|
||||
_accum_start = NULL;
|
||||
}
|
||||
_total_time.Set(0,0,0,0,0);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Accumulator::Report
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Span Time_Accumulator::Report()
|
||||
{
|
||||
Time_Span answer(_total_time);
|
||||
if(_accum_start != NULL)
|
||||
{
|
||||
Time_Span ww(Time_Clock::GetCurrentTime() - *_accum_start);
|
||||
answer += ww;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
#endif //__TIME_ACCUMULATOR_H__
|
||||
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
#ifndef __TIME_BASE_H__
|
||||
#define __TIME_BASE_H__
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Functions To support General Time Managment. And to allow for cross platform use.
|
||||
//
|
||||
//
|
||||
// Today Really Two Base classes and one convience class
|
||||
//
|
||||
// Time_Clock = The clock time down to micro seconds..
|
||||
//
|
||||
// Time_Span = Delta Time to the Mico Second..
|
||||
//
|
||||
// Time_Out = Help timer ............count down a duration.
|
||||
//
|
||||
// I realize TimeClock is really an implied delta to EPOCH. I have chosen to implement it this way.
|
||||
// it may be apropriate to convert it all to delta times with an EPOCk constant and
|
||||
// functions that can handle the EPOCK to current time.
|
||||
// All though this is probably the "right" implementation most coders do not
|
||||
// think of clock time in this fashon.
|
||||
//
|
||||
//
|
||||
// General Observation..
|
||||
//
|
||||
// Windows 2k and Linux are really slow (~250k a sec) at returning the current system time ??
|
||||
// So use time functions that grab the current system time sparingly ??
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#include <wtypes.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/timeb.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <string>
|
||||
#include <assert.h>
|
||||
|
||||
enum { USEC = 1000000 };
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : NormalizeTime
|
||||
// Description :
|
||||
// Return type : inline void
|
||||
// Argument : timeval &in
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline void NormalizeTime(timeval &in)
|
||||
{
|
||||
while (in.tv_usec >= USEC)
|
||||
{
|
||||
in.tv_usec -= USEC;
|
||||
in.tv_sec++;
|
||||
}
|
||||
|
||||
while (in.tv_usec < 0)
|
||||
{
|
||||
in.tv_usec += USEC;
|
||||
in.tv_sec--;
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : TimeDif
|
||||
// Description :
|
||||
// Return type : inline void
|
||||
// Argument : const struct timeval &start
|
||||
// Argument : const struct timeval &fin
|
||||
// Argument : struct timeval &answer
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline void TimeDif(const struct timeval &start, const struct timeval &fin, struct timeval &answer)
|
||||
{
|
||||
answer.tv_usec = fin.tv_usec - start.tv_usec;
|
||||
answer.tv_sec = fin.tv_sec - start.tv_sec;
|
||||
NormalizeTime(answer);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : TimeAdd
|
||||
// Description :
|
||||
// Return type : inline void
|
||||
// Argument : const struct timeval &start
|
||||
// Argument : const struct timeval &delta
|
||||
// Argument : struct timeval &answer
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline void TimeAdd(const struct timeval &start, const struct timeval &delta, struct timeval &answer)
|
||||
{
|
||||
answer.tv_usec = start.tv_usec + delta.tv_usec;
|
||||
answer.tv_sec = start.tv_sec + delta.tv_sec;
|
||||
NormalizeTime(answer);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Lets make Windows think it is a unix machine :)
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : gettimeofday
|
||||
// Description :
|
||||
// Return type : inline int
|
||||
// Argument : struct timeval *tv
|
||||
// Argument : void * trash
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int gettimeofday(struct timeval *tv, void * trash)
|
||||
{
|
||||
struct timeb timeb;
|
||||
ftime( &timeb);
|
||||
tv->tv_sec = (long)timeb.time;
|
||||
tv->tv_usec = (unsigned int)timeb.millitm * 1000;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "time_clock.h"
|
||||
#include "time_span.h"
|
||||
#include "time_general.h"
|
||||
#include "time_out.h"
|
||||
|
||||
#endif //__TIME_BASE_H__
|
||||
|
|
@ -0,0 +1,516 @@
|
|||
#ifndef __Time_H__
|
||||
#define __Time_H__
|
||||
//////////////////////////////////////////////////////
|
||||
// Class : Time_Clock
|
||||
//
|
||||
// Description:
|
||||
// This class is to provide a consistant interface and storage to
|
||||
// clock time .. Epoch based time to the second
|
||||
//
|
||||
// jan-2000 .. rhh changinging all time to use sub second timing...
|
||||
//
|
||||
//
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
class Time_Span;
|
||||
|
||||
class Time_Clock
|
||||
{
|
||||
friend class Time_Span;
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
static Time_Clock GetCurrentTime();
|
||||
void ToCurrentTime();
|
||||
Time_Clock( timeval &in_mytime)
|
||||
{
|
||||
_my_time = in_mytime;
|
||||
};
|
||||
Time_Clock();
|
||||
Time_Clock(time_t time);
|
||||
Time_Clock(long secs, long usecs);
|
||||
Time_Clock(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, unsigned long microseconds = 0, int nDST = -1);
|
||||
Time_Clock(const Time_Clock& timeSrc);
|
||||
|
||||
inline const Time_Clock& operator=(const Time_Clock& timeSrc);
|
||||
inline const Time_Clock& operator=(time_t t);
|
||||
|
||||
// Attributes
|
||||
struct tm* GetGmtTm(struct tm* ptm = NULL) const;
|
||||
struct tm* GetLocalTm(struct tm* ptm = NULL) const;
|
||||
|
||||
time_t GetTime() const;
|
||||
int GetYear() const;
|
||||
int GetMonth() const; // month of year (1 = Jan)
|
||||
int GetDay() const; // day of month
|
||||
int GetHour() const;
|
||||
int GetMinute() const;
|
||||
int GetSecond() const;
|
||||
int GetDayOfWeek() const; // 1=Sun, 2=Mon, ..., 7=Sat
|
||||
|
||||
void Set(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, unsigned long microseconds = 0, int nDST = -1);
|
||||
|
||||
|
||||
// Operations
|
||||
// time math
|
||||
const Time_Clock& operator+=(const Time_Span &Time_Span);
|
||||
const Time_Clock& operator-=(const Time_Span &Time_Span);
|
||||
bool operator==(const Time_Clock &time) const;
|
||||
bool operator!=(const Time_Clock &time) const;
|
||||
bool operator<(const Time_Clock &time) const;
|
||||
bool operator>(const Time_Clock &time) const;
|
||||
bool operator<=(const Time_Clock &time) const;
|
||||
bool operator>=(const Time_Clock &time) const;
|
||||
|
||||
|
||||
time_t GetTime_t()
|
||||
{
|
||||
return _my_time.tv_sec;
|
||||
};
|
||||
unsigned long GetUsecPart()
|
||||
{
|
||||
return _my_time.tv_usec;
|
||||
};
|
||||
|
||||
// formatting using "C" strftime
|
||||
std::string Format(char * pFormat) const;
|
||||
std::string FormatGmt(char * pFormat) const;
|
||||
const timeval & GetTval()
|
||||
{
|
||||
return _my_time;
|
||||
};
|
||||
const timeval & GetTval() const
|
||||
{
|
||||
return _my_time;
|
||||
} ;
|
||||
private:
|
||||
struct timeval _my_time;
|
||||
};
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Time_Clock - absolute time
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::Time_Clock
|
||||
// Description : Construction from parts
|
||||
// Argument : int nYear
|
||||
// Argument : int nMonth
|
||||
// Argument : int nDay
|
||||
// Argument : int nHour
|
||||
// Argument : int nMin
|
||||
// Argument : int nSec
|
||||
// Argument : int nDST
|
||||
//////////////////////////////////////////////////////////
|
||||
inline Time_Clock::Time_Clock(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, unsigned long microseconds , int nDST)
|
||||
{
|
||||
struct tm atm;
|
||||
atm.tm_sec = nSec;
|
||||
atm.tm_min = nMin;
|
||||
atm.tm_hour = nHour;
|
||||
assert(nDay >= 1 && nDay <= 31);
|
||||
atm.tm_mday = nDay;
|
||||
assert(nMonth >= 1 && nMonth <= 12);
|
||||
atm.tm_mon = nMonth - 1; // tm_mon is 0 based
|
||||
assert(nYear >= 1900);
|
||||
atm.tm_year = nYear - 1900; // tm_year is 1900 based
|
||||
atm.tm_isdst = nDST;
|
||||
_my_time.tv_sec = (long)mktime(&atm);
|
||||
assert(_my_time.tv_sec != -1); // indicates an illegal input time
|
||||
_my_time.tv_usec = microseconds;
|
||||
assert(_my_time.tv_usec < 1000000);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::Set
|
||||
// Description :
|
||||
// Return type : inline
|
||||
// Argument : int nYear
|
||||
// Argument : int nMonth
|
||||
// Argument : int nDay
|
||||
// Argument : int nHour
|
||||
// Argument : int nMin
|
||||
// Argument : int nSec
|
||||
// Argument : unsigned long microseconds
|
||||
// Argument : int nDST
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline void Time_Clock::Set(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, unsigned long microseconds , int nDST)
|
||||
{
|
||||
struct tm atm;
|
||||
atm.tm_sec = nSec;
|
||||
atm.tm_min = nMin;
|
||||
atm.tm_hour = nHour;
|
||||
assert(nDay >= 1 && nDay <= 31);
|
||||
atm.tm_mday = nDay;
|
||||
assert(nMonth >= 1 && nMonth <= 12);
|
||||
atm.tm_mon = nMonth - 1; // tm_mon is 0 based
|
||||
assert(nYear >= 1900);
|
||||
atm.tm_year = nYear - 1900; // tm_year is 1900 based
|
||||
atm.tm_isdst = nDST;
|
||||
_my_time.tv_sec = (long)mktime(&atm);
|
||||
assert(_my_time.tv_sec != -1); // indicates an illegal input time
|
||||
_my_time.tv_usec = microseconds;
|
||||
assert(_my_time.tv_usec < 1000000);
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::GetCurrentTime
|
||||
// Description : The Default no param constructor.. Will set time to current system time
|
||||
// Return type : Time_Clock
|
||||
//////////////////////////////////////////////////////////
|
||||
inline Time_Clock Time_Clock::GetCurrentTime()
|
||||
{
|
||||
return Time_Clock();
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::Time_Clock
|
||||
// Description :
|
||||
// Return type : inline
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Clock::Time_Clock()
|
||||
{
|
||||
gettimeofday(&_my_time, NULL);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::ToCurrentTime
|
||||
// Description : Load this object with the current OS time
|
||||
// Return type : inline void
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline void Time_Clock::ToCurrentTime()
|
||||
{
|
||||
gettimeofday(&_my_time, NULL);
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::GetGmtTm
|
||||
// Description : Access the stored time and convers to a struct tm format
|
||||
// If storage location is specified then it will stor information in the
|
||||
// provided buffer else it will use the library's internal buffer space
|
||||
// Return type : struct tm*
|
||||
// Argument : struct tm* ptm
|
||||
//////////////////////////////////////////////////////////
|
||||
inline struct tm* Time_Clock::GetGmtTm(struct tm* ptm) const
|
||||
{
|
||||
if (ptm != NULL)
|
||||
{
|
||||
*ptm = *gmtime((const time_t *)&_my_time.tv_sec);
|
||||
return ptm;
|
||||
} else
|
||||
return gmtime((const time_t *)&_my_time.tv_sec);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::GetLocalTm
|
||||
// Description : Gets The local time in a tm structre from the internal time value
|
||||
//
|
||||
// Return type : struct tm*
|
||||
// Argument : struct tm* ptm
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline struct tm* Time_Clock::GetLocalTm(struct tm* ptm) const
|
||||
{
|
||||
if (ptm != NULL)
|
||||
{
|
||||
struct tm* ptmTemp = localtime((const time_t *)&_my_time.tv_sec);
|
||||
if (ptmTemp == NULL)
|
||||
return NULL; // indicates the _my_time.tv_sec was not initialized!
|
||||
*ptm = *ptmTemp;
|
||||
return ptm;
|
||||
} else
|
||||
return localtime((const time_t *)&_my_time.tv_sec);
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// String formatting
|
||||
#define maxTimeBufferSize 4096
|
||||
// Verifies will fail if the needed buffer size is too large
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::Format
|
||||
// Description : Used to allow access to the "C" library strftime functions..
|
||||
//
|
||||
// Return type : std::string
|
||||
// Argument : char * pFormat
|
||||
//////////////////////////////////////////////////////////
|
||||
inline std::string Time_Clock::Format(char * pFormat) const
|
||||
{
|
||||
|
||||
char szBuffer[maxTimeBufferSize];
|
||||
char ch, ch1;
|
||||
char * pch = szBuffer;
|
||||
|
||||
while ((ch = *pFormat++) != '\0')
|
||||
{
|
||||
assert(pch < &szBuffer[maxTimeBufferSize]);
|
||||
if (ch == '%')
|
||||
{
|
||||
switch (ch1 = *pFormat++)
|
||||
{
|
||||
default:
|
||||
*pch++ = ch;
|
||||
*pch++ = ch1;
|
||||
break;
|
||||
case 'N':
|
||||
pch += sprintf(pch, "%03d", _my_time.tv_usec / 1000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*pch++ = ch;
|
||||
}
|
||||
}
|
||||
|
||||
*pch = '\0';
|
||||
|
||||
char szBuffer1[maxTimeBufferSize];
|
||||
|
||||
struct tm* ptmTemp = localtime((const time_t *)&_my_time.tv_sec);
|
||||
if (ptmTemp == NULL ||
|
||||
!strftime(szBuffer1, sizeof(szBuffer1), szBuffer, ptmTemp))
|
||||
szBuffer1[0] = '\0';
|
||||
return std::string(szBuffer1);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::FormatGmt
|
||||
// Description : A Wraper to
|
||||
//
|
||||
// size_t strftime( char *strDest, size_t maxsize, const char *format, const struct tm *timeptr );
|
||||
//
|
||||
// Return type : inline std::string
|
||||
// Argument : char * pFormat
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline std::string Time_Clock::FormatGmt(char * pFormat) const
|
||||
{
|
||||
|
||||
char szBuffer[maxTimeBufferSize];
|
||||
char ch, ch1;
|
||||
char * pch = szBuffer;
|
||||
|
||||
while ((ch = *pFormat++) != '\0')
|
||||
{
|
||||
assert(pch < &szBuffer[maxTimeBufferSize]);
|
||||
if (ch == '%')
|
||||
{
|
||||
switch (ch1 = *pFormat++)
|
||||
{
|
||||
default:
|
||||
*pch++ = ch;
|
||||
*pch++ = ch1;
|
||||
break;
|
||||
case 'N':
|
||||
pch += sprintf(pch, "%03d", _my_time.tv_usec / 1000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*pch++ = ch;
|
||||
}
|
||||
}
|
||||
*pch = '\0';
|
||||
|
||||
char szBuffer1[maxTimeBufferSize];
|
||||
|
||||
struct tm* ptmTemp = gmtime((const time_t *)&_my_time.tv_sec);
|
||||
if (ptmTemp == NULL ||
|
||||
!strftime(szBuffer1, sizeof(szBuffer1), szBuffer, ptmTemp))
|
||||
szBuffer1[0] = '\0';
|
||||
return std::string(szBuffer1);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::Time_Clock
|
||||
// Description : The Constructor that take a time_t objext
|
||||
// Return type : inline
|
||||
// Argument : time_t time
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Clock::Time_Clock(time_t time)
|
||||
{
|
||||
_my_time.tv_sec = (long)time;
|
||||
_my_time.tv_usec = 0;
|
||||
};
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::Time_Clock
|
||||
// Description : Constructor that takes in sec and usecs..
|
||||
// Return type : inline
|
||||
// Argument : long secs
|
||||
// Argument : long usecs
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Clock::Time_Clock(long secs, long usecs)
|
||||
{
|
||||
_my_time.tv_sec = secs;
|
||||
_my_time.tv_usec = usecs;
|
||||
NormalizeTime(_my_time);
|
||||
};
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::Time_Clock
|
||||
// Description : yet another constructor
|
||||
// Return type : inline
|
||||
// Argument : const Time_Clock& timeSrc
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Clock::Time_Clock(const Time_Clock& timeSrc)
|
||||
{
|
||||
_my_time.tv_sec = timeSrc._my_time.tv_sec;
|
||||
_my_time.tv_usec = timeSrc._my_time.tv_usec;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::operator==
|
||||
// Description : .. is time equal
|
||||
// Return type : inline bool
|
||||
// Argument : const Time_Clock &time
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Time_Clock::operator==(const Time_Clock &time) const
|
||||
{
|
||||
return ((_my_time.tv_sec == time._my_time.tv_sec) && (_my_time.tv_usec == time._my_time.tv_usec));
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::operator!=
|
||||
// Description : .is time !=
|
||||
// Return type : inline bool
|
||||
// Argument : const Time_Clock &time
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Time_Clock::operator!=(const Time_Clock &time) const
|
||||
{
|
||||
return ((_my_time.tv_sec != time._my_time.tv_sec) || (_my_time.tv_usec != time._my_time.tv_usec));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::operator<
|
||||
// Description :
|
||||
// Return type : inline bool
|
||||
// Argument : const Time_Clock &time
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Time_Clock::operator<(const Time_Clock &time) const
|
||||
{
|
||||
return ((_my_time.tv_sec < time._my_time.tv_sec) ||
|
||||
((_my_time.tv_sec == time._my_time.tv_sec) && (_my_time.tv_usec < time._my_time.tv_usec)));
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::operator>
|
||||
// Description :
|
||||
// Return type : inline bool
|
||||
// Argument : const Time_Clock &time
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Time_Clock::operator>(const Time_Clock &time) const
|
||||
{
|
||||
return ((_my_time.tv_sec > time._my_time.tv_sec) ||
|
||||
((_my_time.tv_sec == time._my_time.tv_sec) && (_my_time.tv_usec > time._my_time.tv_usec)));
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::operator<=
|
||||
// Description :
|
||||
// Return type : inline bool
|
||||
// Argument : const Time_Clock &time
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Time_Clock::operator<=(const Time_Clock &time) const
|
||||
{
|
||||
return ((_my_time.tv_sec < time._my_time.tv_sec) ||
|
||||
((_my_time.tv_sec == time._my_time.tv_sec) && (_my_time.tv_usec <= time._my_time.tv_usec)));
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::operator>=
|
||||
// Description :
|
||||
// Return type : inline bool
|
||||
// Argument : const Time_Clock &time
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Time_Clock::operator>=(const Time_Clock &time) const
|
||||
{
|
||||
return ((_my_time.tv_sec > time._my_time.tv_sec) ||
|
||||
((_my_time.tv_sec == time._my_time.tv_sec) && (_my_time.tv_usec >= time._my_time.tv_usec)));
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock& Time_Clock::operator=
|
||||
// Description :
|
||||
// Return type : inline const
|
||||
// Argument : const Time_Clock& timeSrc
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline const Time_Clock& Time_Clock::operator=(const Time_Clock& timeSrc)
|
||||
{
|
||||
if (&timeSrc == this)
|
||||
return * this;
|
||||
|
||||
_my_time = timeSrc._my_time;
|
||||
return *this;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock& Time_Clock::operator=
|
||||
// Description :
|
||||
// Return type : inline const
|
||||
// Argument : time_t t
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline const Time_Clock& Time_Clock::operator=(time_t t)
|
||||
{
|
||||
_my_time.tv_sec = (long)t;
|
||||
_my_time.tv_usec = 0;
|
||||
return *this;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::GetTime
|
||||
// Description :
|
||||
// Return type : inline time_t
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline time_t Time_Clock::GetTime() const
|
||||
{
|
||||
return _my_time.tv_sec;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::GetYear
|
||||
// Description :
|
||||
// Return type : inline int
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int Time_Clock::GetYear() const
|
||||
{
|
||||
return (GetLocalTm(NULL)->tm_year) + 1900;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::GetMonth
|
||||
// Description :
|
||||
// Return type : inline int
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int Time_Clock::GetMonth() const
|
||||
{
|
||||
return GetLocalTm(NULL)->tm_mon + 1;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::GetDay
|
||||
// Description :
|
||||
// Return type : inline int
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int Time_Clock::GetDay() const
|
||||
{
|
||||
return GetLocalTm(NULL)->tm_mday;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::GetHour
|
||||
// Description :
|
||||
// Return type : inline int
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int Time_Clock::GetHour() const
|
||||
{
|
||||
return GetLocalTm(NULL)->tm_hour;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::GetMinute
|
||||
// Description :
|
||||
// Return type : inline int
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int Time_Clock::GetMinute() const
|
||||
{
|
||||
return GetLocalTm(NULL)->tm_min;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::GetSecond
|
||||
// Description :
|
||||
// Return type : inline int
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int Time_Clock::GetSecond() const
|
||||
{
|
||||
return GetLocalTm(NULL)->tm_sec;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock::GetDayOfWeek
|
||||
// Description :
|
||||
// Return type : inline int
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int Time_Clock::GetDayOfWeek() const
|
||||
{
|
||||
return GetLocalTm(NULL)->tm_wday + 1;
|
||||
}
|
||||
|
||||
#endif //__Time_H__
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
#ifndef __TIME_GENERAL_H__
|
||||
#define __TIME_GENERAL_H__
|
||||
|
||||
|
||||
Time_Span TimeDifference(const Time_Clock &time1, const Time_Clock &time2);
|
||||
Time_Clock TimeDifference( const Time_Clock &time1, const Time_Span &Time_Span);
|
||||
Time_Clock TimeAddition(const Time_Clock &time1, Time_Span &Time_Span);
|
||||
|
||||
|
||||
Time_Clock operator+(const Time_Clock &tm, const Time_Span &ts);
|
||||
Time_Clock operator-(const Time_Clock &tm, const Time_Span &ts);
|
||||
|
||||
|
||||
bool SetFromTimeStr(const char * str, Time_Clock & outtime);
|
||||
std::string GetTimeStr(const Time_Clock & intime);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : TimeDifference
|
||||
// Description :
|
||||
// Return type : inline Time_Span
|
||||
// Argument : const Time_Clock &time1
|
||||
// Argument : const Time_Clock &time2
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Span TimeDifference(const Time_Clock &time1, const Time_Clock &time2)
|
||||
{
|
||||
timeval ans;
|
||||
TimeDif(time2.GetTval(), time1.GetTval(), ans);
|
||||
return Time_Span(ans);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : TimeDifference
|
||||
// Description :
|
||||
// Return type :
|
||||
// Argument : const Time_Clock &time1
|
||||
// Argument : const Time_Span &Time_Span
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Clock TimeDifference( const Time_Clock &time1, const Time_Span &Time_Span)
|
||||
{
|
||||
timeval ans;
|
||||
TimeDif(Time_Span.GetTval(), time1.GetTval(), ans);
|
||||
return Time_Clock(ans);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : TimeAddition
|
||||
// Description :
|
||||
// Return type :
|
||||
// Argument : const Time_Clock &time1
|
||||
// Argument : Time_Span &Time_Span
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Clock TimeAddition(const Time_Clock &time1, Time_Span &Time_Span)
|
||||
{
|
||||
timeval ans;
|
||||
TimeAdd(time1.GetTval(), Time_Span.GetTval(), ans);
|
||||
return Time_Clock(ans);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock& Time_Clock::operator+=
|
||||
// Description :
|
||||
// Return type : inline const
|
||||
// Argument : Time_Span &Time_Span
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline const Time_Clock& Time_Clock::operator+=(const Time_Span &Time_Span)
|
||||
{
|
||||
_my_time.tv_usec += Time_Span._my_time.tv_usec;
|
||||
_my_time.tv_sec += Time_Span._my_time.tv_sec;
|
||||
NormalizeTime(_my_time);
|
||||
return *this;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : operator+
|
||||
// Description :
|
||||
// Return type : inline Time_Clock
|
||||
// Argument : const Time_Clock &tm
|
||||
// Argument : const Time_Span &ts
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Clock operator+(const Time_Clock &tm, const Time_Span &ts)
|
||||
{
|
||||
Time_Clock work(tm);
|
||||
work += ts;
|
||||
return work;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : operator-
|
||||
// Description :
|
||||
// Return type : inline Time_Clock
|
||||
// Argument : const Time_Clock &tm
|
||||
// Argument : const Time_Span &ts
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Clock operator-(const Time_Clock &tm, const Time_Span &ts)
|
||||
{
|
||||
return TimeDifference(tm, ts);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Clock& Time_Clock::operator-=
|
||||
// Description :
|
||||
// Return type : inline const
|
||||
// Argument : Time_Span &Time_Span
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline const Time_Clock& Time_Clock::operator-=(const Time_Span &Time_Span)
|
||||
{
|
||||
_my_time.tv_usec -= Time_Span._my_time.tv_usec;
|
||||
_my_time.tv_sec -= Time_Span._my_time.tv_sec;
|
||||
NormalizeTime(_my_time);
|
||||
return *this;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : operator-
|
||||
// Description :
|
||||
// Return type : inline Time_Span
|
||||
// Argument : const Time_Clock &tm1
|
||||
// Argument : const Time_Clock &tm2
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Span operator-(const Time_Clock &tm1, const Time_Clock &tm2)
|
||||
{
|
||||
return TimeDifference(tm1, tm2);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : char * GetTimeStr
|
||||
// Description :
|
||||
// Return type : inline const
|
||||
// Argument : const Time_Clock & intime
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline std::string GetTimeStr(const Time_Clock & intime)
|
||||
{
|
||||
static std::string ts;
|
||||
static Time_Clock prev_time;
|
||||
|
||||
if (prev_time != intime || ts.empty())
|
||||
{
|
||||
ts = intime.Format("%Y-%m-%d %H:%M:%S");
|
||||
prev_time = intime;
|
||||
}
|
||||
return ts;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : GetTimeStr
|
||||
// Description :
|
||||
// Return type : inline std::string
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline std::string GetTimeStr()
|
||||
{
|
||||
return GetTimeStr(Time_Clock::GetCurrentTime());
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : SetFromTimeStr
|
||||
// Description :
|
||||
// Return type : inline bool
|
||||
// Argument : const char * str
|
||||
// Argument : Time_Clock & outtime
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool SetFromTimeStr(const char * str, Time_Clock & outtime)
|
||||
{
|
||||
int year = 0;
|
||||
int month = 0;
|
||||
int day = 0;
|
||||
int hour = 0;
|
||||
int min = 0;
|
||||
int sec = 0;
|
||||
|
||||
if (sscanf(str, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &min, &sec) != 6)
|
||||
return false;
|
||||
|
||||
outtime.Set(year, month, day, hour, min, sec);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif //__TIME_GENERAL_H__
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
#ifndef __TIME_OUT_H__
|
||||
#define __TIME_OUT_H__
|
||||
|
||||
///////////////////////////////////////
|
||||
//
|
||||
// think of this class as a time based alarm..
|
||||
//
|
||||
// would be nice to have a template implementation of this class .. could avoud some storage and some math ..
|
||||
//
|
||||
// I would do this but not sure how to represent the duration in the template ??
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class Time_Out
|
||||
{
|
||||
public:
|
||||
Time_Out()
|
||||
{
|
||||
}
|
||||
|
||||
Time_Out(const Time_Span & dur) : _alarm_time(Time_Clock::GetCurrentTime() + dur) , _duration(dur)
|
||||
{
|
||||
}
|
||||
/*
|
||||
Time_Out(const Time_Clock & tm, const Time_Span & dur) : _alarm_time(tm + dur) , _duration(dur)
|
||||
{
|
||||
}
|
||||
*/
|
||||
void ResetAll(const Time_Clock &tm, const Time_Span &sp);
|
||||
void ReStart();
|
||||
void ResetTime(const Time_Clock & tm);
|
||||
void SetTimeOutSec(int sec);
|
||||
|
||||
bool Expired(const Time_Clock &tm, bool reset = false);
|
||||
bool Expired(bool reset = false);
|
||||
|
||||
Time_Span Remaining(const Time_Clock & tm) const;
|
||||
Time_Span Remaining() const;
|
||||
|
||||
void ForceToExpired()
|
||||
{
|
||||
_alarm_time.ToCurrentTime();
|
||||
}
|
||||
|
||||
bool operator() (bool reset= false)
|
||||
{
|
||||
return Expired(reset);
|
||||
}
|
||||
bool operator() (const Time_Clock &tm, bool reset = false)
|
||||
{
|
||||
return Expired(tm, reset);
|
||||
}
|
||||
|
||||
Time_Clock GetAlarm(void)
|
||||
{
|
||||
return _alarm_time;
|
||||
}
|
||||
|
||||
Time_Span Duration() const { return _duration; };
|
||||
|
||||
void NextInStep(Time_Clock &curtime)
|
||||
{
|
||||
_alarm_time += _duration;
|
||||
if(_alarm_time <=curtime) // if we fall way behind.. just ratchet it up ...
|
||||
_alarm_time = curtime+_duration;
|
||||
}
|
||||
private:
|
||||
Time_Clock _alarm_time;
|
||||
Time_Span _duration;
|
||||
};
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Out::ReStart
|
||||
// Description :
|
||||
// Return type : void
|
||||
// Argument : const Time_Clock &tm
|
||||
// Argument : const Time_Span &sp
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline void Time_Out::ResetAll(const Time_Clock &tm, const Time_Span &sp)
|
||||
{
|
||||
_duration = sp;
|
||||
_alarm_time = tm + _duration;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::ReStart
|
||||
// Description :
|
||||
// Return type : void
|
||||
// Argument : const Time_Clock &tm
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline void Time_Out::SetTimeOutSec(int sec)
|
||||
{
|
||||
_duration.Set(0, 0, 0, sec, 0);
|
||||
ReStart();
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::ReStart
|
||||
// Description :
|
||||
// Return type : void
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline void Time_Out::ReStart()
|
||||
{
|
||||
_alarm_time = Time_Clock::GetCurrentTime() + _duration;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : ResetTime
|
||||
// Description :
|
||||
// Return type : void
|
||||
// Argument : const Time_Clock & tm
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline void Time_Out::ResetTime(const Time_Clock & tm)
|
||||
{
|
||||
_alarm_time = tm + _duration;
|
||||
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::Expired
|
||||
// Description :
|
||||
// Return type : bool
|
||||
// Argument : const Time_Clock &tm
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Time_Out::Expired(const Time_Clock &tm, bool reset)
|
||||
{
|
||||
bool answer = (_alarm_time <= tm) ;
|
||||
if (answer && reset)
|
||||
ResetTime(tm);
|
||||
return answer;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::Expired
|
||||
// Description :
|
||||
// Return type : bool
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Time_Out::Expired(bool reset)
|
||||
{
|
||||
return Expired(Time_Clock::GetCurrentTime(), reset);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::Remaining
|
||||
// Description :
|
||||
// Return type : Time_Span
|
||||
// Argument : const Time_Clock & tm
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Span Time_Out::Remaining(const Time_Clock & tm) const
|
||||
{
|
||||
return _alarm_time - tm;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::Remaining
|
||||
// Description :
|
||||
// Return type : Time_Span
|
||||
// Argument : void
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Span Time_Out::Remaining() const
|
||||
{
|
||||
return Remaining(Time_Clock::GetCurrentTime());
|
||||
}
|
||||
|
||||
#endif //__TIME_OUT_H__
|
||||
|
|
@ -0,0 +1,387 @@
|
|||
#ifndef __TIME_SPAN_H__
|
||||
#define __TIME_SPAN_H__
|
||||
//////////////////////////////////////////////////////
|
||||
// Class : Time_Span
|
||||
//
|
||||
// Description:
|
||||
//////////////////////////////////////////////////////
|
||||
class Time_Span
|
||||
{
|
||||
public:
|
||||
// Constructors
|
||||
Time_Span()
|
||||
{
|
||||
}
|
||||
|
||||
Time_Span(struct timeval time)
|
||||
{
|
||||
_my_time = time;NormalizeTime(_my_time);
|
||||
}
|
||||
|
||||
Time_Span(time_t time);
|
||||
Time_Span(long lDays, int nHours, int nMins, int nSecs, int usecs);
|
||||
Time_Span(long seconds, int usecs ) ;
|
||||
Time_Span(const Time_Span& Time_SpanSrc);
|
||||
Time_Span(const Time_Clock& Time_SpanSrc);
|
||||
|
||||
///////////////////
|
||||
|
||||
const Time_Span& operator=(const Time_Span& Time_SpanSrc);
|
||||
|
||||
// Attributes
|
||||
// extract parts
|
||||
long GetDays() const; // total # of days
|
||||
long GetTotalHours() const;
|
||||
int GetHours() const;
|
||||
long GetTotalMinutes() const;
|
||||
int GetMinutes() const;
|
||||
long GetTotalSeconds() const;
|
||||
int GetSeconds() const;
|
||||
long GetTotalMSeconds() const;
|
||||
long GetTotal100Seconds() const;
|
||||
long GetMSeconds() const;
|
||||
|
||||
// Operations
|
||||
// time math
|
||||
const Time_Span& operator+=(Time_Span &Time_Span);
|
||||
const Time_Span& operator-=(Time_Span &Time_Span);
|
||||
bool operator==(Time_Span &Time_Span) const;
|
||||
bool operator!=(Time_Span &Time_Span) const;
|
||||
bool operator<(Time_Span &Time_Span) const;
|
||||
bool operator>(Time_Span &Time_Span) const;
|
||||
bool operator<=(Time_Span &Time_Span) const;
|
||||
bool operator>=(Time_Span &Time_Span) const;
|
||||
const timeval & GetTval() const
|
||||
{
|
||||
return _my_time;
|
||||
}
|
||||
|
||||
|
||||
void Set(long lDays, int nHours, int nMins, int nSecs, int usecs);
|
||||
|
||||
std::string Format(char *pFormat) const;
|
||||
private:
|
||||
struct timeval _my_time;
|
||||
friend class Time_Clock;
|
||||
};
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::Time_Span
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Span::Time_Span(long seconds, int usecs)
|
||||
{
|
||||
_my_time.tv_sec = seconds;
|
||||
_my_time.tv_usec = usecs;
|
||||
NormalizeTime(_my_time);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::Time_Span
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Span::Time_Span(time_t time)
|
||||
{
|
||||
_my_time.tv_usec = 0;
|
||||
_my_time.tv_sec = (long)time;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::Time_Span
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Span::Time_Span(long lDays, int nHours, int nMins, int nSecs, int usecs)
|
||||
{
|
||||
_my_time.tv_sec = nSecs + 60 * (nMins + 60 * (nHours + 24 * lDays));
|
||||
_my_time.tv_usec = usecs;
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::Set
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline void Time_Span::Set(long lDays, int nHours, int nMins, int nSecs, int usecs)
|
||||
{
|
||||
_my_time.tv_sec = nSecs + 60 * (nMins + 60 * (nHours + 24 * lDays));
|
||||
_my_time.tv_usec = usecs;
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::Time_Span
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Span::Time_Span(const Time_Span& Time_SpanSrc)
|
||||
{
|
||||
_my_time = Time_SpanSrc._my_time;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::Time_Span
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Span::Time_Span(const Time_Clock& Time_SpanSrc)
|
||||
{
|
||||
_my_time = Time_SpanSrc._my_time;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span& Time_Span::operator=
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline const Time_Span& Time_Span::operator=(const Time_Span& Time_SpanSrc)
|
||||
{
|
||||
if (&Time_SpanSrc == this)
|
||||
return * this;
|
||||
_my_time = Time_SpanSrc._my_time; return *this;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::GetDays
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline long Time_Span::GetDays() const
|
||||
{
|
||||
return _my_time.tv_sec / (24*3600L);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::GetTotalHours
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline long Time_Span::GetTotalHours() const
|
||||
{
|
||||
return _my_time.tv_sec / 3600;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::GetHours
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int Time_Span::GetHours() const
|
||||
{
|
||||
return (int)(GetTotalHours() - GetDays()*24);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::GetTotalMinutes
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline long Time_Span::GetTotalMinutes() const
|
||||
{
|
||||
return _my_time.tv_sec / 60;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::GetMinutes
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int Time_Span::GetMinutes() const
|
||||
{
|
||||
return (int)(GetTotalMinutes() - GetTotalHours()*60);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::GetTotalSeconds
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline long Time_Span::GetTotalSeconds() const
|
||||
{
|
||||
return _my_time.tv_sec;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::GetTotalMSeconds
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline long Time_Span::GetTotalMSeconds() const
|
||||
{
|
||||
return (_my_time.tv_sec * 1000) + (_my_time.tv_usec / 1000);
|
||||
}
|
||||
|
||||
|
||||
inline long Time_Span::GetTotal100Seconds() const
|
||||
{
|
||||
return (_my_time.tv_sec * 100) + (_my_time.tv_usec / 10000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::GetTotalMSeconds
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline long Time_Span::GetMSeconds() const
|
||||
{
|
||||
return (_my_time.tv_usec / 1000);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::GetSeconds
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int Time_Span::GetSeconds() const
|
||||
{
|
||||
return (int)(GetTotalSeconds() - GetTotalMinutes()*60);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : TimeDifference
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Span TimeDifference(const Time_Span &Time_Span1, const Time_Span &Time_Span2)
|
||||
{
|
||||
timeval ans;
|
||||
TimeDif(Time_Span2.GetTval(), Time_Span1.GetTval(), ans);
|
||||
return Time_Span(ans);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : TimeAddition
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline Time_Span TimeAddition(const Time_Span &Time_Span1, const Time_Span &Time_Span2)
|
||||
{
|
||||
timeval ans;
|
||||
TimeAdd(Time_Span2.GetTval(), Time_Span1.GetTval(), ans);
|
||||
return Time_Span(ans);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span& Time_Span::operator+=
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline const Time_Span& Time_Span::operator+=(Time_Span &Time_Span)
|
||||
{
|
||||
_my_time.tv_usec += Time_Span._my_time.tv_usec;
|
||||
_my_time.tv_sec += Time_Span._my_time.tv_sec;
|
||||
NormalizeTime(_my_time);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span& Time_Span::operator-=
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline const Time_Span& Time_Span::operator-=(Time_Span &Time_Span)
|
||||
{
|
||||
_my_time.tv_usec -= Time_Span._my_time.tv_usec;
|
||||
_my_time.tv_sec -= Time_Span._my_time.tv_sec;
|
||||
NormalizeTime(_my_time);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::operator==
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Time_Span::operator==(Time_Span &Time_Span) const
|
||||
{
|
||||
return ((_my_time.tv_sec == Time_Span._my_time.tv_sec) && (_my_time.tv_usec == Time_Span._my_time.tv_usec));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::operator!=
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Time_Span::operator!=(Time_Span &Time_Span) const
|
||||
{
|
||||
return ((_my_time.tv_sec != Time_Span._my_time.tv_sec) || (_my_time.tv_usec != Time_Span._my_time.tv_usec));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::operator<
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Time_Span::operator<(Time_Span &Time_Span) const
|
||||
{
|
||||
return ((_my_time.tv_sec < Time_Span._my_time.tv_sec) ||
|
||||
((_my_time.tv_sec == Time_Span._my_time.tv_sec) && (_my_time.tv_usec < Time_Span._my_time.tv_usec)));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::operator>
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Time_Span::operator>(Time_Span &Time_Span) const
|
||||
{
|
||||
return ((_my_time.tv_sec > Time_Span._my_time.tv_sec) ||
|
||||
((_my_time.tv_sec == Time_Span._my_time.tv_sec) && (_my_time.tv_usec > Time_Span._my_time.tv_usec)));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::operator<=
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Time_Span::operator<=(Time_Span &Time_Span) const
|
||||
{
|
||||
return ((_my_time.tv_sec < Time_Span._my_time.tv_sec) ||
|
||||
((_my_time.tv_sec == Time_Span._my_time.tv_sec) && (_my_time.tv_usec <= Time_Span._my_time.tv_usec)));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::operator>=
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline bool Time_Span::operator>=(Time_Span &Time_Span) const
|
||||
{
|
||||
return ((_my_time.tv_sec > Time_Span._my_time.tv_sec) ||
|
||||
((_my_time.tv_sec == Time_Span._my_time.tv_sec) && (_my_time.tv_usec >= Time_Span._my_time.tv_usec)));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Function name : Time_Span::Format
|
||||
// Description :
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline std::string Time_Span::Format(char * pFormat) const
|
||||
// formatting Time_Spans is a little trickier than formatting
|
||||
// * we are only interested in relative time formats, ie. it is illegal
|
||||
// to format anything dealing with absolute time (i.e. years, months,
|
||||
// day of week, day of year, timezones, ...)
|
||||
// * the only valid formats:
|
||||
// %D - # of days -- NEW !!!
|
||||
// %H - hour in 24 hour format
|
||||
// %M - minute (0-59)
|
||||
// %S - seconds (0-59)
|
||||
// %% - percent sign
|
||||
// %N - nanosecs
|
||||
{
|
||||
char szBuffer[maxTimeBufferSize];
|
||||
char ch;
|
||||
char * pch = szBuffer;
|
||||
|
||||
while ((ch = *pFormat++) != '\0') {
|
||||
assert(pch < &szBuffer[maxTimeBufferSize]);
|
||||
if (ch == '%') {
|
||||
switch (ch = *pFormat++) {
|
||||
default:
|
||||
assert(false); // probably a bad format character
|
||||
case '%':
|
||||
*pch++ = ch;
|
||||
break;
|
||||
case 'D':
|
||||
pch += sprintf(pch, "%ld", GetDays());
|
||||
break;
|
||||
case 'H':
|
||||
pch += sprintf(pch, "%02d", GetHours());
|
||||
break;
|
||||
case 'M':
|
||||
pch += sprintf(pch, "%02d", GetMinutes());
|
||||
break;
|
||||
case 'S':
|
||||
pch += sprintf(pch, "%02d", GetSeconds());
|
||||
break;
|
||||
case 'N':
|
||||
pch += sprintf(pch, "%03d", _my_time.tv_usec / 1000);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
*pch++ = ch;
|
||||
}
|
||||
}
|
||||
|
||||
*pch = '\0';
|
||||
return std::string(szBuffer);
|
||||
}
|
||||
|
||||
#endif //__TIME_SPAN_H__
|
||||
Loading…
Reference in New Issue