From 30b6230c50eae3ee8505478e0b72b31ed711469f Mon Sep 17 00:00:00 2001 From: serverericoza Date: Sat, 5 Jun 2010 22:54:07 +0200 Subject: [PATCH] Mijn eerste commit, omdat ik het waard ben... --- Client/1 | 0 Client/2 | 0 Client/3 | 0 Client/Makefile | 18 + Client/main.cpp | 19 + Client/sockets/SocketW.h | 22 + Client/sockets/sw_base.cpp | 764 +++++++++++++++++++++++++++++++++++ Client/sockets/sw_base.h | 205 ++++++++++ Client/sockets/sw_inet.cpp | 249 ++++++++++++ Client/sockets/sw_inet.h | 48 +++ Client/sockets/sw_internal.h | 75 ++++ Client/sockets/sw_unix.cpp | 99 +++++ Client/sockets/sw_unix.h | 41 ++ Server/Makefile | 18 + Server/main.cpp | 72 ++++ Server/sockets.zip | Bin 0 -> 13832 bytes Server/sockets/SocketW.h | 22 + Server/sockets/sw_base.cpp | 764 +++++++++++++++++++++++++++++++++++ Server/sockets/sw_base.h | 205 ++++++++++ Server/sockets/sw_inet.cpp | 249 ++++++++++++ Server/sockets/sw_inet.h | 48 +++ Server/sockets/sw_internal.h | 75 ++++ Server/sockets/sw_unix.cpp | 99 +++++ Server/sockets/sw_unix.h | 41 ++ blaat | 1 - 25 files changed, 3133 insertions(+), 1 deletion(-) create mode 100644 Client/1 create mode 100644 Client/2 create mode 100644 Client/3 create mode 100644 Client/Makefile create mode 100644 Client/main.cpp create mode 100644 Client/sockets/SocketW.h create mode 100644 Client/sockets/sw_base.cpp create mode 100644 Client/sockets/sw_base.h create mode 100644 Client/sockets/sw_inet.cpp create mode 100644 Client/sockets/sw_inet.h create mode 100644 Client/sockets/sw_internal.h create mode 100644 Client/sockets/sw_unix.cpp create mode 100644 Client/sockets/sw_unix.h create mode 100644 Server/Makefile create mode 100644 Server/main.cpp create mode 100644 Server/sockets.zip create mode 100644 Server/sockets/SocketW.h create mode 100644 Server/sockets/sw_base.cpp create mode 100644 Server/sockets/sw_base.h create mode 100644 Server/sockets/sw_inet.cpp create mode 100644 Server/sockets/sw_inet.h create mode 100644 Server/sockets/sw_internal.h create mode 100644 Server/sockets/sw_unix.cpp create mode 100644 Server/sockets/sw_unix.h delete mode 100644 blaat diff --git a/Client/1 b/Client/1 new file mode 100644 index 00000000..e69de29b diff --git a/Client/2 b/Client/2 new file mode 100644 index 00000000..e69de29b diff --git a/Client/3 b/Client/3 new file mode 100644 index 00000000..e69de29b diff --git a/Client/Makefile b/Client/Makefile new file mode 100644 index 00000000..c0d40be8 --- /dev/null +++ b/Client/Makefile @@ -0,0 +1,18 @@ +SRC = main.cpp sockets/sw_base.cpp sockets/sw_inet.cpp sockets/sw_unix.cpp +OBJ = $(SRC:.cpp=.o) +OUT = Socket +INCLUDES = +CCFLAGS = -Wall -Wextra -funsigned-char -g +CC = $(CROSS)g++ +LD = $(CROSS)ld +AR = $(CROSS)ar +LIBS= +.SUFFIXES: .cpp +.PHONY: clean default +default: $(OUT) +.cpp.o: + $(CC) $(INCLUDES) $(CCFLAGS) $(LIBS) -c $< -o $@ +$(OUT): $(OBJ) + $(CC) $(LIBS) -o $(OUT) $(OBJ) +clean: + rm -rf $(OBJ) $(OUT) Makefile.bak *~ diff --git a/Client/main.cpp b/Client/main.cpp new file mode 100644 index 00000000..d43f0a3e --- /dev/null +++ b/Client/main.cpp @@ -0,0 +1,19 @@ +#include +#include "sockets/SocketW.h" +#include +#include +#include + +int main() { + SWUnixSocket mySocket; + mySocket.connect("../socketfile"); + std::string msg; + // do something with mySocket... + while(true) { + msg = mySocket.recvmsg(); + std::cout << msg; + } + // disconnect + mySocket.disconnect(); + return 0; +} diff --git a/Client/sockets/SocketW.h b/Client/sockets/SocketW.h new file mode 100644 index 00000000..b7096c0c --- /dev/null +++ b/Client/sockets/SocketW.h @@ -0,0 +1,22 @@ +// C++ Socket Wrapper +// +// Started 020316 +// +// License: LGPL v2.1+ (see the file LICENSE) +// (c)2002-2003 Anders Lindstr�m + +/*********************************************************************** + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + ***********************************************************************/ + +#ifndef SocketW_H +#define SocketW_H + +#include "sw_base.h" +#include "sw_unix.h" +#include "sw_inet.h" + +#endif //SocketW_H diff --git a/Client/sockets/sw_base.cpp b/Client/sockets/sw_base.cpp new file mode 100644 index 00000000..23ca1eb6 --- /dev/null +++ b/Client/sockets/sw_base.cpp @@ -0,0 +1,764 @@ +// C++ Socket Wrapper +// SocketW base class +// +// Started 020316 +// +// License: LGPL v2.1+ (see the file LICENSE) +// (c)2002-2003 Anders Lindstr�m + +/*********************************************************************** + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + ***********************************************************************/ + +#include "sw_base.h" +#include +#include +#include +#include +#include + +#ifndef __WIN32__ + #include + #include + #include + #include + #include + + #define INVALID_SOCKET -1 //avoid M$ braindamage +#else + //why use POSIX standards when we can make our own + //and frustrate people? (well known M$ policy) + + #ifndef EBADF + #define EBADF WSAEBADF + #endif + + #define ENOTSOCK WSAENOTSOCK + #define EOPNOTSUPP WSAEOPNOTSUPP + #define EADDRINUSE WSAEADDRINUSE + #define EWOULDBLOCK WSAEWOULDBLOCK + #define EMSGSIZE WSAEMSGSIZE + #define EINPROGRESS WSAEINPROGRESS + #define EALREADY WSAEALREADY + #define ECONNREFUSED WSAECONNREFUSED + #define ETIMEDOUT WSAETIMEDOUT + #define ENOTCONN WSAENOTCONN + + #ifndef EINTR + #define EINTR WSAEINTR + #endif +#endif + +#ifndef MSG_NOSIGNAL + #define MSG_NOSIGNAL 0 +#endif + +// Socklen hack +#if defined(__linux__) || defined(__FreeBSD__) // || defined(__bsdi__) || defined(__NetBSD__) too, perhaps? Bugreports, please! + #define sw_socklen_t socklen_t +#elif defined(__WIN32__) || defined(__osf__) + #define sw_socklen_t int +#else + #define sw_socklen_t unsigned int +#endif + + +using namespace std; + +#ifdef __WIN32__ +//Win32 braindamage +int close(int fd) +{ + return closesocket(fd); +} + +int fcntl(int fd, int cmd, long arg) +{ + unsigned long mode = arg; + + return WSAIoctl(fd, cmd, &mode, sizeof(unsigned long), NULL, 0, NULL, NULL, NULL); +} + +void WSA_exit(void) +{ + WSACleanup(); +} +#endif + + +//==================================================================== +//== Error handling mode +//==================================================================== +bool sw_DoThrow = false; +bool sw_Verbose = true; + +void sw_setThrowMode(bool throw_errors) +{ + sw_DoThrow = throw_errors; +} + +void sw_setVerboseMode(bool verbose) +{ + sw_Verbose = verbose; +} + +bool sw_getThrowMode(void) +{ + return sw_DoThrow; +} + +bool sw_getVerboseMode(void) +{ + return sw_Verbose; +} + + +//==================================================================== +//== Base error class +//==================================================================== +SWBaseSocket::SWBaseError::SWBaseError() +{ + be = ok; + error_string = ""; + failed_class = NULL; +} + +SWBaseSocket::SWBaseError::SWBaseError(base_error e) +{ + be = e; + error_string = ""; + failed_class = NULL; +} + +string SWBaseSocket::SWBaseError::get_error() +{ + return error_string; +} + +SWBaseSocket* SWBaseSocket::SWBaseError::get_failedClass(void) +{ + return failed_class; +} + +void SWBaseSocket::SWBaseError::set_errorString(string msg) +{ + error_string = msg; +} + +void SWBaseSocket::SWBaseError::set_failedClass(SWBaseSocket *pnt) +{ + failed_class = pnt; +} + +bool SWBaseSocket::SWBaseError::operator==(SWBaseError e) +{ + return be == e.be; +} + +bool SWBaseSocket::SWBaseError::operator!=(SWBaseError e) +{ + return be != e.be; +} + + +//==================================================================== +//== SWBaseSocket +//== Base class for sockets +//==================================================================== +SWBaseSocket::SWBaseSocket() +{ + //indicate nonopen + myfd = -1; + recv_close = false; + + //init values + error_string = ""; + block_mode = blocking; + fsend_ready = true; + frecv_ready = true; + tsec = 0; + tusec = 0; + + #ifdef __WIN32__ + //kick winsock awake + static bool firstuse = true; + if( firstuse == true ){ + WSAData wsaData; + int nCode; + if( (nCode = WSAStartup(MAKEWORD(1, 1), &wsaData)) != 0 ){ + handle_errno(NULL, "SWBaseSocket - WSAStartup() failed: "); + exit(-1); // Should never happend + } + + //cleanup at exit + atexit(WSA_exit); + firstuse = false; + } + #endif /* __WIN32__ */ +} + +SWBaseSocket::~SWBaseSocket() +{ + if(myfd > 0) + close(myfd); +} + +bool SWBaseSocket::listen(int qLimit, SWBaseError *error) +{ + get_socket(); + + //Avoid "Address already in use" thingie + char yes=1; + setsockopt(myfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); + + if(::listen(myfd, qLimit) == -1){ + handle_errno(error, "SWBaseSocket::listen() error: "); + return false; + } + + no_error(error); + return true; +} + +SWBaseSocket* SWBaseSocket::accept(SWBaseError *error) +{ + int remotefd = -1; + sockaddr remoteAdr; + + if( !waitRead(error) ) + return NULL; + + sw_socklen_t ssize = sizeof(sockaddr); + + if((remotefd = ::accept(myfd, &remoteAdr, &ssize)) == int(INVALID_SOCKET)){ + handle_errno(error, "SWBaseSocket::accept() error: "); + return NULL; + } + + //nonblocking? + if( block_mode == nonblocking ) + fcntl(remotefd, F_SETFL, O_NONBLOCK); + + /* Create new class*/ + SWBaseSocket* remoteClass = create(remotefd, error); + if( remoteClass == NULL ) + return NULL; + + no_error(error); + return remoteClass; +} + +bool SWBaseSocket::disconnect(SWBaseError *error) +{ + int n = 0; + char buf[256]; + + if(myfd < 0){ + set_error(error, notConnected, "SWBaseSocket::disconnect() - No connection"); + return false; + } + + //close WR (this signals the peer) + if( shutdown(myfd, 1) != 0 ){ + handle_errno(error, "SWBaseSocket::disconnect() error: "); + return false; + } + + + SWBaseError err; + + //wait for close signal from peer + if( recv_close == false ){ + while(true){ + if( !waitRead(error) ) + return false; + + n = recv(buf, 256, &err); + + if( n <= 0 ) + break; + if(block_mode == noWait){ + //we don't want to block + set_error(error, notReady, "SWBaseSocket::disconnect() - Need more time, call again"); + return false; + } + } + } + + if( n != 0 ){ + set_error(error, err, error_string); + return false; //error + } + + //reset state + reset(); + + close(myfd); + myfd = -1; + + no_error(error); + return true; +} + +bool SWBaseSocket::close_fd() +{ + if( myfd > 0 ){ + close(myfd); + myfd = -1; + + //reset state + reset(); + + return true; + } + return false; +} + +int SWBaseSocket::send(const char *buf, int bytes, SWBaseError *error) +{ + int ret; + + if(myfd < 0){ + set_error(error, notConnected, "SWBaseSocket::send() - No connection"); + return -1; + } + + if( !waitWrite(error) ) + return -1; + + ret = ::send(myfd, buf, bytes, MSG_NOSIGNAL); + + if( ret < 0 ) + handle_errno(error, "SWBaseSocket::send() error: "); + else + no_error(error); + + return ret; +} + +int SWBaseSocket::fsend(const char *buf, int bytes, SWBaseError *error) +{ + int n; + int bytessent; + + if(fsend_ready){ + //First call + fsend_bytesleft = bytes; + fsend_total = fsend_bytesleft; //global var needed for resume + bytessent = 0; + fsend_ready = false; //point of no return + } + else{ + //resume + bytessent = fsend_total - fsend_bytesleft; + } + + //send package + while( fsend_bytesleft > 0 ){ + n = send( buf + bytessent , fsend_bytesleft, error ); + + //return on error, wouldblock or nowait + if( n < 0 ) + return ( (bytessent > 0 )? -bytessent : -1 ); + + bytessent += n; + fsend_bytesleft -= n; + + if ( block_mode == noWait && fsend_bytesleft > 0 ){ + set_error(error, notReady, "SWBaseSocket::fsend() - Need more time, call again"); + return -bytessent; + } + } + + fsend_ready = true; + + no_error(error); + return fsend_total; +} + +int SWBaseSocket::sendmsg(const string msg, SWBaseError *error) +{ + return send(msg.c_str(), msg.size(), error); +} + +int SWBaseSocket::fsendmsg(const string msg, SWBaseError *error) +{ + return fsend(msg.c_str(), msg.size(), error); +} + +int SWBaseSocket::recv(char *buf, int bytes, SWBaseError *error) +{ + int ret; + + if(myfd < 0){ + set_error(error, notConnected, "SWBaseSocket::recv() - No connection"); + return -1; + } + + if( !waitRead(error) ) + return -1; + + ret = ::recv(myfd, buf, bytes, MSG_NOSIGNAL); + + if( ret < 0 ) + handle_errno(error, "SWBaseSocket::recv() error: "); + else if( ret == 0 ){ + recv_close = true; //we recived a close signal from peer + set_error(error, terminated, "SWBaseSocket::recv() - Connection terminated by peer"); + }else + no_error(error); + + return ret; +} + +int SWBaseSocket::frecv(char *buf, int bytes, SWBaseError *error) +{ + int n; + int bytesrecv; + + if(frecv_ready){ + //First call + frecv_bytesleft = bytes; + frecv_total = frecv_bytesleft; //global var needed for resume + bytesrecv = 0; + frecv_ready = false; //point of no return + } + else{ + //resume + bytesrecv = frecv_total - frecv_bytesleft; + } + + + //recv package + while( frecv_bytesleft > 0 ){ + n = recv( buf + bytesrecv , frecv_bytesleft, error ); + + //return on error, wouldblock, nowait or timeout + if( n < 0 ) + return ( (bytesrecv > 0 )? -bytesrecv : -1 ); + if( n == 0 ) + return 0; // terminated + + bytesrecv += n; + frecv_bytesleft -= n; + + if ( block_mode == noWait && frecv_bytesleft > 0 ){ + set_error(error, notReady, "SWBaseSocket::frecv() - Need more time, call again"); + return -bytesrecv; + } + } + + frecv_ready = true; + + no_error(error); + return frecv_total; +} + +string SWBaseSocket::recvmsg(int bytes, SWBaseError *error) +{ + char *buf = new char[bytes+1]; + + SWBaseError err; + string msg = ""; + int ret = recv(buf, bytes, &err); + + if( ret > 0 ){ + buf[ret]='\0'; // Make sure the string is null terminated + msg = buf; + no_error(error); + } + delete[] buf; + + if( ret < 1 ) + set_error(error, err, err.get_error()); + + return msg; +} + +int SWBaseSocket::get_fd(SWBaseError *error) +{ + if( myfd > 0 ){ + no_error(error); + return myfd; + } + + set_error(error, notConnected, "SWBaseSocket::get_fd() - No descriptor"); + return -1; +} + +bool SWBaseSocket::get_host(sockaddr *host, SWBaseError *error) +{ + if( host == NULL){ + set_error(error, fatal, "SWBaseSocket::get_host() - Got NULL pointer"); + return false; + } + + if(myfd < 0){ + set_error(error, notConnected, "SWBaseSocket::get_host() - No socket"); + return false; + } + + sw_socklen_t tmp = sizeof(sockaddr); + if( getsockname(myfd, host, &tmp) != 0 ){ + handle_errno(error, "SWBaseSocket::get_host() error: "); + return false; + } + + no_error(error); + return true; +} + +bool SWBaseSocket::get_peer(sockaddr *peer, SWBaseError *error) +{ + if( peer == NULL){ + set_error(error, fatal, "SWBaseSocket::get_peer() - Got NULL pointer"); + return false; + } + + if(myfd > 0){ + sw_socklen_t tmp = sizeof(sockaddr); + if( getpeername(myfd, peer, &tmp) != 0 ){ + handle_errno(error, "SWBaseSocket::get_peer() error: "); + return false; + } + }else{ + set_error(error, notConnected, "SWBaseSocket::get_peer() - No connection"); + return false; + } + + no_error(error); + return true; +} + +void SWBaseSocket::reset() +{ + // Reset flags + recv_close = false; + + fsend_ready = true; + frecv_ready = true; +} + +bool SWBaseSocket::waitIO(io_type &type, SWBaseError *error) +{ + if( block_mode != blocking ){ + no_error(error); + return true; + } + + // We prefere to wait with select() even if no timeout is set + // as select() behaves more predictable + + timeval t; + timeval *to = NULL; // Indicate "wait for ever" + t.tv_sec = tsec; + t.tv_usec = tusec; + + if( tsec > 0 || tusec > 0 ) + to = &t; + + fd_set readfds, writefds, exceptfds; + + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&exceptfds); + FD_SET(myfd, &readfds); + FD_SET(myfd, &writefds); + FD_SET(myfd, &exceptfds); + + int ret = 0; + + switch (type){ + case read: + ret = select(myfd+1, &readfds, NULL, NULL, to); + break; + case write: + ret = select(myfd+1, NULL, &writefds, NULL, to); + break; + case except: + ret = select(myfd+1, NULL, NULL, &exceptfds, to); + break; + case rw: + ret = select(myfd+1, &readfds, &writefds, NULL, to); + break; + case all: + ret = select(myfd+1, &readfds, &writefds, &exceptfds, to); + break; + } + + if( ret < 0 ){ + handle_errno(error, "SWBaseSocket::waitIO() error: "); + return false; + } + if( ret == 0 ){ + set_error(error, timeout, "SWBaseSocket::waitIO() timeout"); + return false; + } + + if( FD_ISSET(myfd, &readfds) ){ + no_error(error); + type = read; + return true; + } + if( FD_ISSET(myfd, &writefds) ){ + no_error(error); + type = write; + return true; + } + if( FD_ISSET(myfd, &exceptfds) ){ + no_error(error); + type = except; + return true; + } + + set_error(error, fatal, "SWBaseSocket::waitIO() failed on select()"); + return false; +} + +bool SWBaseSocket::waitRead(SWBaseError *error) +{ + io_type tmp = read; + return waitIO(tmp, error); +} + +bool SWBaseSocket::waitWrite(SWBaseError *error) +{ + io_type tmp = write; + return waitIO(tmp, error); +} + +void SWBaseSocket::print_error() +{ + if( error_string.size() > 0 ) + fprintf(stderr, "%s!\n", error_string.c_str()); +} + +void SWBaseSocket::handle_errno(SWBaseError *error, string msg) +{ + #ifndef __WIN32__ + msg += strerror(errno); + #else + //stupid stupid stupid stupid M$ + switch (WSAGetLastError()){ + case 0: msg += "No error"; break; + case WSAEINTR: msg += "Interrupted system call"; break; + case WSAEBADF: msg += "Bad file number"; break; + case WSAEACCES: msg += "Permission denied"; break; + case WSAEFAULT: msg += "Bad address"; break; + case WSAEINVAL: msg += "Invalid argument"; break; + case WSAEMFILE: msg += "Too many open sockets"; break; + case WSAEWOULDBLOCK: msg += "Operation would block"; break; + case WSAEINPROGRESS: msg += "Operation now in progress"; break; + case WSAEALREADY: msg += "Operation already in progress"; break; + case WSAENOTSOCK: msg += "Socket operation on non-socket"; break; + case WSAEDESTADDRREQ: msg += "Destination address required"; break; + case WSAEMSGSIZE: msg += "Message too long"; break; + case WSAEPROTOTYPE: msg += "Protocol wrong type for socket"; break; + case WSAENOPROTOOPT: msg += "Bad protocol option"; break; + case WSAEPROTONOSUPPORT: msg += "Protocol not supported"; break; + case WSAESOCKTNOSUPPORT: msg += "Socket type not supported"; break; + case WSAEOPNOTSUPP: msg += "Operation not supported on socket"; break; + case WSAEPFNOSUPPORT: msg += "Protocol family not supported"; break; + case WSAEAFNOSUPPORT: msg += "Address family not supported"; break; + case WSAEADDRINUSE: msg += "Address already in use"; break; + case WSAEADDRNOTAVAIL: msg += "Can't assign requested address"; break; + case WSAENETDOWN: msg += "Network is down"; break; + case WSAENETUNREACH: msg += "Network is unreachable"; break; + case WSAENETRESET: msg += "Net connection reset"; break; + case WSAECONNABORTED: msg += "Software caused connection abort"; break; + case WSAECONNRESET: msg += "Connection reset by peer"; break; + case WSAENOBUFS: msg += "No buffer space available"; break; + case WSAEISCONN: msg += "Socket is already connected"; break; + case WSAENOTCONN: msg += "Socket is not connected"; break; + case WSAESHUTDOWN: msg += "Can't send after socket shutdown"; break; + case WSAETOOMANYREFS: msg += "Too many references"; break; + case WSAETIMEDOUT: msg += "Connection timed out"; break; + case WSAECONNREFUSED: msg += "Connection refused"; break; + case WSAELOOP: msg += "Too many levels of symbolic links"; break; + case WSAENAMETOOLONG: msg += "File name too long"; break; + case WSAEHOSTDOWN: msg += "Host is down"; break; + case WSAEHOSTUNREACH: msg += "No route to host"; break; + case WSAENOTEMPTY: msg += "Directory not empty"; break; + case WSAEPROCLIM: msg += "Too many processes"; break; + case WSAEUSERS: msg += "Too many users"; break; + case WSAEDQUOT: msg += "Disc quota exceeded"; break; + case WSAESTALE: msg += "Stale NFS file handle"; break; + case WSAEREMOTE: msg += "Too many levels of remote in path"; break; + case WSASYSNOTREADY: msg += "Network system is unavailable"; break; + case WSAVERNOTSUPPORTED: msg += "Winsock version out of range"; break; + case WSANOTINITIALISED: msg += "WSAStartup not yet called"; break; + case WSAEDISCON: msg += "Graceful shutdown in progress"; break; + case WSAHOST_NOT_FOUND: msg += "Host not found"; break; + case WSANO_DATA: msg += "No host data of that type was found"; break; + default: msg += "Unknown Winsock error: " + WSAGetLastError(); break; + } + #endif + + int errorno; + + //Win32 braindamage + #ifdef __WIN32__ + errorno = WSAGetLastError(); + #else + errorno = errno; + #endif + + SWBaseError e; + + if( errorno == EADDRINUSE ) + e = portInUse; + else if( errorno == EAGAIN || errorno == EWOULDBLOCK ) + e = notReady; + else if( errorno == EMSGSIZE ) + e = msgTooLong; + else if( errorno == EINPROGRESS || errorno == EALREADY ) + e = notReady; + else if( errorno == ECONNREFUSED || errorno == ETIMEDOUT ) + e = noResponse; + else if( errorno == ENOTCONN || errorno == EBADF || errorno == ENOTSOCK ) + e = notConnected; + else if( errorno == EPIPE ){ + e = terminated; + recv_close = true; + }else if( errorno == EINTR ) + e = interrupted; + else + e = fatal; //default + + set_error(error, e, msg); +} + +void SWBaseSocket::no_error(SWBaseError *error) +{ + if(error != NULL){ + *error = ok; + error->error_string = ""; + error->failed_class = NULL; + } +} + +void SWBaseSocket::set_error(SWBaseError *error, SWBaseError name, string msg) +{ + error_string = msg; + + if(error != NULL){ + *error = name; + error->error_string = msg; + error->failed_class = this; + }else{ + if( sw_Verbose ) + print_error(); + + if( sw_DoThrow ){ + SWBaseError e; + e = name; + e.error_string = msg; + e.failed_class = this; + throw e; + } + } +} + diff --git a/Client/sockets/sw_base.h b/Client/sockets/sw_base.h new file mode 100644 index 00000000..a6a191f1 --- /dev/null +++ b/Client/sockets/sw_base.h @@ -0,0 +1,205 @@ +// C++ Socket Wrapper +// SocketW base socket header +// +// Started 020316 +// +// License: LGPL v2.1+ (see the file LICENSE) +// (c)2002-2003 Anders Lindström + +/*********************************************************************** + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + ***********************************************************************/ + +#ifndef sw_base_H +#define sw_base_H + +#include "sw_internal.h" + +#include +#include + +// Set error handling mode +// throw_errors == true : Throws the error class on unhandled errors +// throw_errors == false : Exit on unhandled errors +// verbose == true : Prints the error message to stderr on unhandled errors +// +// Default is throw_errors == false and verbose == true +void sw_setThrowMode(bool throw_errors); +void sw_setVerboseMode(bool verbose); +bool sw_getThrowMode(void); +bool sw_getVerboseMode(void); + + +// Abstract base class for streaming sockets +class DECLSPEC SWBaseSocket +{ +public: + SWBaseSocket(); + virtual ~SWBaseSocket(); + + // Error types + // ok - operation succesful + // fatal - unspecified error + // notReady - you should call the function again + // indicates that the function would block (if nowait/nonblocking) + // portInUse - this port is used by another socket ( on listen() ) + // notConnected - socket not connected (or valid) + // msgTooLong - the message size it too big for send() + // terminated - connection terminated (by peer) + // noResponse - can't connect() to peer + // timeout - a read/write operation timed out (only if a timeout value is set and if in blocking mode) + // interrupted - operation was interrupted by a nonblocked signal + enum base_error{ok, fatal, notReady, portInUse, notConnected, msgTooLong, terminated, noResponse, timeout, interrupted}; + + class DECLSPEC SWBaseError + { + public: + SWBaseError(); + SWBaseError(base_error e); + + virtual ~SWBaseError(){;} + + virtual std::string get_error(); + virtual SWBaseSocket* get_failedClass(void); + + virtual bool operator==(SWBaseError e); + virtual bool operator!=(SWBaseError e); + + virtual void set_errorString(std::string msg); + virtual void set_failedClass(SWBaseSocket *pnt); + protected: + friend class SWBaseSocket; + + // The base error type + base_error be; + + // Human readable error string + std::string error_string; + + // A pointer to the class causing the error + SWBaseSocket *failed_class; + }; + + + // Note: If no SWBaseError class is provided with a method call (==NULL), + // SocketW will print the error to stderr and exit or throw on errors. + + // Note: All bool functions returns true on success. + + // Block mode + // blocking - everythings blocks until completly done + // noWait - operations block but only once + // useful with blocking w. select() + // nonblocking - don't block (you should use select()) + enum block_type{blocking, noWait, nonblocking}; + + + // Connection methods + // qLimit - the maximum length the queue of pending connections. + // Accept returns a new socket class connected with peer (should be + // freed with delete) or NULL on failure. You can cast the class to + // the correct type if you need to ( eg. (SWInetSocket *)mysocket ). + virtual bool listen(int qLimit = 5, SWBaseError *error = NULL); + virtual SWBaseSocket* accept(SWBaseError *error = NULL); + // bind() and connect() are implemented in child classes + + // do the disconnect ritual (signal peer, wait for close singal and close socket) + virtual bool disconnect(SWBaseError *error = NULL); + + // force close socket + virtual bool close_fd(); //use with care, disconnect() is cleaner + + // Direct I/O (raw) + // Can send/recv less bytes than specified! + // Returns the actual amount of bytes sent/recv on sucess + // and an negative integer on failure. + virtual int send(const char *buf, int bytes, SWBaseError *error = NULL); + virtual int sendmsg(const std::string msg, SWBaseError *error = NULL); + virtual int recv(char *buf, int bytes, SWBaseError *error = NULL); + virtual std::string recvmsg(int bytes = 256, SWBaseError *error = NULL); + + // Forced I/O + // Force system to send/recv the specified amount of bytes. + // On nowait/nonblocking: might return with notReady and then you + // MUST call the same method again (eg. wait with select() to know when) + // with the same parameters until the operation is finished. + // Returns 'bytes' when finished, negative integer on failure and + // 'notReady'. In the 'notReady' case, -(return value) is the amount of + // bytes sent/recv so far. + virtual int fsend(const char *buf, int bytes, SWBaseError *error = NULL); + virtual int fsendmsg(const std::string msg, SWBaseError *error = NULL); + virtual int frecv(char *buf, int bytes, SWBaseError *error = NULL); + + // Tools + // get_fd() - get socket descriptor, can be used with select() + // returns -1 on failure. + // get_host/peer fills the provided structures with info about the + // host/peer (see man unix & ip). + // SWInetSocket has some more tools for TCP/IP sockets. + virtual int get_fd(SWBaseError *error); + virtual bool get_host(sockaddr *host, SWBaseError *error = NULL); + virtual bool get_peer(sockaddr *peer, SWBaseError *error = NULL); + + // Set recv timeout (only in blocking mode). + // set_timeout(0,0) means wait forever (default). + // This affects the functions recv(), send(), accept() and disconnect() + // and others that use those, i.e. all frecvmsg(). + void set_timeout(Uint32 sec, Uint32 usec){ tsec = sec, tusec = usec; } + + // Error handling + virtual void print_error(); //prints the last error if any to stderr + virtual std::string get_error(){return error_string;} //returns a human readable error string + +protected: + // get a new socket if myfd < 0 + virtual void get_socket()=0; + + // create a new class for accept() using socketdescriptor + virtual SWBaseSocket* create(int socketdescriptor, SWBaseError *error)=0; + + // reset state + virtual void reset(); + + // wait for I/O (with timeout) + enum io_type{read, write, except, rw, all}; + virtual bool waitIO(io_type &type, SWBaseError *error); + bool waitRead(SWBaseError *error); + bool waitWrite(SWBaseError *error); + + // internal error handling + virtual void handle_errno(SWBaseError *error, std::string msg); + virtual void no_error(SWBaseError *error); + virtual void set_error(SWBaseError *error, SWBaseError name, std::string msg); + + // our socket descriptor + int myfd; + + // last error + std::string error_string; + + // data for fsend + bool fsend_ready; + int fsend_total; + int fsend_bytesleft; + + // data for frecv + bool frecv_ready; + int frecv_total; + int frecv_bytesleft; + + // have we recived a shutdown signal? + bool recv_close; + + //blocking mode (set by child classes) + block_type block_mode; + + //timeout for waitIO() + int tsec; + int tusec; +}; + + +#endif /* sw_base_H */ diff --git a/Client/sockets/sw_inet.cpp b/Client/sockets/sw_inet.cpp new file mode 100644 index 00000000..c056722e --- /dev/null +++ b/Client/sockets/sw_inet.cpp @@ -0,0 +1,249 @@ +// C++ Socket Wrapper +// SocketW Inet socket +// +// Started 020316 +// +// License: LGPL v2.1+ (see the file LICENSE) +// (c)2002-2003 Anders Lindström + +/*********************************************************************** + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + ***********************************************************************/ + +#include "sw_inet.h" + +#ifndef __WIN32__ + #include + #include + #include + #include + #include +#else + #define F_SETFL FIONBIO + #define O_NONBLOCK 1 + + //Defined in sw_base.cxx + extern int close(int fd); + extern int fcntl(int fd, int cmd, long arg); +#endif + +using namespace std; + +//==================================================================== +//== SWInetSocket +//== Inet (TCP/IP) streaming sockets +//==================================================================== +SWInetSocket::SWInetSocket(block_type block) +{ + block_mode = block; +} + +SWInetSocket::~SWInetSocket() +{ + +} + +void SWInetSocket::get_socket() +{ + if( myfd < 0 ){ + myfd = socket(PF_INET, SOCK_STREAM, 0); + + if( block_mode == nonblocking ) + fcntl(myfd, F_SETFL, O_NONBLOCK); + + //reset state + reset(); + } +} + +SWBaseSocket* SWInetSocket::create(int socketdescriptor, SWBaseError *error) +{ + SWInetSocket* remoteClass; + + /* Create new class*/ + remoteClass = new SWInetSocket(block_mode); + remoteClass->myfd = socketdescriptor; + + no_error(error); + return remoteClass; +} + +bool SWInetSocket::bind(int port, SWBaseError *error) +{ + return bind(port, "", error); +} + +bool SWInetSocket::bind(int port, string host, SWBaseError *error) +{ + hostent *h; + in_addr inp; + + if( host.size() > 0 ){ + // Bind to a specific address + + if( (h = gethostbyname(host.c_str())) == NULL ){ + set_error(error, fatal, "SWInetSocket::bind() - Can't get host by name"); + return false; + } + + inp = *((in_addr *)h->h_addr); + }else{ + // Bind to any + inp.s_addr = INADDR_ANY; + } + + + get_socket(); + + sockaddr_in myAdr; + + memset(&myAdr, 0, sizeof(myAdr)); + myAdr.sin_family = AF_INET; + myAdr.sin_port = htons(port); + myAdr.sin_addr.s_addr = inp.s_addr; + + if(::bind(myfd, (sockaddr *)&myAdr, sizeof(myAdr)) == -1){ + handle_errno(error, "SWInetSocket::bind() error: "); + return false; + } + + no_error(error); + return true; +} + +bool SWInetSocket::connect(int port, string hostname, SWBaseError *error) +{ + get_socket(); + + hostent *host; + + if( (host = gethostbyname(hostname.c_str())) == NULL ){ + set_error(error, fatal, "SWInetSocket::connect() - Can't get host by name"); + return false; + } + + sockaddr_in remoteAdr; + + memset(&remoteAdr, 0, sizeof(remoteAdr)); + remoteAdr.sin_family = AF_INET; + remoteAdr.sin_port = htons(port); + remoteAdr.sin_addr = *((in_addr *)host->h_addr); + + if(::connect(myfd, (sockaddr *)&remoteAdr, sizeof(remoteAdr)) == -1){ + handle_errno(error, "SWInetSocket::connect() error: "); + return false; + } + + no_error(error); + return true; +} + + +string SWInetSocket::get_peerAddr(SWBaseError *error) +{ + sockaddr_in adr; + + if( !get_peer((sockaddr *)&adr, error) ) + return ""; + + char *pnt; + + if( (pnt = inet_ntoa(adr.sin_addr)) == NULL ){ + set_error(error, fatal, "SWInetSocket::get_peerName() - Can't get peer address"); + return ""; + } + string name(pnt); + + no_error(error); + return name; +} + +int SWInetSocket::get_peerPort(SWBaseError *error) +{ + sockaddr_in adr; + + if( !get_peer((sockaddr *)&adr, error) ) + return -1; + + no_error(error); + + return ntohs(adr.sin_port); +} + +string SWInetSocket::get_peerName(SWBaseError *error) +{ + string name = get_peerAddr(error); + if(name.size() < 1) + return ""; + + + hostent *h; + + if( (h = gethostbyname(name.c_str())) == NULL ){ + set_error(error, fatal, "SWInetSocket::get_peerName() - Can't get peer by address"); + return ""; + } + string host_name(h->h_name); + + no_error(error); + return host_name; +} + +string SWInetSocket::get_hostAddr(SWBaseError *error) +{ + //We need to get the real address, so we must + //first get this computers host name and then + //translate that into an address! + + string name = get_hostName(error); + if( name.size() < 1 ) + return ""; + + hostent *host; + + if( (host = gethostbyname(name.c_str())) == NULL ){ + set_error(error, fatal, "SWInetSocket::get_hostAddr() - Can't get host by name"); + return ""; + } + + char *pnt; + + if( (pnt = inet_ntoa(*((in_addr *)host->h_addr))) == NULL){ + set_error(error, fatal, "SWInetSocket::get_hostAddr() - Can't get host address"); + return ""; + } + + string adr(pnt); + + return adr; +} + +int SWInetSocket::get_hostPort(SWBaseError *error) +{ + sockaddr_in adr; + + if( !get_host((sockaddr *)&adr, error) ) + return -1; + + no_error(error); + + return ntohs(adr.sin_port); +} + +string SWInetSocket::get_hostName(SWBaseError *error) +{ + char buf[256]; + + if( gethostname(buf, 256) != 0 ){ + handle_errno(error, "SWInetSocket::gethostname() error: "); + return ""; + } + + string msg(buf); + + no_error(error); + return msg; +} diff --git a/Client/sockets/sw_inet.h b/Client/sockets/sw_inet.h new file mode 100644 index 00000000..26050845 --- /dev/null +++ b/Client/sockets/sw_inet.h @@ -0,0 +1,48 @@ +// C++ Socket Wrapper +// SocketW Inet socket header +// +// Started 020316 +// +// License: LGPL v2.1+ (see the file LICENSE) +// (c)2002-2003 Anders Lindström + +/*********************************************************************** + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + ***********************************************************************/ + +#ifndef sw_inet_H +#define sw_inet_H + +#include "sw_internal.h" +#include "sw_base.h" +#include + +// Simple streaming TCP/IP class +class DECLSPEC SWInetSocket : public SWBaseSocket +{ +public: + SWInetSocket(block_type block=blocking); + virtual ~SWInetSocket(); + + virtual bool bind(int port, SWBaseError *error = NULL); //use port=0 to get any free port + virtual bool bind(int port, std::string host, SWBaseError *error = NULL); //you can also specify the host interface to use + virtual bool connect(int port, std::string hostname, SWBaseError *error = NULL); + + // Tools + // Gets IP addr, name or port. + virtual std::string get_peerAddr(SWBaseError *error = NULL); + virtual int get_peerPort(SWBaseError *error = NULL); + virtual std::string get_peerName(SWBaseError *error = NULL); + virtual std::string get_hostAddr(SWBaseError *error = NULL); + virtual int get_hostPort(SWBaseError *error = NULL); + virtual std::string get_hostName(SWBaseError *error = NULL); + +protected: + virtual void get_socket(); + virtual SWBaseSocket* create(int socketdescriptor, SWBaseError *error); +}; + +#endif /* sw_inet_H */ diff --git a/Client/sockets/sw_internal.h b/Client/sockets/sw_internal.h new file mode 100644 index 00000000..94313bcd --- /dev/null +++ b/Client/sockets/sw_internal.h @@ -0,0 +1,75 @@ +// C++ Socket Wrapper +// SocketW internal header +// +// Started 030823 +// +// License: LGPL v2.1+ (see the file LICENSE) +// (c)2002-2003 Anders Lindstr�m + +/*********************************************************************** + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + ***********************************************************************/ + +#ifndef sw_internal_H +#define sw_internal_H + +// This header is included in all *.h files + +#ifndef __WIN32__ + #include + #include + #include + #include +#else + #include + + #define F_SETFL FIONBIO + #define O_NONBLOCK 1 +#endif + +#ifndef _SDL_H + +// Define general types +typedef unsigned char Uint8; +typedef signed char Sint8; +typedef unsigned short Uint16; +typedef signed short Sint16; +typedef unsigned int Uint32; +typedef signed int Sint32; + +// It's VERY important that these types really have the right sizes! +// This black magic is from SDL +#define COMPILE_TIME_ASSERT(name, x) \ + typedef int _dummy_ ## name[(x) * 2 - 1] +COMPILE_TIME_ASSERT(uint8, sizeof(Uint8) == 1); +COMPILE_TIME_ASSERT(sint8, sizeof(Sint8) == 1); +COMPILE_TIME_ASSERT(uint16, sizeof(Uint16) == 2); +COMPILE_TIME_ASSERT(sint16, sizeof(Sint16) == 2); +COMPILE_TIME_ASSERT(uint32, sizeof(Uint32) == 4); +COMPILE_TIME_ASSERT(sint32, sizeof(Sint32) == 4); +#undef COMPILE_TIME_ASSERT + +#endif /* _SDL_H */ + +// Some compilers use a special export keyword +#ifndef DECLSPEC + #ifdef __BEOS__ + #if defined(__GNUC__) + #define DECLSPEC __declspec(dllexport) + #else + #define DECLSPEC __declspec(export) + #endif + #else + #ifdef WIN32 + #define DECLSPEC __declspec(dllexport) + #else + #define DECLSPEC + #endif + #endif +#endif + + +#endif /* sw_internal_H */ diff --git a/Client/sockets/sw_unix.cpp b/Client/sockets/sw_unix.cpp new file mode 100644 index 00000000..07e2dd10 --- /dev/null +++ b/Client/sockets/sw_unix.cpp @@ -0,0 +1,99 @@ +// C++ Socket Wrapper +// SocketW Unix socket +// +// Started 020316 +// +// License: LGPL v2.1+ (see the file LICENSE) +// (c)2002-2003 Anders Lindström + +/*********************************************************************** + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + ***********************************************************************/ + +#include "sw_unix.h" +#include + +using namespace std; + +//==================================================================== +//== SWUnixSocket +//== Unix streaming sockets +//==================================================================== +#ifndef __WIN32__ + +SWUnixSocket::SWUnixSocket(block_type block) +{ + block_mode = block; +} + +SWUnixSocket::~SWUnixSocket() +{ + //nothing here +} + +void SWUnixSocket::get_socket() +{ + if( myfd < 0 ){ + myfd = socket(PF_UNIX, SOCK_STREAM, 0); + + if( block_mode == nonblocking ) + fcntl(myfd, F_SETFL, O_NONBLOCK); + + //reset state + reset(); + } +} + + +SWBaseSocket* SWUnixSocket::create(int socketdescriptor, SWBaseError *error) +{ + SWUnixSocket* remoteClass; + + /* Create new class*/ + remoteClass = new SWUnixSocket(block_mode); + remoteClass->myfd = socketdescriptor; + + no_error(error); + return remoteClass; +} + +bool SWUnixSocket::bind(string path, SWBaseError *error) +{ + get_socket(); + + sockaddr_un myAdr; + + myAdr.sun_family = AF_UNIX; + strncpy(myAdr.sun_path, path.c_str(), path.size()+1); + + if(::bind(myfd, (sockaddr *)&myAdr, sizeof(myAdr)) == -1){ + handle_errno(error, "SWUnixSocket::bind() error: "); + return false; + } + + no_error(error); + return true; +} + +bool SWUnixSocket::connect(string path, SWBaseError *error) +{ + get_socket(); + + sockaddr_un remoteAdr; + + remoteAdr.sun_family = AF_UNIX; + strncpy(remoteAdr.sun_path, path.c_str(), path.size()+1); + + if(::connect(myfd, (sockaddr *)&remoteAdr, sizeof(remoteAdr)) == -1){ + handle_errno(error, "SWUnixSocket::connect() error: "); + return false; + } + + no_error(error); + return true; +} + +#endif /* __WIN32__ */ diff --git a/Client/sockets/sw_unix.h b/Client/sockets/sw_unix.h new file mode 100644 index 00000000..576f14c0 --- /dev/null +++ b/Client/sockets/sw_unix.h @@ -0,0 +1,41 @@ +// C++ Socket Wrapper +// SocketW Unix socket header +// +// Started 020316 +// +// License: LGPL v2.1+ (see the file LICENSE) +// (c)2002-2003 Anders Lindström + +/*********************************************************************** + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + ***********************************************************************/ + +#ifndef sw_unix_H +#define sw_unix_H +#ifndef __WIN32__ + +#include "sw_internal.h" +#include "sw_base.h" +#include + +// Simple streaming Unix class +class DECLSPEC SWUnixSocket : public SWBaseSocket +{ +public: + SWUnixSocket(block_type block=blocking); + ~SWUnixSocket(); + + // bind and connect to the socket file "path" + virtual bool bind(std::string path, SWBaseError *error = NULL); + virtual bool connect(std::string path, SWBaseError *error = NULL); + +protected: + virtual void get_socket(); + virtual SWBaseSocket* create(int socketdescriptor, SWBaseError *error); +}; + +#endif /* __WIN32__ */ +#endif /* sw_unix_H */ diff --git a/Server/Makefile b/Server/Makefile new file mode 100644 index 00000000..0d022100 --- /dev/null +++ b/Server/Makefile @@ -0,0 +1,18 @@ +SRC = main.cpp sockets/sw_base.cpp sockets/sw_inet.cpp sockets/sw_unix.cpp +OBJ = $(SRC:.cpp=.o) +OUT = Socket +INCLUDES = +CCFLAGS = -Wall -Wextra -funsigned-char -g +CC = $(CROSS)g++ +LD = $(CROSS)ld +AR = $(CROSS)ar +LIBS = +.SUFFIXES: .cpp +.PHONY: clean default +default: $(OUT) +.cpp.o: + $(CC) $(INCLUDES) $(CCFLAGS) $(LIBS) -c $< -o $@ +$(OUT): $(OBJ) + $(CC) $(LIBS) -o $(OUT) $(OBJ) +clean: + rm -rf $(OBJ) $(OUT) Makefile.bak *~ diff --git a/Server/main.cpp b/Server/main.cpp new file mode 100644 index 00000000..540479fe --- /dev/null +++ b/Server/main.cpp @@ -0,0 +1,72 @@ +#include +#include "sockets/SocketW.h" +#include +#include +#include +#include + +#define BUFLEN 3000000 + +bool machineEndianness() { + int i = 1; + char *p = (char *) &i; + if (p[0] == 1) { + return false;//little-endian + } else { + return true; + } +} + +int main() { + char buffer[BUFLEN]; + char input[BUFLEN]; + int inp_amount; + int position_current = 0; + int position_startframe = 0; + int frame_bodylength = 0; + SWUnixSocket listener; + SWUnixSocket *mySocket; + SWBaseSocket::SWBaseError BError; + char header[13] = {'F','L','V',0x01,0x05,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x00}; + + listener.bind("../socketfile"); + listener.listen(); + listener.set_timeout(1,0); + + while(true) { + inp_amount = fread(&input,1,11,stdin); + if (input[0] == 9) { + if (!mySocket) { + mySocket = (SWUnixSocket *)listener.accept(&BError); + mySocket->send(&header[0],13); + } + } + std::cout << "Blaah\n"; + position_current = 0; + position_startframe = position_current; + for(int i = 0; i < 11; i++) { buffer[position_current] = input[i]; position_current ++; } + frame_bodylength = 0; + if (machineEndianness() ) { + frame_bodylength += input[1]; + frame_bodylength += (input[2] << 8); + frame_bodylength += (input[3] << 16); + } else { + frame_bodylength += input[3]; + frame_bodylength += (input[2] << 8); + frame_bodylength += (input[1] << 16); + } + std::cout << frame_bodylength << "\n"; + for (int i = 0; i < frame_bodylength + 4; i++) { + inp_amount = fread(&input,1,1,stdin); + buffer[position_current] = input[0]; position_current ++; + std::cout << " " << position_current << "\n"; + } + std::cout << "Total message read!\n"; + exit(0); + mySocket->send(&buffer[0], position_current-1, &BError); + } + + // disconnect and clean up + mySocket->disconnect(); + return 0; +} diff --git a/Server/sockets.zip b/Server/sockets.zip new file mode 100644 index 0000000000000000000000000000000000000000..5c2dee19654211a39e9c380c095e4c08dffda003 GIT binary patch literal 13832 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μ&E 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 E2f0*~)Bpeg literal 0 HcmV?d00001 diff --git a/Server/sockets/SocketW.h b/Server/sockets/SocketW.h new file mode 100644 index 00000000..b7096c0c --- /dev/null +++ b/Server/sockets/SocketW.h @@ -0,0 +1,22 @@ +// C++ Socket Wrapper +// +// Started 020316 +// +// License: LGPL v2.1+ (see the file LICENSE) +// (c)2002-2003 Anders Lindstr�m + +/*********************************************************************** + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + ***********************************************************************/ + +#ifndef SocketW_H +#define SocketW_H + +#include "sw_base.h" +#include "sw_unix.h" +#include "sw_inet.h" + +#endif //SocketW_H diff --git a/Server/sockets/sw_base.cpp b/Server/sockets/sw_base.cpp new file mode 100644 index 00000000..23ca1eb6 --- /dev/null +++ b/Server/sockets/sw_base.cpp @@ -0,0 +1,764 @@ +// C++ Socket Wrapper +// SocketW base class +// +// Started 020316 +// +// License: LGPL v2.1+ (see the file LICENSE) +// (c)2002-2003 Anders Lindstr�m + +/*********************************************************************** + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + ***********************************************************************/ + +#include "sw_base.h" +#include +#include +#include +#include +#include + +#ifndef __WIN32__ + #include + #include + #include + #include + #include + + #define INVALID_SOCKET -1 //avoid M$ braindamage +#else + //why use POSIX standards when we can make our own + //and frustrate people? (well known M$ policy) + + #ifndef EBADF + #define EBADF WSAEBADF + #endif + + #define ENOTSOCK WSAENOTSOCK + #define EOPNOTSUPP WSAEOPNOTSUPP + #define EADDRINUSE WSAEADDRINUSE + #define EWOULDBLOCK WSAEWOULDBLOCK + #define EMSGSIZE WSAEMSGSIZE + #define EINPROGRESS WSAEINPROGRESS + #define EALREADY WSAEALREADY + #define ECONNREFUSED WSAECONNREFUSED + #define ETIMEDOUT WSAETIMEDOUT + #define ENOTCONN WSAENOTCONN + + #ifndef EINTR + #define EINTR WSAEINTR + #endif +#endif + +#ifndef MSG_NOSIGNAL + #define MSG_NOSIGNAL 0 +#endif + +// Socklen hack +#if defined(__linux__) || defined(__FreeBSD__) // || defined(__bsdi__) || defined(__NetBSD__) too, perhaps? Bugreports, please! + #define sw_socklen_t socklen_t +#elif defined(__WIN32__) || defined(__osf__) + #define sw_socklen_t int +#else + #define sw_socklen_t unsigned int +#endif + + +using namespace std; + +#ifdef __WIN32__ +//Win32 braindamage +int close(int fd) +{ + return closesocket(fd); +} + +int fcntl(int fd, int cmd, long arg) +{ + unsigned long mode = arg; + + return WSAIoctl(fd, cmd, &mode, sizeof(unsigned long), NULL, 0, NULL, NULL, NULL); +} + +void WSA_exit(void) +{ + WSACleanup(); +} +#endif + + +//==================================================================== +//== Error handling mode +//==================================================================== +bool sw_DoThrow = false; +bool sw_Verbose = true; + +void sw_setThrowMode(bool throw_errors) +{ + sw_DoThrow = throw_errors; +} + +void sw_setVerboseMode(bool verbose) +{ + sw_Verbose = verbose; +} + +bool sw_getThrowMode(void) +{ + return sw_DoThrow; +} + +bool sw_getVerboseMode(void) +{ + return sw_Verbose; +} + + +//==================================================================== +//== Base error class +//==================================================================== +SWBaseSocket::SWBaseError::SWBaseError() +{ + be = ok; + error_string = ""; + failed_class = NULL; +} + +SWBaseSocket::SWBaseError::SWBaseError(base_error e) +{ + be = e; + error_string = ""; + failed_class = NULL; +} + +string SWBaseSocket::SWBaseError::get_error() +{ + return error_string; +} + +SWBaseSocket* SWBaseSocket::SWBaseError::get_failedClass(void) +{ + return failed_class; +} + +void SWBaseSocket::SWBaseError::set_errorString(string msg) +{ + error_string = msg; +} + +void SWBaseSocket::SWBaseError::set_failedClass(SWBaseSocket *pnt) +{ + failed_class = pnt; +} + +bool SWBaseSocket::SWBaseError::operator==(SWBaseError e) +{ + return be == e.be; +} + +bool SWBaseSocket::SWBaseError::operator!=(SWBaseError e) +{ + return be != e.be; +} + + +//==================================================================== +//== SWBaseSocket +//== Base class for sockets +//==================================================================== +SWBaseSocket::SWBaseSocket() +{ + //indicate nonopen + myfd = -1; + recv_close = false; + + //init values + error_string = ""; + block_mode = blocking; + fsend_ready = true; + frecv_ready = true; + tsec = 0; + tusec = 0; + + #ifdef __WIN32__ + //kick winsock awake + static bool firstuse = true; + if( firstuse == true ){ + WSAData wsaData; + int nCode; + if( (nCode = WSAStartup(MAKEWORD(1, 1), &wsaData)) != 0 ){ + handle_errno(NULL, "SWBaseSocket - WSAStartup() failed: "); + exit(-1); // Should never happend + } + + //cleanup at exit + atexit(WSA_exit); + firstuse = false; + } + #endif /* __WIN32__ */ +} + +SWBaseSocket::~SWBaseSocket() +{ + if(myfd > 0) + close(myfd); +} + +bool SWBaseSocket::listen(int qLimit, SWBaseError *error) +{ + get_socket(); + + //Avoid "Address already in use" thingie + char yes=1; + setsockopt(myfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); + + if(::listen(myfd, qLimit) == -1){ + handle_errno(error, "SWBaseSocket::listen() error: "); + return false; + } + + no_error(error); + return true; +} + +SWBaseSocket* SWBaseSocket::accept(SWBaseError *error) +{ + int remotefd = -1; + sockaddr remoteAdr; + + if( !waitRead(error) ) + return NULL; + + sw_socklen_t ssize = sizeof(sockaddr); + + if((remotefd = ::accept(myfd, &remoteAdr, &ssize)) == int(INVALID_SOCKET)){ + handle_errno(error, "SWBaseSocket::accept() error: "); + return NULL; + } + + //nonblocking? + if( block_mode == nonblocking ) + fcntl(remotefd, F_SETFL, O_NONBLOCK); + + /* Create new class*/ + SWBaseSocket* remoteClass = create(remotefd, error); + if( remoteClass == NULL ) + return NULL; + + no_error(error); + return remoteClass; +} + +bool SWBaseSocket::disconnect(SWBaseError *error) +{ + int n = 0; + char buf[256]; + + if(myfd < 0){ + set_error(error, notConnected, "SWBaseSocket::disconnect() - No connection"); + return false; + } + + //close WR (this signals the peer) + if( shutdown(myfd, 1) != 0 ){ + handle_errno(error, "SWBaseSocket::disconnect() error: "); + return false; + } + + + SWBaseError err; + + //wait for close signal from peer + if( recv_close == false ){ + while(true){ + if( !waitRead(error) ) + return false; + + n = recv(buf, 256, &err); + + if( n <= 0 ) + break; + if(block_mode == noWait){ + //we don't want to block + set_error(error, notReady, "SWBaseSocket::disconnect() - Need more time, call again"); + return false; + } + } + } + + if( n != 0 ){ + set_error(error, err, error_string); + return false; //error + } + + //reset state + reset(); + + close(myfd); + myfd = -1; + + no_error(error); + return true; +} + +bool SWBaseSocket::close_fd() +{ + if( myfd > 0 ){ + close(myfd); + myfd = -1; + + //reset state + reset(); + + return true; + } + return false; +} + +int SWBaseSocket::send(const char *buf, int bytes, SWBaseError *error) +{ + int ret; + + if(myfd < 0){ + set_error(error, notConnected, "SWBaseSocket::send() - No connection"); + return -1; + } + + if( !waitWrite(error) ) + return -1; + + ret = ::send(myfd, buf, bytes, MSG_NOSIGNAL); + + if( ret < 0 ) + handle_errno(error, "SWBaseSocket::send() error: "); + else + no_error(error); + + return ret; +} + +int SWBaseSocket::fsend(const char *buf, int bytes, SWBaseError *error) +{ + int n; + int bytessent; + + if(fsend_ready){ + //First call + fsend_bytesleft = bytes; + fsend_total = fsend_bytesleft; //global var needed for resume + bytessent = 0; + fsend_ready = false; //point of no return + } + else{ + //resume + bytessent = fsend_total - fsend_bytesleft; + } + + //send package + while( fsend_bytesleft > 0 ){ + n = send( buf + bytessent , fsend_bytesleft, error ); + + //return on error, wouldblock or nowait + if( n < 0 ) + return ( (bytessent > 0 )? -bytessent : -1 ); + + bytessent += n; + fsend_bytesleft -= n; + + if ( block_mode == noWait && fsend_bytesleft > 0 ){ + set_error(error, notReady, "SWBaseSocket::fsend() - Need more time, call again"); + return -bytessent; + } + } + + fsend_ready = true; + + no_error(error); + return fsend_total; +} + +int SWBaseSocket::sendmsg(const string msg, SWBaseError *error) +{ + return send(msg.c_str(), msg.size(), error); +} + +int SWBaseSocket::fsendmsg(const string msg, SWBaseError *error) +{ + return fsend(msg.c_str(), msg.size(), error); +} + +int SWBaseSocket::recv(char *buf, int bytes, SWBaseError *error) +{ + int ret; + + if(myfd < 0){ + set_error(error, notConnected, "SWBaseSocket::recv() - No connection"); + return -1; + } + + if( !waitRead(error) ) + return -1; + + ret = ::recv(myfd, buf, bytes, MSG_NOSIGNAL); + + if( ret < 0 ) + handle_errno(error, "SWBaseSocket::recv() error: "); + else if( ret == 0 ){ + recv_close = true; //we recived a close signal from peer + set_error(error, terminated, "SWBaseSocket::recv() - Connection terminated by peer"); + }else + no_error(error); + + return ret; +} + +int SWBaseSocket::frecv(char *buf, int bytes, SWBaseError *error) +{ + int n; + int bytesrecv; + + if(frecv_ready){ + //First call + frecv_bytesleft = bytes; + frecv_total = frecv_bytesleft; //global var needed for resume + bytesrecv = 0; + frecv_ready = false; //point of no return + } + else{ + //resume + bytesrecv = frecv_total - frecv_bytesleft; + } + + + //recv package + while( frecv_bytesleft > 0 ){ + n = recv( buf + bytesrecv , frecv_bytesleft, error ); + + //return on error, wouldblock, nowait or timeout + if( n < 0 ) + return ( (bytesrecv > 0 )? -bytesrecv : -1 ); + if( n == 0 ) + return 0; // terminated + + bytesrecv += n; + frecv_bytesleft -= n; + + if ( block_mode == noWait && frecv_bytesleft > 0 ){ + set_error(error, notReady, "SWBaseSocket::frecv() - Need more time, call again"); + return -bytesrecv; + } + } + + frecv_ready = true; + + no_error(error); + return frecv_total; +} + +string SWBaseSocket::recvmsg(int bytes, SWBaseError *error) +{ + char *buf = new char[bytes+1]; + + SWBaseError err; + string msg = ""; + int ret = recv(buf, bytes, &err); + + if( ret > 0 ){ + buf[ret]='\0'; // Make sure the string is null terminated + msg = buf; + no_error(error); + } + delete[] buf; + + if( ret < 1 ) + set_error(error, err, err.get_error()); + + return msg; +} + +int SWBaseSocket::get_fd(SWBaseError *error) +{ + if( myfd > 0 ){ + no_error(error); + return myfd; + } + + set_error(error, notConnected, "SWBaseSocket::get_fd() - No descriptor"); + return -1; +} + +bool SWBaseSocket::get_host(sockaddr *host, SWBaseError *error) +{ + if( host == NULL){ + set_error(error, fatal, "SWBaseSocket::get_host() - Got NULL pointer"); + return false; + } + + if(myfd < 0){ + set_error(error, notConnected, "SWBaseSocket::get_host() - No socket"); + return false; + } + + sw_socklen_t tmp = sizeof(sockaddr); + if( getsockname(myfd, host, &tmp) != 0 ){ + handle_errno(error, "SWBaseSocket::get_host() error: "); + return false; + } + + no_error(error); + return true; +} + +bool SWBaseSocket::get_peer(sockaddr *peer, SWBaseError *error) +{ + if( peer == NULL){ + set_error(error, fatal, "SWBaseSocket::get_peer() - Got NULL pointer"); + return false; + } + + if(myfd > 0){ + sw_socklen_t tmp = sizeof(sockaddr); + if( getpeername(myfd, peer, &tmp) != 0 ){ + handle_errno(error, "SWBaseSocket::get_peer() error: "); + return false; + } + }else{ + set_error(error, notConnected, "SWBaseSocket::get_peer() - No connection"); + return false; + } + + no_error(error); + return true; +} + +void SWBaseSocket::reset() +{ + // Reset flags + recv_close = false; + + fsend_ready = true; + frecv_ready = true; +} + +bool SWBaseSocket::waitIO(io_type &type, SWBaseError *error) +{ + if( block_mode != blocking ){ + no_error(error); + return true; + } + + // We prefere to wait with select() even if no timeout is set + // as select() behaves more predictable + + timeval t; + timeval *to = NULL; // Indicate "wait for ever" + t.tv_sec = tsec; + t.tv_usec = tusec; + + if( tsec > 0 || tusec > 0 ) + to = &t; + + fd_set readfds, writefds, exceptfds; + + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&exceptfds); + FD_SET(myfd, &readfds); + FD_SET(myfd, &writefds); + FD_SET(myfd, &exceptfds); + + int ret = 0; + + switch (type){ + case read: + ret = select(myfd+1, &readfds, NULL, NULL, to); + break; + case write: + ret = select(myfd+1, NULL, &writefds, NULL, to); + break; + case except: + ret = select(myfd+1, NULL, NULL, &exceptfds, to); + break; + case rw: + ret = select(myfd+1, &readfds, &writefds, NULL, to); + break; + case all: + ret = select(myfd+1, &readfds, &writefds, &exceptfds, to); + break; + } + + if( ret < 0 ){ + handle_errno(error, "SWBaseSocket::waitIO() error: "); + return false; + } + if( ret == 0 ){ + set_error(error, timeout, "SWBaseSocket::waitIO() timeout"); + return false; + } + + if( FD_ISSET(myfd, &readfds) ){ + no_error(error); + type = read; + return true; + } + if( FD_ISSET(myfd, &writefds) ){ + no_error(error); + type = write; + return true; + } + if( FD_ISSET(myfd, &exceptfds) ){ + no_error(error); + type = except; + return true; + } + + set_error(error, fatal, "SWBaseSocket::waitIO() failed on select()"); + return false; +} + +bool SWBaseSocket::waitRead(SWBaseError *error) +{ + io_type tmp = read; + return waitIO(tmp, error); +} + +bool SWBaseSocket::waitWrite(SWBaseError *error) +{ + io_type tmp = write; + return waitIO(tmp, error); +} + +void SWBaseSocket::print_error() +{ + if( error_string.size() > 0 ) + fprintf(stderr, "%s!\n", error_string.c_str()); +} + +void SWBaseSocket::handle_errno(SWBaseError *error, string msg) +{ + #ifndef __WIN32__ + msg += strerror(errno); + #else + //stupid stupid stupid stupid M$ + switch (WSAGetLastError()){ + case 0: msg += "No error"; break; + case WSAEINTR: msg += "Interrupted system call"; break; + case WSAEBADF: msg += "Bad file number"; break; + case WSAEACCES: msg += "Permission denied"; break; + case WSAEFAULT: msg += "Bad address"; break; + case WSAEINVAL: msg += "Invalid argument"; break; + case WSAEMFILE: msg += "Too many open sockets"; break; + case WSAEWOULDBLOCK: msg += "Operation would block"; break; + case WSAEINPROGRESS: msg += "Operation now in progress"; break; + case WSAEALREADY: msg += "Operation already in progress"; break; + case WSAENOTSOCK: msg += "Socket operation on non-socket"; break; + case WSAEDESTADDRREQ: msg += "Destination address required"; break; + case WSAEMSGSIZE: msg += "Message too long"; break; + case WSAEPROTOTYPE: msg += "Protocol wrong type for socket"; break; + case WSAENOPROTOOPT: msg += "Bad protocol option"; break; + case WSAEPROTONOSUPPORT: msg += "Protocol not supported"; break; + case WSAESOCKTNOSUPPORT: msg += "Socket type not supported"; break; + case WSAEOPNOTSUPP: msg += "Operation not supported on socket"; break; + case WSAEPFNOSUPPORT: msg += "Protocol family not supported"; break; + case WSAEAFNOSUPPORT: msg += "Address family not supported"; break; + case WSAEADDRINUSE: msg += "Address already in use"; break; + case WSAEADDRNOTAVAIL: msg += "Can't assign requested address"; break; + case WSAENETDOWN: msg += "Network is down"; break; + case WSAENETUNREACH: msg += "Network is unreachable"; break; + case WSAENETRESET: msg += "Net connection reset"; break; + case WSAECONNABORTED: msg += "Software caused connection abort"; break; + case WSAECONNRESET: msg += "Connection reset by peer"; break; + case WSAENOBUFS: msg += "No buffer space available"; break; + case WSAEISCONN: msg += "Socket is already connected"; break; + case WSAENOTCONN: msg += "Socket is not connected"; break; + case WSAESHUTDOWN: msg += "Can't send after socket shutdown"; break; + case WSAETOOMANYREFS: msg += "Too many references"; break; + case WSAETIMEDOUT: msg += "Connection timed out"; break; + case WSAECONNREFUSED: msg += "Connection refused"; break; + case WSAELOOP: msg += "Too many levels of symbolic links"; break; + case WSAENAMETOOLONG: msg += "File name too long"; break; + case WSAEHOSTDOWN: msg += "Host is down"; break; + case WSAEHOSTUNREACH: msg += "No route to host"; break; + case WSAENOTEMPTY: msg += "Directory not empty"; break; + case WSAEPROCLIM: msg += "Too many processes"; break; + case WSAEUSERS: msg += "Too many users"; break; + case WSAEDQUOT: msg += "Disc quota exceeded"; break; + case WSAESTALE: msg += "Stale NFS file handle"; break; + case WSAEREMOTE: msg += "Too many levels of remote in path"; break; + case WSASYSNOTREADY: msg += "Network system is unavailable"; break; + case WSAVERNOTSUPPORTED: msg += "Winsock version out of range"; break; + case WSANOTINITIALISED: msg += "WSAStartup not yet called"; break; + case WSAEDISCON: msg += "Graceful shutdown in progress"; break; + case WSAHOST_NOT_FOUND: msg += "Host not found"; break; + case WSANO_DATA: msg += "No host data of that type was found"; break; + default: msg += "Unknown Winsock error: " + WSAGetLastError(); break; + } + #endif + + int errorno; + + //Win32 braindamage + #ifdef __WIN32__ + errorno = WSAGetLastError(); + #else + errorno = errno; + #endif + + SWBaseError e; + + if( errorno == EADDRINUSE ) + e = portInUse; + else if( errorno == EAGAIN || errorno == EWOULDBLOCK ) + e = notReady; + else if( errorno == EMSGSIZE ) + e = msgTooLong; + else if( errorno == EINPROGRESS || errorno == EALREADY ) + e = notReady; + else if( errorno == ECONNREFUSED || errorno == ETIMEDOUT ) + e = noResponse; + else if( errorno == ENOTCONN || errorno == EBADF || errorno == ENOTSOCK ) + e = notConnected; + else if( errorno == EPIPE ){ + e = terminated; + recv_close = true; + }else if( errorno == EINTR ) + e = interrupted; + else + e = fatal; //default + + set_error(error, e, msg); +} + +void SWBaseSocket::no_error(SWBaseError *error) +{ + if(error != NULL){ + *error = ok; + error->error_string = ""; + error->failed_class = NULL; + } +} + +void SWBaseSocket::set_error(SWBaseError *error, SWBaseError name, string msg) +{ + error_string = msg; + + if(error != NULL){ + *error = name; + error->error_string = msg; + error->failed_class = this; + }else{ + if( sw_Verbose ) + print_error(); + + if( sw_DoThrow ){ + SWBaseError e; + e = name; + e.error_string = msg; + e.failed_class = this; + throw e; + } + } +} + diff --git a/Server/sockets/sw_base.h b/Server/sockets/sw_base.h new file mode 100644 index 00000000..a6a191f1 --- /dev/null +++ b/Server/sockets/sw_base.h @@ -0,0 +1,205 @@ +// C++ Socket Wrapper +// SocketW base socket header +// +// Started 020316 +// +// License: LGPL v2.1+ (see the file LICENSE) +// (c)2002-2003 Anders Lindström + +/*********************************************************************** + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + ***********************************************************************/ + +#ifndef sw_base_H +#define sw_base_H + +#include "sw_internal.h" + +#include +#include + +// Set error handling mode +// throw_errors == true : Throws the error class on unhandled errors +// throw_errors == false : Exit on unhandled errors +// verbose == true : Prints the error message to stderr on unhandled errors +// +// Default is throw_errors == false and verbose == true +void sw_setThrowMode(bool throw_errors); +void sw_setVerboseMode(bool verbose); +bool sw_getThrowMode(void); +bool sw_getVerboseMode(void); + + +// Abstract base class for streaming sockets +class DECLSPEC SWBaseSocket +{ +public: + SWBaseSocket(); + virtual ~SWBaseSocket(); + + // Error types + // ok - operation succesful + // fatal - unspecified error + // notReady - you should call the function again + // indicates that the function would block (if nowait/nonblocking) + // portInUse - this port is used by another socket ( on listen() ) + // notConnected - socket not connected (or valid) + // msgTooLong - the message size it too big for send() + // terminated - connection terminated (by peer) + // noResponse - can't connect() to peer + // timeout - a read/write operation timed out (only if a timeout value is set and if in blocking mode) + // interrupted - operation was interrupted by a nonblocked signal + enum base_error{ok, fatal, notReady, portInUse, notConnected, msgTooLong, terminated, noResponse, timeout, interrupted}; + + class DECLSPEC SWBaseError + { + public: + SWBaseError(); + SWBaseError(base_error e); + + virtual ~SWBaseError(){;} + + virtual std::string get_error(); + virtual SWBaseSocket* get_failedClass(void); + + virtual bool operator==(SWBaseError e); + virtual bool operator!=(SWBaseError e); + + virtual void set_errorString(std::string msg); + virtual void set_failedClass(SWBaseSocket *pnt); + protected: + friend class SWBaseSocket; + + // The base error type + base_error be; + + // Human readable error string + std::string error_string; + + // A pointer to the class causing the error + SWBaseSocket *failed_class; + }; + + + // Note: If no SWBaseError class is provided with a method call (==NULL), + // SocketW will print the error to stderr and exit or throw on errors. + + // Note: All bool functions returns true on success. + + // Block mode + // blocking - everythings blocks until completly done + // noWait - operations block but only once + // useful with blocking w. select() + // nonblocking - don't block (you should use select()) + enum block_type{blocking, noWait, nonblocking}; + + + // Connection methods + // qLimit - the maximum length the queue of pending connections. + // Accept returns a new socket class connected with peer (should be + // freed with delete) or NULL on failure. You can cast the class to + // the correct type if you need to ( eg. (SWInetSocket *)mysocket ). + virtual bool listen(int qLimit = 5, SWBaseError *error = NULL); + virtual SWBaseSocket* accept(SWBaseError *error = NULL); + // bind() and connect() are implemented in child classes + + // do the disconnect ritual (signal peer, wait for close singal and close socket) + virtual bool disconnect(SWBaseError *error = NULL); + + // force close socket + virtual bool close_fd(); //use with care, disconnect() is cleaner + + // Direct I/O (raw) + // Can send/recv less bytes than specified! + // Returns the actual amount of bytes sent/recv on sucess + // and an negative integer on failure. + virtual int send(const char *buf, int bytes, SWBaseError *error = NULL); + virtual int sendmsg(const std::string msg, SWBaseError *error = NULL); + virtual int recv(char *buf, int bytes, SWBaseError *error = NULL); + virtual std::string recvmsg(int bytes = 256, SWBaseError *error = NULL); + + // Forced I/O + // Force system to send/recv the specified amount of bytes. + // On nowait/nonblocking: might return with notReady and then you + // MUST call the same method again (eg. wait with select() to know when) + // with the same parameters until the operation is finished. + // Returns 'bytes' when finished, negative integer on failure and + // 'notReady'. In the 'notReady' case, -(return value) is the amount of + // bytes sent/recv so far. + virtual int fsend(const char *buf, int bytes, SWBaseError *error = NULL); + virtual int fsendmsg(const std::string msg, SWBaseError *error = NULL); + virtual int frecv(char *buf, int bytes, SWBaseError *error = NULL); + + // Tools + // get_fd() - get socket descriptor, can be used with select() + // returns -1 on failure. + // get_host/peer fills the provided structures with info about the + // host/peer (see man unix & ip). + // SWInetSocket has some more tools for TCP/IP sockets. + virtual int get_fd(SWBaseError *error); + virtual bool get_host(sockaddr *host, SWBaseError *error = NULL); + virtual bool get_peer(sockaddr *peer, SWBaseError *error = NULL); + + // Set recv timeout (only in blocking mode). + // set_timeout(0,0) means wait forever (default). + // This affects the functions recv(), send(), accept() and disconnect() + // and others that use those, i.e. all frecvmsg(). + void set_timeout(Uint32 sec, Uint32 usec){ tsec = sec, tusec = usec; } + + // Error handling + virtual void print_error(); //prints the last error if any to stderr + virtual std::string get_error(){return error_string;} //returns a human readable error string + +protected: + // get a new socket if myfd < 0 + virtual void get_socket()=0; + + // create a new class for accept() using socketdescriptor + virtual SWBaseSocket* create(int socketdescriptor, SWBaseError *error)=0; + + // reset state + virtual void reset(); + + // wait for I/O (with timeout) + enum io_type{read, write, except, rw, all}; + virtual bool waitIO(io_type &type, SWBaseError *error); + bool waitRead(SWBaseError *error); + bool waitWrite(SWBaseError *error); + + // internal error handling + virtual void handle_errno(SWBaseError *error, std::string msg); + virtual void no_error(SWBaseError *error); + virtual void set_error(SWBaseError *error, SWBaseError name, std::string msg); + + // our socket descriptor + int myfd; + + // last error + std::string error_string; + + // data for fsend + bool fsend_ready; + int fsend_total; + int fsend_bytesleft; + + // data for frecv + bool frecv_ready; + int frecv_total; + int frecv_bytesleft; + + // have we recived a shutdown signal? + bool recv_close; + + //blocking mode (set by child classes) + block_type block_mode; + + //timeout for waitIO() + int tsec; + int tusec; +}; + + +#endif /* sw_base_H */ diff --git a/Server/sockets/sw_inet.cpp b/Server/sockets/sw_inet.cpp new file mode 100644 index 00000000..c056722e --- /dev/null +++ b/Server/sockets/sw_inet.cpp @@ -0,0 +1,249 @@ +// C++ Socket Wrapper +// SocketW Inet socket +// +// Started 020316 +// +// License: LGPL v2.1+ (see the file LICENSE) +// (c)2002-2003 Anders Lindström + +/*********************************************************************** + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + ***********************************************************************/ + +#include "sw_inet.h" + +#ifndef __WIN32__ + #include + #include + #include + #include + #include +#else + #define F_SETFL FIONBIO + #define O_NONBLOCK 1 + + //Defined in sw_base.cxx + extern int close(int fd); + extern int fcntl(int fd, int cmd, long arg); +#endif + +using namespace std; + +//==================================================================== +//== SWInetSocket +//== Inet (TCP/IP) streaming sockets +//==================================================================== +SWInetSocket::SWInetSocket(block_type block) +{ + block_mode = block; +} + +SWInetSocket::~SWInetSocket() +{ + +} + +void SWInetSocket::get_socket() +{ + if( myfd < 0 ){ + myfd = socket(PF_INET, SOCK_STREAM, 0); + + if( block_mode == nonblocking ) + fcntl(myfd, F_SETFL, O_NONBLOCK); + + //reset state + reset(); + } +} + +SWBaseSocket* SWInetSocket::create(int socketdescriptor, SWBaseError *error) +{ + SWInetSocket* remoteClass; + + /* Create new class*/ + remoteClass = new SWInetSocket(block_mode); + remoteClass->myfd = socketdescriptor; + + no_error(error); + return remoteClass; +} + +bool SWInetSocket::bind(int port, SWBaseError *error) +{ + return bind(port, "", error); +} + +bool SWInetSocket::bind(int port, string host, SWBaseError *error) +{ + hostent *h; + in_addr inp; + + if( host.size() > 0 ){ + // Bind to a specific address + + if( (h = gethostbyname(host.c_str())) == NULL ){ + set_error(error, fatal, "SWInetSocket::bind() - Can't get host by name"); + return false; + } + + inp = *((in_addr *)h->h_addr); + }else{ + // Bind to any + inp.s_addr = INADDR_ANY; + } + + + get_socket(); + + sockaddr_in myAdr; + + memset(&myAdr, 0, sizeof(myAdr)); + myAdr.sin_family = AF_INET; + myAdr.sin_port = htons(port); + myAdr.sin_addr.s_addr = inp.s_addr; + + if(::bind(myfd, (sockaddr *)&myAdr, sizeof(myAdr)) == -1){ + handle_errno(error, "SWInetSocket::bind() error: "); + return false; + } + + no_error(error); + return true; +} + +bool SWInetSocket::connect(int port, string hostname, SWBaseError *error) +{ + get_socket(); + + hostent *host; + + if( (host = gethostbyname(hostname.c_str())) == NULL ){ + set_error(error, fatal, "SWInetSocket::connect() - Can't get host by name"); + return false; + } + + sockaddr_in remoteAdr; + + memset(&remoteAdr, 0, sizeof(remoteAdr)); + remoteAdr.sin_family = AF_INET; + remoteAdr.sin_port = htons(port); + remoteAdr.sin_addr = *((in_addr *)host->h_addr); + + if(::connect(myfd, (sockaddr *)&remoteAdr, sizeof(remoteAdr)) == -1){ + handle_errno(error, "SWInetSocket::connect() error: "); + return false; + } + + no_error(error); + return true; +} + + +string SWInetSocket::get_peerAddr(SWBaseError *error) +{ + sockaddr_in adr; + + if( !get_peer((sockaddr *)&adr, error) ) + return ""; + + char *pnt; + + if( (pnt = inet_ntoa(adr.sin_addr)) == NULL ){ + set_error(error, fatal, "SWInetSocket::get_peerName() - Can't get peer address"); + return ""; + } + string name(pnt); + + no_error(error); + return name; +} + +int SWInetSocket::get_peerPort(SWBaseError *error) +{ + sockaddr_in adr; + + if( !get_peer((sockaddr *)&adr, error) ) + return -1; + + no_error(error); + + return ntohs(adr.sin_port); +} + +string SWInetSocket::get_peerName(SWBaseError *error) +{ + string name = get_peerAddr(error); + if(name.size() < 1) + return ""; + + + hostent *h; + + if( (h = gethostbyname(name.c_str())) == NULL ){ + set_error(error, fatal, "SWInetSocket::get_peerName() - Can't get peer by address"); + return ""; + } + string host_name(h->h_name); + + no_error(error); + return host_name; +} + +string SWInetSocket::get_hostAddr(SWBaseError *error) +{ + //We need to get the real address, so we must + //first get this computers host name and then + //translate that into an address! + + string name = get_hostName(error); + if( name.size() < 1 ) + return ""; + + hostent *host; + + if( (host = gethostbyname(name.c_str())) == NULL ){ + set_error(error, fatal, "SWInetSocket::get_hostAddr() - Can't get host by name"); + return ""; + } + + char *pnt; + + if( (pnt = inet_ntoa(*((in_addr *)host->h_addr))) == NULL){ + set_error(error, fatal, "SWInetSocket::get_hostAddr() - Can't get host address"); + return ""; + } + + string adr(pnt); + + return adr; +} + +int SWInetSocket::get_hostPort(SWBaseError *error) +{ + sockaddr_in adr; + + if( !get_host((sockaddr *)&adr, error) ) + return -1; + + no_error(error); + + return ntohs(adr.sin_port); +} + +string SWInetSocket::get_hostName(SWBaseError *error) +{ + char buf[256]; + + if( gethostname(buf, 256) != 0 ){ + handle_errno(error, "SWInetSocket::gethostname() error: "); + return ""; + } + + string msg(buf); + + no_error(error); + return msg; +} diff --git a/Server/sockets/sw_inet.h b/Server/sockets/sw_inet.h new file mode 100644 index 00000000..26050845 --- /dev/null +++ b/Server/sockets/sw_inet.h @@ -0,0 +1,48 @@ +// C++ Socket Wrapper +// SocketW Inet socket header +// +// Started 020316 +// +// License: LGPL v2.1+ (see the file LICENSE) +// (c)2002-2003 Anders Lindström + +/*********************************************************************** + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + ***********************************************************************/ + +#ifndef sw_inet_H +#define sw_inet_H + +#include "sw_internal.h" +#include "sw_base.h" +#include + +// Simple streaming TCP/IP class +class DECLSPEC SWInetSocket : public SWBaseSocket +{ +public: + SWInetSocket(block_type block=blocking); + virtual ~SWInetSocket(); + + virtual bool bind(int port, SWBaseError *error = NULL); //use port=0 to get any free port + virtual bool bind(int port, std::string host, SWBaseError *error = NULL); //you can also specify the host interface to use + virtual bool connect(int port, std::string hostname, SWBaseError *error = NULL); + + // Tools + // Gets IP addr, name or port. + virtual std::string get_peerAddr(SWBaseError *error = NULL); + virtual int get_peerPort(SWBaseError *error = NULL); + virtual std::string get_peerName(SWBaseError *error = NULL); + virtual std::string get_hostAddr(SWBaseError *error = NULL); + virtual int get_hostPort(SWBaseError *error = NULL); + virtual std::string get_hostName(SWBaseError *error = NULL); + +protected: + virtual void get_socket(); + virtual SWBaseSocket* create(int socketdescriptor, SWBaseError *error); +}; + +#endif /* sw_inet_H */ diff --git a/Server/sockets/sw_internal.h b/Server/sockets/sw_internal.h new file mode 100644 index 00000000..94313bcd --- /dev/null +++ b/Server/sockets/sw_internal.h @@ -0,0 +1,75 @@ +// C++ Socket Wrapper +// SocketW internal header +// +// Started 030823 +// +// License: LGPL v2.1+ (see the file LICENSE) +// (c)2002-2003 Anders Lindstr�m + +/*********************************************************************** + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + ***********************************************************************/ + +#ifndef sw_internal_H +#define sw_internal_H + +// This header is included in all *.h files + +#ifndef __WIN32__ + #include + #include + #include + #include +#else + #include + + #define F_SETFL FIONBIO + #define O_NONBLOCK 1 +#endif + +#ifndef _SDL_H + +// Define general types +typedef unsigned char Uint8; +typedef signed char Sint8; +typedef unsigned short Uint16; +typedef signed short Sint16; +typedef unsigned int Uint32; +typedef signed int Sint32; + +// It's VERY important that these types really have the right sizes! +// This black magic is from SDL +#define COMPILE_TIME_ASSERT(name, x) \ + typedef int _dummy_ ## name[(x) * 2 - 1] +COMPILE_TIME_ASSERT(uint8, sizeof(Uint8) == 1); +COMPILE_TIME_ASSERT(sint8, sizeof(Sint8) == 1); +COMPILE_TIME_ASSERT(uint16, sizeof(Uint16) == 2); +COMPILE_TIME_ASSERT(sint16, sizeof(Sint16) == 2); +COMPILE_TIME_ASSERT(uint32, sizeof(Uint32) == 4); +COMPILE_TIME_ASSERT(sint32, sizeof(Sint32) == 4); +#undef COMPILE_TIME_ASSERT + +#endif /* _SDL_H */ + +// Some compilers use a special export keyword +#ifndef DECLSPEC + #ifdef __BEOS__ + #if defined(__GNUC__) + #define DECLSPEC __declspec(dllexport) + #else + #define DECLSPEC __declspec(export) + #endif + #else + #ifdef WIN32 + #define DECLSPEC __declspec(dllexport) + #else + #define DECLSPEC + #endif + #endif +#endif + + +#endif /* sw_internal_H */ diff --git a/Server/sockets/sw_unix.cpp b/Server/sockets/sw_unix.cpp new file mode 100644 index 00000000..07e2dd10 --- /dev/null +++ b/Server/sockets/sw_unix.cpp @@ -0,0 +1,99 @@ +// C++ Socket Wrapper +// SocketW Unix socket +// +// Started 020316 +// +// License: LGPL v2.1+ (see the file LICENSE) +// (c)2002-2003 Anders Lindström + +/*********************************************************************** + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + ***********************************************************************/ + +#include "sw_unix.h" +#include + +using namespace std; + +//==================================================================== +//== SWUnixSocket +//== Unix streaming sockets +//==================================================================== +#ifndef __WIN32__ + +SWUnixSocket::SWUnixSocket(block_type block) +{ + block_mode = block; +} + +SWUnixSocket::~SWUnixSocket() +{ + //nothing here +} + +void SWUnixSocket::get_socket() +{ + if( myfd < 0 ){ + myfd = socket(PF_UNIX, SOCK_STREAM, 0); + + if( block_mode == nonblocking ) + fcntl(myfd, F_SETFL, O_NONBLOCK); + + //reset state + reset(); + } +} + + +SWBaseSocket* SWUnixSocket::create(int socketdescriptor, SWBaseError *error) +{ + SWUnixSocket* remoteClass; + + /* Create new class*/ + remoteClass = new SWUnixSocket(block_mode); + remoteClass->myfd = socketdescriptor; + + no_error(error); + return remoteClass; +} + +bool SWUnixSocket::bind(string path, SWBaseError *error) +{ + get_socket(); + + sockaddr_un myAdr; + + myAdr.sun_family = AF_UNIX; + strncpy(myAdr.sun_path, path.c_str(), path.size()+1); + + if(::bind(myfd, (sockaddr *)&myAdr, sizeof(myAdr)) == -1){ + handle_errno(error, "SWUnixSocket::bind() error: "); + return false; + } + + no_error(error); + return true; +} + +bool SWUnixSocket::connect(string path, SWBaseError *error) +{ + get_socket(); + + sockaddr_un remoteAdr; + + remoteAdr.sun_family = AF_UNIX; + strncpy(remoteAdr.sun_path, path.c_str(), path.size()+1); + + if(::connect(myfd, (sockaddr *)&remoteAdr, sizeof(remoteAdr)) == -1){ + handle_errno(error, "SWUnixSocket::connect() error: "); + return false; + } + + no_error(error); + return true; +} + +#endif /* __WIN32__ */ diff --git a/Server/sockets/sw_unix.h b/Server/sockets/sw_unix.h new file mode 100644 index 00000000..576f14c0 --- /dev/null +++ b/Server/sockets/sw_unix.h @@ -0,0 +1,41 @@ +// C++ Socket Wrapper +// SocketW Unix socket header +// +// Started 020316 +// +// License: LGPL v2.1+ (see the file LICENSE) +// (c)2002-2003 Anders Lindström + +/*********************************************************************** + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + ***********************************************************************/ + +#ifndef sw_unix_H +#define sw_unix_H +#ifndef __WIN32__ + +#include "sw_internal.h" +#include "sw_base.h" +#include + +// Simple streaming Unix class +class DECLSPEC SWUnixSocket : public SWBaseSocket +{ +public: + SWUnixSocket(block_type block=blocking); + ~SWUnixSocket(); + + // bind and connect to the socket file "path" + virtual bool bind(std::string path, SWBaseError *error = NULL); + virtual bool connect(std::string path, SWBaseError *error = NULL); + +protected: + virtual void get_socket(); + virtual SWBaseSocket* create(int socketdescriptor, SWBaseError *error); +}; + +#endif /* __WIN32__ */ +#endif /* sw_unix_H */ diff --git a/blaat b/blaat deleted file mode 100644 index ed8d5eb7..00000000 --- a/blaat +++ /dev/null @@ -1 +0,0 @@ -Blaat