aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorFritz Elfert <felfert@to.com>1999-06-28 08:56:01 +0000
committerFritz Elfert <felfert@to.com>1999-06-28 08:56:01 +0000
commit34b70b0b46e34a73308a4034cc9b1c70209b9eb4 (patch)
tree7abe8be40fde08828d3606e13c41435b2fc9a26c /lib
parent3d3be141551bb4622da1cb610e4f6f798dd1715e (diff)
downloadplptools-34b70b0b46e34a73308a4034cc9b1c70209b9eb4.tar.gz
plptools-34b70b0b46e34a73308a4034cc9b1c70209b9eb4.tar.bz2
plptools-34b70b0b46e34a73308a4034cc9b1c70209b9eb4.zip
First import.
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am3
-rw-r--r--lib/bool.h20
-rw-r--r--lib/bufferarray.cc68
-rw-r--r--lib/bufferarray.h25
-rw-r--r--lib/bufferstore.cc166
-rw-r--r--lib/bufferstore.h50
-rw-r--r--lib/iowatch.cc77
-rw-r--r--lib/iowatch.h21
-rw-r--r--lib/ppsocket.cc863
-rw-r--r--lib/ppsocket.h117
10 files changed, 1410 insertions, 0 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644
index 0000000..ec2faee
--- /dev/null
+++ b/lib/Makefile.am
@@ -0,0 +1,3 @@
+noinst_LIBRARIES = libutils.a
+
+libutils_a_SOURCES = bufferarray.cc bufferstore.cc iowatch.cc ppsocket.cc
diff --git a/lib/bool.h b/lib/bool.h
new file mode 100644
index 0000000..7525d6c
--- /dev/null
+++ b/lib/bool.h
@@ -0,0 +1,20 @@
+#ifndef _bool_h_
+#define _bool_h_
+
+#ifndef __GNUC__
+
+#ifndef bool
+#define bool int
+#endif
+
+#ifndef true
+#define true 1
+#endif
+
+#ifndef false
+#define false 0
+#endif
+
+#endif
+
+#endif
diff --git a/lib/bufferarray.cc b/lib/bufferarray.cc
new file mode 100644
index 0000000..4dc3971
--- /dev/null
+++ b/lib/bufferarray.cc
@@ -0,0 +1,68 @@
+//
+// PLP - An implementation of the PSION link protocol
+//
+// Copyright (C) 1999 Philip Proudman
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// e-mail philip.proudman@btinternet.com
+
+
+#include <stdio.h>
+
+#include "bufferstore.h"
+#include "bufferarray.h"
+
+bufferArray::bufferArray() {
+ len = 0;
+ lenAllocd = 5;
+ buff = new bufferStore [lenAllocd];
+}
+
+bufferArray::bufferArray(const bufferArray &a) {
+ len = a.len;
+ lenAllocd = a.lenAllocd;
+ buff = new bufferStore [lenAllocd];
+ for (int i=0; i < len; i++) buff[i] = a.buff[i];
+}
+
+bufferArray::~bufferArray() {
+ delete [] buff;
+}
+
+bufferStore bufferArray::popBuffer() {
+ bufferStore ret;
+ if (len > 0) {
+ ret = buff[0];
+ len--;
+ for (long i=0; i<len; i++) {
+ buff[i] = buff[i+1];
+ }
+ }
+ return ret;
+}
+
+void bufferArray::pushBuffer(const bufferStore &b) {
+ if (len == lenAllocd) {
+ lenAllocd += 5;
+ bufferStore* nb = new bufferStore [lenAllocd];
+ for (long i=0; i<len; i++) {
+ nb[i] = buff[i];
+ }
+ delete [] buff;
+ buff = nb;
+ }
+ buff[len++] = b;
+}
diff --git a/lib/bufferarray.h b/lib/bufferarray.h
new file mode 100644
index 0000000..089eb4e
--- /dev/null
+++ b/lib/bufferarray.h
@@ -0,0 +1,25 @@
+#ifndef _bufferarray_h
+#define _bufferarray_h
+
+#include "bool.h"
+class bufferStore;
+
+class bufferArray {
+public:
+ bufferArray();
+ bufferArray(const bufferArray &a);
+ ~bufferArray();
+ void operator =(const bufferArray &a);
+
+ bool empty() const;
+ bufferStore popBuffer();
+ void pushBuffer(const bufferStore& b);
+private:
+ long len;
+ long lenAllocd;
+ bufferStore* buff;
+};
+
+inline bool bufferArray::empty() const { return len == 0; }
+
+#endif
diff --git a/lib/bufferstore.cc b/lib/bufferstore.cc
new file mode 100644
index 0000000..8138ad2
--- /dev/null
+++ b/lib/bufferstore.cc
@@ -0,0 +1,166 @@
+//
+// PLP - An implementation of the PSION link protocol
+//
+// Copyright (C) 1999 Philip Proudman
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// e-mail philip.proudman@btinternet.com
+
+#include <stream.h>
+#include <iomanip.h>
+#include <string.h>
+
+#include "bufferstore.h"
+
+bufferStore::bufferStore() {
+ lenAllocd = 0;
+ buff = NULL;
+ len = 0;
+ start = 0;
+}
+
+bufferStore::bufferStore(const bufferStore &a) {
+ lenAllocd = (a.getLen() > MIN_LEN) ? a.getLen() : MIN_LEN;
+ buff = new unsigned char [lenAllocd];
+ len = a.getLen();
+ for (long i=0; i<len; i++) buff[i] = a.getByte(i);
+ start = 0;
+}
+
+bufferStore::bufferStore(const unsigned char*_buff, long _len) {
+ lenAllocd = (_len > MIN_LEN) ? _len : MIN_LEN;
+ buff = new unsigned char [lenAllocd];
+ len = _len;
+ for (long i=0; i<len; i++) buff[i] = _buff[i];
+ start = 0;
+}
+
+void bufferStore::operator =(const bufferStore &a) {
+ checkAllocd(a.getLen());
+ len = a.getLen();
+ for (long i=0; i<len; i++) buff[i] = a.getByte(i);
+ start = 0;
+}
+
+void bufferStore::init() {
+ start = 0;
+ len = 0;
+}
+
+void bufferStore::init(const unsigned char*_buff, long _len) {
+ checkAllocd(_len);
+ start = 0;
+ len = _len;
+ for (long i=0; i<len; i++) buff[i] = _buff[i];
+}
+
+bufferStore::~bufferStore() {
+ delete [] buff;
+}
+
+unsigned long bufferStore::getLen() const {
+ if (start > len) return 0;
+ return len - start;
+}
+
+unsigned char bufferStore::getByte(long pos) const {
+ return buff[pos+start];
+}
+
+unsigned int bufferStore::getWord(long pos) const {
+ return buff[pos+start] + (buff[pos+start+1] << 8);
+}
+
+unsigned int bufferStore::getDWord(long pos) const {
+ return buff[pos+start] +
+ (buff[pos+start+1] << 8) +
+ (buff[pos+start+2] << 16) +
+ (buff[pos+start+3] << 24);
+}
+
+const char* bufferStore::getString(long pos) const {
+ return (const char*)buff+pos+start;
+}
+
+ostream &operator<<(ostream &s, const bufferStore &m) {
+ {
+ for (int i = m.start; i < m.len; i++)
+ s << hex << setw(2) << setfill('0') << (int)m.buff[i] << " ";
+ }
+ s << "(";
+ {
+ for (int i = m.start; i < m.len; i++) {
+ unsigned char c = m.buff[i];
+ if (c>=' ' && c <= 'z') s << c;
+ }
+ }
+ s<< ")";
+ return s;
+}
+
+void bufferStore::discardFirstBytes(int n) {
+ start += n;
+ if (start > len) start = len;
+}
+
+void bufferStore::checkAllocd(long newLen) {
+ if (newLen >= lenAllocd) {
+ do {
+ if (lenAllocd < MIN_LEN)
+ lenAllocd = MIN_LEN;
+ else
+ lenAllocd *= 2;
+ } while (newLen >= lenAllocd);
+ unsigned char* newBuff = new unsigned char [lenAllocd];
+ for (int i=start; i<len; i++) newBuff[i] = buff[i];
+ delete [] buff;
+ buff = newBuff;
+ }
+}
+
+void bufferStore::addByte(unsigned char cc) {
+ checkAllocd(len + 1);
+ buff[len++] = cc;
+}
+
+void bufferStore::addString(const char* s) {
+ checkAllocd(len + strlen(s));
+ for (int i=0; s[i]; i++) buff[len++] = s[i];
+}
+
+void bufferStore::addStringT(const char* s) {
+ addString(s);
+ addByte(0);
+}
+
+void bufferStore::addBuff(const bufferStore &s, long maxLen) {
+ checkAllocd(len + s.getLen());
+ for (unsigned long i=0; i < s.getLen() && (maxLen < 0 || i < (unsigned long)maxLen); i++) buff[len++] = s.getByte(i);
+}
+
+void bufferStore::addWord(int a) {
+ checkAllocd(len + 2);
+ buff[len++] = a & 0xff;
+ buff[len++] = (a>>8) & 0xff;
+}
+
+void bufferStore::addDWord(long a) {
+ checkAllocd(len + 4);
+ buff[len++] = a & 0xff;
+ buff[len++] = (a>>8) & 0xff;
+ buff[len++] = (a>>16) & 0xff;
+ buff[len++] = (a>>24) & 0xff;
+}
diff --git a/lib/bufferstore.h b/lib/bufferstore.h
new file mode 100644
index 0000000..4840689
--- /dev/null
+++ b/lib/bufferstore.h
@@ -0,0 +1,50 @@
+#ifndef _bufferstore_h
+#define _bufferstore_h
+
+#include "bool.h"
+class ostream;
+
+class bufferStore {
+public:
+ bufferStore();
+ bufferStore(const unsigned char*buff, long len);
+ ~bufferStore();
+ bufferStore(const bufferStore &a);
+ void operator =(const bufferStore &a);
+
+ // Reading Utils
+ unsigned long getLen() const;
+ unsigned char getByte(long pos) const;
+ unsigned int getWord(long pos) const;
+ unsigned int getDWord(long pos) const;
+ const char* getString(long pos=0) const;
+ void discardFirstBytes(int n);
+ friend ostream &operator<<(ostream &s, const bufferStore &m);
+ bool empty() const;
+
+ // Writing utils
+ void init();
+ void init(const unsigned char*buff, long len);
+ void addByte(unsigned char c);
+ void addWord(int a);
+ void addDWord(long a);
+ void addString(const char* s);
+ void addStringT(const char* s);
+ void addBuff(const bufferStore &s, long maxLen=-1);
+
+private:
+ void checkAllocd(long newLen);
+
+ long len;
+ long lenAllocd;
+ long start;
+ unsigned char* buff;
+
+ enum c { MIN_LEN = 300 };
+};
+
+inline bool bufferStore::empty() const {
+ return (len-start) == 0;
+}
+
+#endif
diff --git a/lib/iowatch.cc b/lib/iowatch.cc
new file mode 100644
index 0000000..15e8ecf
--- /dev/null
+++ b/lib/iowatch.cc
@@ -0,0 +1,77 @@
+//
+// PLP - An implementation of the PSION link protocol
+//
+// Copyright (C) 1999 Philip Proudman
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// e-mail philip.proudman@btinternet.com
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <stream.h>
+#include <memory.h>
+
+#include "bool.h"
+#include "iowatch.h"
+
+IOWatch::IOWatch() {
+ num = 0;
+ io = new int [MAX_IO];
+}
+
+IOWatch::~IOWatch() {
+ delete [] io;
+}
+
+void IOWatch::addIO(int a) {
+ int pos;
+ for (pos = 0; pos < num && a < io[pos]; pos++);
+ for (int i = num; i > pos; i--) io[i] = io[i-1];
+ io[pos] = a;
+ num++;
+}
+
+void IOWatch::remIO(int a) {
+ int pos;
+ for (pos = 0; pos < num && a != io[pos]; pos++);
+ if (pos != num) {
+ num--;
+ for (int i = pos; i <num; i++) io[i] = io[i+1];
+ }
+}
+
+bool IOWatch::watch(long secs, long usecs) {
+ if (num > 0) {
+ fd_set iop;
+ FD_ZERO(&iop);
+ for (int i=0; i<num; i++) {
+ FD_SET(io[i], &iop);
+ }
+ struct timeval t;
+ t.tv_usec = usecs;
+ t.tv_sec = secs;
+ return select(io[0]+1, &iop, NULL, NULL, &t);
+ }
+ else {
+ sleep(secs);
+ usleep(usecs);
+ }
+ return false;
+}
+
+
diff --git a/lib/iowatch.h b/lib/iowatch.h
new file mode 100644
index 0000000..18c0d44
--- /dev/null
+++ b/lib/iowatch.h
@@ -0,0 +1,21 @@
+#ifndef _iowatch_h
+#define _iowatch_h
+
+#include "bool.h"
+
+class IOWatch {
+public:
+ IOWatch();
+ ~IOWatch();
+
+ void addIO(int a);
+ void remIO(int a);
+ bool watch(long secs, long usecs);
+private:
+
+ enum consts { MAX_IO = 20 };
+ int *io;
+ int num;
+};
+
+#endif
diff --git a/lib/ppsocket.cc b/lib/ppsocket.cc
new file mode 100644
index 0000000..c9ef495
--- /dev/null
+++ b/lib/ppsocket.cc
@@ -0,0 +1,863 @@
+//
+// PLP - An implementation of the PSION link protocol
+//
+// Copyright (C) 1999 Philip Proudman
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// e-mail philip.proudman@btinternet.com
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <iostream.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include "../defaults.h"
+#include "bool.h"
+#include "bufferstore.h"
+#include "ppsocket.h"
+
+//**********************************************************************
+// For unix we need a few definitions
+//**********************************************************************
+
+#ifndef MAKEWORD
+#define MAKEWORD(a, b) ((WORD)(((BYTE)(a)) | ((WORD)((BYTE)(b))) << 8))
+#endif
+#ifndef SHORT
+#define SHORT int
+#endif
+
+//This constructor is useful when converting a socket
+//to a derived class of socket
+ppsocket::ppsocket(const ppsocket& another)
+{
+ m_Socket = another.m_Socket;
+ m_HostAddr = another.m_HostAddr;
+ m_PeerAddr = another.m_PeerAddr;
+ m_Bound = another.m_Bound;
+ m_Timeout = another.m_Timeout;
+ m_LastError = another.m_LastError;
+
+ m_Timeout = INFINITE;
+}
+
+
+ppsocket::ppsocket()
+{
+ m_Socket = INVALID_SOCKET;
+
+ memset(&m_HostAddr, 0, sizeof(m_HostAddr));
+ memset(&m_PeerAddr, 0, sizeof(m_PeerAddr));
+
+
+ ((struct sockaddr_in*) &m_HostAddr)->sin_family = AF_INET;
+ ((struct sockaddr_in*) &m_PeerAddr)->sin_family = AF_INET;
+
+ m_Bound = false;
+
+ m_Timeout = INFINITE;
+}
+
+
+ppsocket::~ppsocket()
+{
+ if (m_Socket != INVALID_SOCKET)
+ {
+ close(m_Socket);
+ }
+}
+
+
+bool ppsocket::startup(void)
+{
+#ifdef WIN32
+ WSADATA wd;
+ m_LastError = WSAStartup(MAKEWORD(1, 1), &wd);
+#else
+ m_LastError = 0;
+#endif
+
+ return(m_LastError == 0 ? true : false);
+}
+
+//pre : must be bound and peer info set
+bool ppsocket::reconnect()
+{
+ printPeer();
+ if (::connect(m_Socket, &m_PeerAddr, sizeof(m_PeerAddr)) != 0)
+ {
+ m_LastError = lastErrorCode();
+ cout << "Reconnect failed : status : " << m_LastError << endl << flush;
+ return(false);
+ }
+ return(true);
+}
+
+
+void ppsocket::printPeer()
+{
+ char* pPeer = 0;
+ int port;
+
+ pPeer = inet_ntoa(((struct sockaddr_in*) &m_PeerAddr)->sin_addr);
+ if (pPeer)
+ {
+ port = ntohs(((struct sockaddr_in*) &m_PeerAddr)->sin_port);
+ cout << "Peer : " << pPeer << " Port : " << port << endl;
+ }
+ else
+ {
+ cout << "Error getting Peer details\n";
+ }
+}
+
+bool ppsocket::connect(char* Peer, int PeerPort, char* Host, int HostPort)
+{
+
+ //****************************************************
+ //* If we aren't already bound set the host and bind *
+ //****************************************************
+
+ if (!bindSocket(Host, HostPort))
+ {
+ if (m_LastError != 0)
+ {
+ return(false);
+ }
+ }
+
+ //****************
+ //* Set the peer *
+ //****************
+ if (!setPeer(Peer, PeerPort))
+ {
+ return(false);
+ }
+
+ //***********
+ //* Connect *
+ //***********
+ if (::connect(m_Socket, &m_PeerAddr, sizeof(m_PeerAddr)) != 0)
+ {
+ m_LastError = lastErrorCode();
+ return(false);
+ }
+
+ return(true);
+}
+
+
+
+bool ppsocket::listen(char* Host, int Port)
+{
+ //****************************************************
+ //* If we aren't already bound set the host and bind *
+ //****************************************************
+
+ if (!bindSocket(Host, Port))
+ {
+ if (m_LastError != 0)
+ {
+ return(false);
+ }
+ }
+
+ //**********************
+ //* Listen on the port *
+ //**********************
+
+ if (::listen(m_Socket, 5) != 0)
+ {
+ m_LastError = lastErrorCode();
+ return(false);
+ }
+
+ return(true);
+}
+
+
+ppsocket* ppsocket::accept(char* Peer, int MaxLen)
+{
+ unsigned int len;
+ ppsocket* accepted;
+ char* peer;
+
+ //*****************************************************
+ //* Allocate a new object to hold the accepted socket *
+ //*****************************************************
+
+ accepted = new ppsocket;
+
+ if (!accepted)
+ {
+ m_LastError = lastErrorCode();
+ return(NULL);
+ }
+
+ //***********************
+ //* Accept a connection *
+ //***********************
+
+ len = sizeof(struct sockaddr);
+ fcntl(m_Socket, F_SETFL, O_NONBLOCK);
+ accepted->m_Socket = ::accept(m_Socket, &accepted->m_PeerAddr, &len);
+
+ if (accepted->m_Socket == INVALID_SOCKET)
+ {
+ m_LastError = lastErrorCode();
+ delete accepted;
+ return (NULL);
+ }
+
+ //****************************************************
+ //* Got a connection so fill in the other attributes *
+ //****************************************************
+
+ accepted->m_HostAddr = m_HostAddr;
+ accepted->m_Bound = true;
+
+ //****************************************************
+ //* If required get the name of the connected client *
+ //****************************************************
+
+ if (Peer)
+ {
+ peer = inet_ntoa(((struct sockaddr_in*) &accepted->m_PeerAddr)->sin_addr);
+ if (peer)
+ {
+ strncpy(Peer, peer, MaxLen);
+ Peer[MaxLen] = '\0';
+ }
+ }
+ else
+ {
+ strcpy(Peer, "");
+ }
+
+ return(accepted);
+}
+
+
+int ppsocket::printf(const char* Format, ...)
+{ int i;
+va_list ap;
+char s[512];
+
+va_start(ap, Format);
+vsprintf(s, Format, ap);
+va_end(ap);
+
+i = writeTimeout(s, strlen(s), 0);
+
+return(i);
+}
+
+bool ppsocket::dataToGet() const {
+ fd_set io;
+ FD_ZERO(&io);
+ FD_SET(m_Socket, &io);
+ struct timeval t;
+ t.tv_usec = 0;
+ t.tv_sec = 0;
+ return (select(m_Socket+1, &io, NULL, NULL, &t) != 0) ? true : false;
+}
+
+int ppsocket::getBufferStore(bufferStore &a, bool wait) {
+ /* Returns a 0 for for no message, 1 for message OK, and -1 for socket problem */
+ if (!wait && !dataToGet()) return 0;
+ a.init();
+ bool hadEscape = false;
+ do {
+ char data;
+ int j = readTimeout(&data, 1, 0);
+ if (j == SOCKET_ERROR || j == 0) {
+ return -1;
+ }
+ if (hadEscape) {
+ a.addByte(data);
+ hadEscape = false;
+ }
+ else {
+ if (data == '\\')
+ hadEscape = true;
+ else if (data == '\0')
+ break;
+ else
+ a.addByte(data);
+ }
+ } while (true);
+#ifdef SOCKET_DIAGNOSTICS
+ cout << "ppsocket got " << a << endl;
+#endif
+ return (a.getLen() == 0) ? 0 : 1;
+}
+
+bool ppsocket::sendBufferStore(const bufferStore &a) {
+#ifdef SOCKET_DIAGNOSTICS
+ cout << "ppsocket sending " << a << endl;
+#endif
+ bufferStore s;
+ long l = a.getLen();
+ for (long i = 0; i<l; i++) {
+ unsigned char cc = a.getByte(i);
+ if (cc == '\0' || cc == '\\') {
+ s.addByte('\\');
+ }
+ s.addByte(cc);
+ }
+ s.addByte('\0');
+
+ {
+ int tosend, sent, retries, i;
+
+ tosend = s.getLen();
+ sent = retries = 0;
+
+ while (tosend > 0)
+ {
+ i = writeTimeout(s.getString(sent), tosend, 0);
+
+ if (i == SOCKET_ERROR || i == 0)
+ return( false);
+
+ sent += i;
+ tosend -= i;
+
+ if (++retries > 5)
+ {
+ m_LastError = 0;
+ return(false);
+ }
+ }
+ }
+ return true;
+}
+
+int ppsocket::readEx(char* Data, int cTerm, int MaxLen)
+{
+ int i, j;
+
+ for (i = 0; i < MaxLen; i++)
+ {
+ j = readTimeout(Data + i, 1, 0);
+
+ if (j == SOCKET_ERROR || j == 0)
+ {
+ Data[i] = '\0';
+ return(i > 0 ? i : 0);
+ }
+
+ if (Data[i] == cTerm)
+ break;
+ }
+
+ return(i+1);
+}
+
+bool ppsocket::puts(const char* Data)
+{
+ int tosend, sent, retries, i;
+
+ tosend = strlen(Data);
+ sent = retries = 0;
+
+ while (tosend > 0)
+ {
+ i = writeTimeout(Data + sent, tosend, 0);
+
+ if (i == SOCKET_ERROR || i == 0)
+ return(sent > 0 ? true : false);
+
+ sent += i;
+ tosend -= i;
+
+ if (++retries > 5)
+ {
+ m_LastError = 0;
+ return(false);
+ }
+ }
+
+ return(true);
+}
+
+
+
+char ppsocket::sgetc(void)
+{
+ int i;
+ char c;
+
+ i = readTimeout(&c, 1, 0);
+ if (i == SOCKET_ERROR || i == 0)
+ {
+ return(0);
+ }
+ return(c);
+}
+
+
+bool ppsocket::sputc(char c)
+{
+ int i;
+
+ cout << hex << (int)c << endl;
+
+ i = writeTimeout(&c, 1, 0);
+
+ if (i == SOCKET_ERROR || i == 0)
+ {
+ return(false);
+ }
+
+ return(true);
+}
+
+
+int ppsocket::read(void* Data, size_t Size, size_t NumObj)
+{
+ int i = readTimeout((char*) Data, Size*NumObj, 0);
+
+ return(i);
+}
+
+
+int ppsocket::write(const void* Data, size_t Size, size_t NumObj)
+{
+ int i = writeTimeout((char*) Data, Size*NumObj, 0);
+
+ return(i);
+}
+
+
+int ppsocket::recv(char* buf, int len, int flags)
+{
+ int i = ::recv(m_Socket, buf, len, flags);
+
+ if (i < 0)
+ m_LastError = lastErrorCode();
+
+ return(i);
+}
+
+
+int ppsocket::send(const char* buf, int len, int flags)
+{
+ int i = ::send(m_Socket, buf, len, flags);
+
+ if (i < 0)
+ m_LastError = lastErrorCode();
+
+ return(i);
+}
+
+
+int ppsocket::readTimeout(char* buf, int len, int flags)
+{
+ int i;
+
+ //*********************************************************
+ //* If there is no timeout use the Berkeley recv function *
+ //*********************************************************
+
+ if (m_Timeout == INFINITE)
+ {
+ i = ::recv(m_Socket, buf, len, flags);
+
+ if (i == SOCKET_ERROR)
+ {
+ m_LastError = lastErrorCode();
+ }
+ }
+
+ //********************************************
+ //* If there is a timeout use overlapped i/o *
+ //********************************************
+
+ else
+ {
+ i = SOCKET_ERROR;
+ }
+
+
+ return(i);
+}
+
+
+int ppsocket::writeTimeout(const char* buf, int len, int flags)
+{
+ int i;
+ // If there is no timeout use the Berkeley send function
+
+ if (m_Timeout == INFINITE)
+ {
+ i = ::send(m_Socket, buf, len, flags);
+
+ if (i == SOCKET_ERROR)
+ {
+ m_LastError = lastErrorCode();
+ }
+ }
+ else
+ {
+ // If there is a timeout use overlapped i/o
+ i = SOCKET_ERROR;
+ }
+
+ return(i);
+}
+
+bool ppsocket::closeSocket(void)
+{
+ if (close(m_Socket) != 0)
+ {
+ m_LastError = lastErrorCode();
+ return(false);
+ }
+
+ m_Socket = INVALID_SOCKET;
+
+ return(true);
+}
+
+
+bool ppsocket::bindSocket(char* Host, int Port)
+{
+
+ // If we are already bound return FALSE but with no last error
+
+ m_LastError = 0;
+
+ if (m_Bound)
+ {
+ return(false);
+ }
+
+ // If the socket hasn't been created create it now
+
+ if (m_Socket == INVALID_SOCKET)
+ {
+ if (!createSocket())
+ {
+ return(false);
+ }
+ }
+
+ // If a host name was supplied then use it
+ if (!setHost(Host, Port))
+ {
+ return(false);
+ }
+
+ // Now bind the socket
+ if (::bind(m_Socket, &m_HostAddr, sizeof(m_HostAddr)) != 0)
+ {
+ m_LastError = lastErrorCode();
+ return(false);
+ }
+
+ m_Bound = true;
+
+ return(true);
+}
+
+
+bool ppsocket::bindInRange(char* Host, int Low, int High, int Retries)
+{
+ int port, i;
+
+ // If we are already bound return FALSE but with no last error
+
+ m_LastError = 0;
+
+ if (m_Bound)
+ {
+ return(false);
+ }
+
+ // If the socket hasn't been created create it now
+
+ if (m_Socket == INVALID_SOCKET)
+ {
+ if (!createSocket())
+ {
+ return(false);
+ }
+ }
+ // If the number of retries is greater than the range then work through the
+ // range sequentially.
+
+ if (Retries > High - Low)
+ {
+ for (port = Low; port <= High; port++)
+ {
+ if (!setHost(Host, port))
+ return(false);
+
+ if (::bind(m_Socket, &m_HostAddr, sizeof(m_HostAddr)) == 0)
+ break;
+ }
+
+ if (port > High)
+ {
+ m_LastError = lastErrorCode();
+ return(false);
+ }
+ }
+
+ // Else select numbers within the range at random
+
+ else
+ {
+ for (i = 0; i < Retries; i++)
+ {
+ port = Low + (rand() % (High - Low));
+
+ if (!setHost(Host, port))
+ return(false);
+
+ if (::bind(m_Socket, &m_HostAddr, sizeof(m_HostAddr)) == 0)
+ break;
+ }
+
+ if (i >= Retries)
+ {
+ m_LastError = lastErrorCode();
+ return(false);
+ }
+ }
+
+ m_Bound = true;
+
+ return(true);
+}
+
+bool ppsocket::linger(bool LingerOn, int LingerTime)
+{
+ int i;
+ struct linger l;
+
+ // If the socket hasn't been created create it now
+
+ if (m_Socket == INVALID_SOCKET)
+ {
+ if (!createSocket())
+ {
+ return(false);
+ }
+ }
+ // Set the lingering
+
+ if (LingerOn)
+ {
+ l.l_onoff = 1;
+ l.l_linger = LingerTime;
+ }
+ else
+ {
+ l.l_onoff = 0;
+ l.l_linger = 0;
+ }
+ i = setsockopt(m_Socket, SOL_SOCKET, SO_LINGER, (const char*) &l, sizeof(l));
+
+ // Check for errors
+
+ if (i != 0)
+ {
+ m_LastError = lastErrorCode();
+ return(false);
+ }
+
+ // Return indicating success
+
+ return(true);
+}
+
+
+bool ppsocket::createSocket(void)
+{
+ // If the socket has already been created just return true
+ if (m_Socket != INVALID_SOCKET)
+ {
+ return(true);
+ }
+
+ // Create the socket
+ m_Socket = ::socket(PF_INET, SOCK_STREAM, 0);
+
+ if (m_Socket == INVALID_SOCKET)
+ {
+ m_LastError = lastErrorCode();
+ return(false);
+ }
+
+ // By default set no lingering
+
+ linger(FALSE, 0);
+
+ // Return indicating success
+
+ return(true);
+}
+
+bool ppsocket::setPeer(char* Peer, int Port)
+{
+ struct hostent* he;
+
+ // If a peer name was supplied then use it
+ if (Peer)
+ {
+ he = gethostbyname(Peer);
+ if (!he)
+ {
+ unsigned long ipaddress = inet_addr(Peer);
+ if (ipaddress == INADDR_NONE)
+ {
+ m_LastError = lastErrorCode();
+ return(false);
+ }
+
+ he = gethostbyaddr((const char*) &ipaddress, 4, PF_INET);
+ if (!he)
+ {
+ m_LastError = lastErrorCode();
+ return(false);
+ }
+ }
+ memcpy((void*) &((struct sockaddr_in*) &m_PeerAddr)->sin_addr, (void*) he->h_addr_list[0], 4);
+ }
+
+ // If a port name was supplied use it
+
+ if (Port > 0)
+ {
+ ((struct sockaddr_in*) &m_PeerAddr)->sin_port = htons((SHORT) Port);
+ }
+
+ return(true);
+}
+
+
+bool ppsocket::getPeer(char* Peer, int MaxLen, int* Port)
+{
+ char* peer;
+
+ if (Peer)
+ {
+ peer = inet_ntoa(((struct sockaddr_in*) &m_PeerAddr)->sin_addr);
+
+ if (!peer)
+ {
+ m_LastError = lastErrorCode();
+ return(false);
+ }
+
+ strncpy(Peer, peer, MaxLen);
+ Peer[MaxLen] = '\0';
+ }
+
+ if (Port)
+ {
+ *Port = ntohs(((struct sockaddr_in*) &m_PeerAddr)->sin_port);
+ }
+
+ return(false);
+}
+
+
+bool ppsocket::setHost(char* Host, int Port)
+{
+ struct hostent* he;
+
+ // If a host name was supplied then use it
+ if (Host)
+ {
+ he = gethostbyname(Host);
+
+ if (!he)
+ {
+ unsigned long ipaddress = inet_addr(Host);
+ if (ipaddress == INADDR_NONE)
+ {
+ m_LastError = lastErrorCode();
+ return(false);
+ }
+
+ he = gethostbyaddr((const char*) &ipaddress, 4, PF_INET);
+
+ if (!he)
+ {
+ m_LastError = lastErrorCode();
+ return(false);
+ }
+ }
+
+ memcpy((void*) &((struct sockaddr_in*) &m_HostAddr)->sin_addr, (void*) he->h_addr_list[0], 4);
+ }
+
+
+ // If a port name was supplied use it
+
+ if (Port > 0)
+ {
+ ((struct sockaddr_in*) &m_HostAddr)->sin_port = htons((SHORT) Port);
+ }
+
+ return(true);
+}
+
+
+bool ppsocket::getHost(char* Host, int MaxLen, int* Port)
+{
+ char* host;
+
+ if (Host)
+ {
+ host = inet_ntoa(((struct sockaddr_in*) &m_HostAddr)->sin_addr);
+
+ if (!host)
+ {
+ m_LastError = lastErrorCode();
+ return(false);
+ }
+
+ strncpy(Host, host, MaxLen);
+ Host[MaxLen] = '\0';
+ }
+
+ if (Port)
+ {
+ *Port = ntohs(((struct sockaddr_in*) &m_HostAddr)->sin_port);
+ }
+ return(false);
+}
+
+DWORD ppsocket::lastErrorCode()
+{
+ return errno;
+}
+
+void ppsocket::setSocketInvalid()
+{
+ m_Socket = INVALID_SOCKET;
+}
diff --git a/lib/ppsocket.h b/lib/ppsocket.h
new file mode 100644
index 0000000..b93ee25
--- /dev/null
+++ b/lib/ppsocket.h
@@ -0,0 +1,117 @@
+#if !defined(AFX_ppsocket_H__5611BC0C_3E39_11D1_8E4B_00805F2AB205__INCLUDED_)
+#define AFX_ppsocket_H__5611BC0C_3E39_11D1_8E4B_00805F2AB205__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#ifndef TRUE
+#define TRUE -1
+#define FALSE 0
+#endif
+#define DWORD unsigned int
+#define SOCKET int
+
+#ifndef INADDR_NONE
+#define INADDR_NONE (in_addr_t)-1
+#endif
+#define INVALID_SOCKET -1
+#define SOCKET_ERROR -1
+#define INFINITE 0
+
+extern int errno;
+
+#include "bool.h"
+class bufferStore;
+
+class ppsocket
+{
+
+public:
+ ppsocket();
+ virtual ~ppsocket();
+
+ virtual bool startup(void);
+
+ virtual bool connect(char* Peer, int PeerPort, char* Host = NULL, int HostPort = 0);
+ virtual bool reconnect();
+
+ virtual void printPeer();
+
+ virtual bool listen(char* Host, int Port);
+
+ ppsocket* accept(char* Peer, int MaxLen);
+
+ bool dataToGet() const;
+ int getBufferStore(bufferStore &a, bool wait = true);
+ bool sendBufferStore(const bufferStore &a);
+
+ int printf(const char* Format, ...);
+
+ int readEx(char* Data, int cTerm, int MaxLen);
+ bool puts(const char* Data);
+
+ char sgetc(void);
+ bool sputc(char c);
+
+ int read(void* Data, size_t Size, size_t NumObj);
+ virtual int write(const void* Data, size_t Size, size_t NumObj);
+
+ int recv(char* buf, int len, int flags);
+ int send(const char* buf, int len, int flags);
+
+ int readTimeout(char* buf, int len, int flags);
+ int writeTimeout(const char* buf, int len, int flags);
+
+ inline void timeout(DWORD t) { m_Timeout = t; }
+ inline DWORD timeout(void) { return(m_Timeout); }
+
+ bool closeSocket(void);
+ bool bindSocket(char* Host, int Port);
+ bool bindInRange(char* Host, int Low, int High, int Retries);
+ bool linger(bool LingerOn, int LingerTime = 0);
+
+ virtual bool createSocket(void);
+
+ bool setPeer(char* Peer, int Port);
+ bool getPeer(char* Peer, int MaxLen, int* Port);
+ bool setHost(char* Host, int Port);
+ bool getHost(char* Host, int MaxLen, int* Port);
+
+ DWORD getLastError(void) { return(m_LastError); }
+ inline SOCKET socket(void) const { return(m_Socket); }
+ DWORD lastErrorCode();
+
+ //set the current socket to invalid
+ //useful when deleting if the socket has been
+ //copied to another and should not be closed
+ //when this instance is destructed
+ void setSocketInvalid();
+
+protected:
+ ppsocket(const ppsocket&);
+
+ struct sockaddr* getPeerAddrStruct() { return &m_PeerAddr; }
+ struct sockaddr* getHostAddrStruct() { return &m_HostAddr; }
+ void setHostAddrStruct(struct sockaddr* pHostStruct) { m_HostAddr = *pHostStruct; }
+ void setSocket(SOCKET& sock) { m_Socket = sock; }
+ void setBound() { m_Bound = true;}
+ void updateLastError() {m_LastError = lastErrorCode(); }
+
+private:
+ SOCKET m_Socket;
+ struct sockaddr m_HostAddr, m_PeerAddr;
+ bool m_Bound;
+#ifdef WIN32
+ OVERLAPPED m_ReadOverlapped, m_WriteOverlapped;
+#endif
+ DWORD m_Timeout;
+ DWORD m_LastError;
+};
+
+#endif