freeswitch/libs/xmlrpc-c/include/xmlrpc-c/packetsocket.hpp

166 lines
4.6 KiB
C++

#ifndef PACKETSOCKET_HPP_INCLUDED
#define PACKETSOCKET_HPP_INCLUDED
/*============================================================================
packetsocket
==============================================================================
This is a facility for communicating socket-style, with defined
packets like a datagram socket but with reliable delivery like a
stream socket. It's like a POSIX "sequential packet" socket, except
it is built on top of a stream socket, so it is usable on the many
systems that have stream sockets but not sequential packet sockets.
============================================================================*/
#include <sys/types.h>
#include <string>
#include <queue>
#include <xmlrpc-c/girmem.hpp>
namespace xmlrpc_c {
class packet : public girmem::autoObject {
public:
packet();
packet(const unsigned char * const data,
size_t const dataLength);
packet(const char * const data,
size_t const dataLength);
~packet();
unsigned char *
getBytes() const { return this->bytes; }
size_t
getLength() const { return this->length; }
void
addData(const unsigned char * const data,
size_t const dataLength);
private:
unsigned char * bytes; // malloc'ed
size_t length;
size_t allocSize;
void
initialize(const unsigned char * const data,
size_t const dataLength);
};
class packetPtr: public girmem::autoObjectPtr {
public:
packetPtr();
explicit packetPtr(packet * const packetP);
packet *
operator->() const;
};
class packetSocket {
/*----------------------------------------------------------------------------
This is an Internet communication vehicle that transmits individual
variable-length packets of text.
It is based on a stream socket.
It would be much better to use a kernel SOCK_SEQPACKET socket, but
Linux 2.4 does not have them.
-----------------------------------------------------------------------------*/
public:
packetSocket(int sockFd);
~packetSocket();
void
writeWait(packetPtr const& packetPtr) const;
void
read(bool * const eofP,
bool * const gotPacketP,
packetPtr * const packetPP);
void
readWait(volatile const int * const interruptP,
bool * const eofP,
bool * const gotPacketP,
packetPtr * const packetPP);
void
readWait(volatile const int * const interruptP,
bool * const eofP,
packetPtr * const packetPP);
void
readWait(bool * const eofP,
packetPtr * const packetPP);
private:
int sockFd;
// The kernel stream socket we use.
bool eof;
// The packet socket is at end-of-file for reads.
// 'readBuffer' is empty and there won't be any more data to fill
// it because the underlying stream socket is closed.
std::queue<packetPtr> readBuffer;
packetPtr packetAccumP;
// The receive packet we're currently accumulating; it will join
// 'readBuffer' when we've received the whole packet (and we've
// seen the END escape sequence so we know we've received it all).
// If we're not currently accumulating a packet (haven't seen a
// PKT escape sequence), this points to nothing.
bool inEscapeSeq;
// In our trek through the data read from the underlying stream
// socket, we are after an ESC character and before the end of the
// escape sequence. 'escAccum' shows what of the escape sequence
// we've seen so far.
bool inPacket;
// We're now receiving packet data from the underlying stream
// socket. We've seen a complete PKT escape sequence, but have not
// seen a complete END escape sequence since.
struct {
unsigned char bytes[3];
size_t len;
} escAccum;
void
bufferFinishedPacket();
void
takeSomeEscapeSeq(const unsigned char * const buffer,
size_t const length,
size_t * const bytesTakenP);
void
takeSomePacket(const unsigned char * const buffer,
size_t const length,
size_t * const bytesTakenP);
void
verifyNothingAccumulated();
void
processBytesRead(const unsigned char * const buffer,
size_t const bytesRead);
void
readFromFile();
};
} // namespace
#endif