123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686 |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- #include "networking.hpp"
-
- Networking Network;
-
-
-
- #if defined(WIN32) || defined(WIN64)
-
-
-
-
- WSADATA WSSTartData;
-
-
-
- string Networking::DescriptiveError(string Msg, int Errno) {
- string s = "";
-
- switch(Errno) {
- case WSA_INVALID_HANDLE: s = "WSA_INVALID_HANDLE"; break;
- case WSA_NOT_ENOUGH_MEMORY: s = "WSA_NOT_ENOUGH_MEMORY"; break;
- case WSA_INVALID_PARAMETER: s = "WSA_INVALID_PARAMETER"; break;
- case WSA_OPERATION_ABORTED: s = "WSA_OPERATION_ABORTED"; break;
- case WSA_IO_INCOMPLETE: s = "WSA_IO_INCOMPLETE"; break;
- case WSA_IO_PENDING: s = "WSA_IO_PENDING"; break;
- case WSAEINTR: s = "WSAEINTR"; break;
- case WSAEBADF: s = "WSAEBADF"; break;
- case WSAEACCES: s = "WSAEACCES"; break;
- case WSAEFAULT: s = "WSAEFAULT"; break;
- case WSAEINVAL: s = "WSAEINVAL"; break;
- case WSAEMFILE: s = "WSAEMFILE"; break;
- case WSAEWOULDBLOCK: s = "WSAEWOULDBLOCK"; break;
- case WSAEINPROGRESS: s = "WSAEINPROGRESS"; break;
- case WSAEALREADY: s = "WSAEALREADY"; break;
- case WSAENOTSOCK: s = "WSAENOTSOCK"; break;
- case WSAEDESTADDRREQ: s = "WSAEDESTADDRREQ"; break;
- case WSAEMSGSIZE: s = "WSAEMSGSIZE"; break;
- case WSAEPROTOTYPE: s = "WSAEPROTOTYPE"; break;
- case WSAENOPROTOOPT: s = "WSAENOPROTOOPT"; break;
- case WSAEPROTONOSUPPORT: s = "WSAEPROTONOSUPPORT"; break;
- case WSAESOCKTNOSUPPORT: s = "WSAESOCKTNOSUPPORT"; break;
- case WSAEOPNOTSUPP: s = "WSAEOPNOTSUPP"; break;
- case WSAEPFNOSUPPORT: s = "WSAEPFNOSUPPORT"; break;
- case WSAEAFNOSUPPORT: s = "WSAEAFNOSUPPORT"; break;
- case WSAEADDRINUSE: s = "WSAEADDRINUSE"; break;
- case WSAEADDRNOTAVAIL: s = "WSAEADDRNOTAVAIL"; break;
- case WSAENETDOWN: s = "WSAENETDOWN"; break;
- case WSAENETUNREACH: s = "WSAENETUNREACH"; break;
- case WSAENETRESET: s = "WSAENETRESET"; break;
- case WSAECONNABORTED: s = "WSAECONNABORTED"; break;
- case WSAECONNRESET: s = "WSAECONNRESET"; break;
- case WSAENOBUFS: s = "WSAENOBUFS"; break;
- case WSAEISCONN: s = "WSAEISCONN"; break;
- case WSAENOTCONN: s = "WSAENOTCONN"; break;
- case WSAESHUTDOWN: s = "WSAESHUTDOWN"; break;
- case WSAETOOMANYREFS: s = "WSAETOOMANYREFS"; break;
- case WSAETIMEDOUT: s = "WSAETIMEDOUT"; break;
- case WSAECONNREFUSED: s = "WSAECONNREFUSED"; break;
- case WSAELOOP: s = "WSAELOOP"; break;
- case WSAENAMETOOLONG: s = "WSAENAMETOOLONG"; break;
- case WSAEHOSTDOWN: s = "WSAEHOSTDOWN"; break;
- case WSAEHOSTUNREACH: s = "WSAEHOSTUNREACH"; break;
- case WSAENOTEMPTY: s = "WSAENOTEMPTY"; break;
- case WSAEPROCLIM: s = "WSAEPROCLIM"; break;
- case WSAEUSERS: s = "WSAEUSERS"; break;
- case WSAEDQUOT: s = "WSAEDQUOT"; break;
- case WSAESTALE: s = "WSAESTALE"; break;
- case WSAEREMOTE: s = "WSAEREMOTE"; break;
- case WSASYSNOTREADY: s = "WSASYSNOTREADY"; break;
- case WSAVERNOTSUPPORTED: s = "WSAVERNOTSUPPORTED"; break;
- case WSANOTINITIALISED: s = "WSANOTINITIALISED"; break;
- case WSAEDISCON: s = "WSAEDISCON"; break;
- case WSAENOMORE: s = "WSAENOMORE"; break;
- case WSAECANCELLED: s = "WSAECANCELLED"; break;
- case WSAEINVALIDPROCTABLE: s = "WSAEINVALIDPROCTABLE"; break;
- case WSAEINVALIDPROVIDER: s = "WSAEINVALIDPROVIDER"; break;
- case WSAEPROVIDERFAILEDINIT: s = "WSAEPROVIDERFAILEDINIT"; break;
- case WSASYSCALLFAILURE: s = "WSASYSCALLFAILURE"; break;
- case WSASERVICE_NOT_FOUND: s = "WSASERVICE_NOT_FOUND"; break;
- case WSATYPE_NOT_FOUND: s = "WSATYPE_NOT_FOUND"; break;
- case WSA_E_NO_MORE: s = "WSA_E_NO_MORE"; break;
- case WSA_E_CANCELLED: s = "WSA_E_CANCELLED"; break;
- case WSAEREFUSED: s = "WSAEREFUSED"; break;
- case WSAHOST_NOT_FOUND: s = "WSAHOST_NOT_FOUND"; break;
- case WSATRY_AGAIN: s = "WSATRY_AGAIN"; break;
- case WSANO_RECOVERY: s = "WSANO_RECOVERY"; break;
- case WSANO_DATA: s = "WSANO_DATA"; break;
- case WSA_QOS_RECEIVERS: s = "WSA_QOS_RECEIVERS"; break;
- case WSA_QOS_SENDERS: s = "WSA_QOS_SENDERS"; break;
- case WSA_QOS_NO_SENDERS: s = "WSA_QOS_NO_SENDERS"; break;
- case WSA_QOS_NO_RECEIVERS: s = "WSA_QOS_NO_RECEIVERS"; break;
- case WSA_QOS_REQUEST_CONFIRMED: s = "WSA_QOS_REQUEST_CONFIRMED"; break;
- case WSA_QOS_ADMISSION_FAILURE: s = "WSA_QOS_ADMISSION_FAILURE"; break;
- case WSA_QOS_POLICY_FAILURE: s = "WSA_QOS_POLICY_FAILURE"; break;
- case WSA_QOS_BAD_STYLE: s = "WSA_QOS_BAD_STYLE"; break;
- case WSA_QOS_BAD_OBJECT: s = "WSA_QOS_BAD_OBJECT"; break;
- case WSA_QOS_TRAFFIC_CTRL_ERROR: s = "WSA_QOS_TRAFFIC_CTRL_ERROR"; break;
- case WSA_QOS_GENERIC_ERROR: s = "WSA_QOS_GENERIC_ERROR"; break;
- case WSA_QOS_ESERVICETYPE: s = "WSA_QOS_ESERVICETYPE"; break;
- case WSA_QOS_EFLOWSPEC: s = "WSA_QOS_EFLOWSPEC"; break;
- case WSA_QOS_EPROVSPECBUF: s = "WSA_QOS_EPROVSPECBUF"; break;
- case WSA_QOS_EFILTERSTYLE: s = "WSA_QOS_EFILTERSTYLE"; break;
- case WSA_QOS_EFILTERTYPE: s = "WSA_QOS_EFILTERTYPE"; break;
- case WSA_QOS_EFILTERCOUNT: s = "WSA_QOS_EFILTERCOUNT"; break;
- case WSA_QOS_EOBJLENGTH: s = "WSA_QOS_EOBJLENGTH"; break;
- case WSA_QOS_EFLOWCOUNT: s = "WSA_QOS_EFLOWCOUNT"; break;
- case WSA_QOS_EPOLICYOBJ: s = "WSA_QOS_EPOLICYOBJ"; break;
- case WSA_QOS_EFLOWDESC: s = "WSA_QOS_EFLOWDESC"; break;
- case WSA_QOS_EPSFLOWSPEC: s = "WSA_QOS_EPSFLOWSPEC"; break;
- case WSA_QOS_EPSFILTERSPEC: s = "WSA_QOS_EPSFILTERSPEC"; break;
- case WSA_QOS_ESDMODEOBJ: s = "WSA_QOS_ESDMODEOBJ"; break;
- case WSA_QOS_ESHAPERATEOBJ: s = "WSA_QOS_ESHAPERATEOBJ"; break;
- case WSA_QOS_RESERVED_PETYPE: s = "WSA_QOS_RESERVED_PETYPE"; break;
-
- #ifdef WSA_QOS_EUNKOWNPSOBJ
- case WSA_QOS_EUNKOWNPSOBJ: s = "WSA_QOS_EUNKOWNPSOBJ"; break;
- #endif
- }
-
- Msg.append(" ");
- if(0 < s.length()) {
- Msg.append(s);
- }
- else {
- ostringstream ErrNoMsg;
- ErrNoMsg << " UNKNOWN ErrorNumber = " << Errno;
- Msg.append(ErrNoMsg.str());
- }
- return Msg;
- };
-
-
-
-
- Networking::Networking() {
- if(0 != WSAStartup(MAKEWORD (2,0), &WSSTartData)) {
- throw InitializationError(
- "Networking::Networking() if(0 != WSAStartup(MAKEWORD (2,0), &WSSTartData))"
- );
- }
- }
-
-
-
-
- Networking::~Networking() {
- WSACleanup();
- }
-
-
-
-
- #else
-
-
-
-
-
-
- string Networking::DescriptiveError(string Msg, int Errno) {
- Msg.append(" "); Msg.append(strerror(Errno));
- return Msg;
- };
-
-
-
-
- Networking::Networking() {
-
- }
-
-
-
-
- Networking::~Networking() {
-
- }
-
-
-
-
- #endif
-
-
-
-
-
-
- const int LowestOctetMask = 0x000000FF;
- const int OneOctetInBits = 8;
-
- void splitIP(
- unsigned long A,
- int& a0,
- int& a1,
- int& a2,
- int& a3
- ){
- a3 = A & LowestOctetMask; A >>= OneOctetInBits;
- a2 = A & LowestOctetMask; A >>= OneOctetInBits;
- a1 = A & LowestOctetMask; A >>= OneOctetInBits;
- a0 = A & LowestOctetMask;
- }
-
-
-
- IP4Address::operator unsigned long int() const {
- return IP;
- }
-
- IP4Address::operator string() const {
- char stringbfr[IPStringBufferSize];
- memset(stringbfr, 0, sizeof(stringbfr));
- int a0, a1, a2, a3;
- splitIP(IP, a0, a1, a2, a3);
- sprintf(stringbfr, "%d.%d.%d.%d", a0, a1, a2, a3);
- return string(stringbfr);
- }
-
-
-
-
-
- const char* SocketAddress::getAddress(char* str) {
- if(NULL == str) {
- str = IPStringBuffer;
- }
- int a0, a1, a2, a3;
- getAddress(a0, a1, a2, a3);
- sprintf(str, "%d.%d.%d.%d", a0, a1, a2, a3);
- return str;
- }
-
-
-
- void SocketAddress::getAddress(int& a0, int& a1, int& a2, int& a3) {
- unsigned long A = getAddress();
- splitIP(A, a0, a1, a2, a3);
- }
-
-
-
- TCPListener::TCPListener(unsigned short Port) {
- LocalAddress.setPort(Port);
- LocalAddress.setAddress(LOCALHOST);
- MaxPending = DefaultMaxPending;
- ReuseAddress = true;
- OpenStage1Complete = false;
- OpenStage2Complete = false;
-
-
-
- LastError = 0;
-
- Handle = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
- if(INVALID_SOCKET == Handle) {
- LastError = Network.getLastError();
- throw Networking::SocketCreationError(
- Network.DescriptiveError(
- "TCPListener::TCPListener().socket()", LastError));
- }
- }
-
- TCPListener::TCPListener(SocketAddress& WhereToBind) {
- LocalAddress = WhereToBind;
- MaxPending = DefaultMaxPending;
- ReuseAddress = true;
- OpenStage1Complete = false;
- OpenStage2Complete = false;
-
-
-
- LastError = 0;
-
- Handle = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
- if(INVALID_SOCKET == Handle) {
- LastError = Network.getLastError();
- throw Networking::SocketCreationError(
- Network.DescriptiveError(
- "TCPListener::TCPListener().socket()", LastError));
- }
- }
-
-
-
- void TCPListener::open() {
-
- if(OpenSucceeded) return;
-
- LastError = 0;
- bool SuccessFlag = true;
-
-
-
- if(!OpenStage1Complete) {
- int ReuseAddress_Flag = (ReuseAddress? 1:0);
- int result =
- setsockopt(
- Handle,
- SOL_SOCKET,
- SO_REUSEADDR,
- (char*) &ReuseAddress_Flag,
- sizeof(ReuseAddress_Flag));
-
- if(0 > result) {
- SuccessFlag = false;
- LastError = Network.getLastError();
- throw Networking::SocketSetSockOptError(
- Network.DescriptiveError(
- "TCPListener::open().setsockopt(SO_REUSEADDR)", LastError));
- }
- OpenStage1Complete = true;
- }
-
-
-
- if(!OpenStage2Complete) {
- int result =
- bind(
- Handle,
- LocalAddress.getPtr_sockaddr(),
- LocalAddress.getAddressSize());
-
- if(0 > result) {
- SuccessFlag = false;
- LastError = Network.getLastError();
- throw Networking::SocketBindError(
- Network.DescriptiveError(
- "TCPListener::open().bind()", LastError));
- }
- OpenStage2Complete = true;
- }
-
-
-
- int result = listen(Handle, MaxPending);
-
- if(0 > result) {
- SuccessFlag = false;
- LastError = Network.getLastError();
- throw Networking::SocketListenError(
- Network.DescriptiveError(
- "TCPListener::open().listen()", LastError));
- }
-
- OpenSucceeded = SuccessFlag;
- }
-
-
-
- TCPClient* TCPListener::acceptClient() {
-
- LastError = 0;
- socklen_t rsize = RemoteAddress.getAddressSize();
-
- hSocket NewHandle =
- accept(
- Handle,
- RemoteAddress.getPtr_sockaddr(),
- &rsize);
-
- if(INVALID_SOCKET == NewHandle) {
- LastError = Network.getLastError();
- if(!Network.WouldBlock(LastError)) {
- throw Networking::SocketAcceptError(
- Network.DescriptiveError(
- "TCPListener::acceptClient().accept()", LastError));
- } else {
- return NULL;
- }
- }
-
-
-
- if(
- 0 != SO_NOSIGPIPE &&
- 0 == MSG_NOSIGNAL
- ) {
- int TurnedOn = 1;
- int result =
- setsockopt(
- NewHandle,
- SOL_SOCKET,
- SO_NOSIGPIPE,
- (char*) &TurnedOn,
- sizeof(TurnedOn));
-
- if(0 > result) {
- LastError = Network.getLastError();
- Network.closeSocket(NewHandle);
- throw Networking::SocketSetSockOptError(
- Network.DescriptiveError(
- "TCPListener::acceptClient().setsockopt(SO_NOSIGPIPE)", LastError));
- }
- }
-
-
-
- return new TCPClient(*this, NewHandle, RemoteAddress);
-
- }
-
-
-
- int TCPClient::transmit(const char* bfr, int size) {
- if(0 == size) return 0;
- if(0 == bfr)
- throw Networking::SocketWriteError("TCPClient::transmit() NULL Bfr!");
- if(0 > size)
- throw Networking::SocketWriteError("TCPClient::transmit() 0 > size!");
-
- LastError = 0;
- int ByteCount = 0;
- ByteCount = send(Handle, bfr, size, MSG_NOSIGNAL);
- LastError = Network.getLastError();
-
- bool AnErrorOccurred = (0 > ByteCount);
- const int NoBytesSent = 0;
-
- if(AnErrorOccurred) {
- if(Network.WouldBlock(LastError)) {
- return NoBytesSent;
- } else {
- throw Networking::SocketWriteError(
- Network.DescriptiveError(
- "TCPClient::transmit().send()", LastError));
- }
- }
-
- return ByteCount;
- }
-
- int TCPClient::receive(char* bfr, int size) {
- if(ReadBufferIsEmpty()) {
- fillReadBuffer();
- }
- if(DataLength < size) {
- size = DataLength;
- }
- int RemainingDataLength = size;
- while(0 < RemainingDataLength) {
- *bfr = *ReadPointer;
- bfr++; ReadPointer++;
- DataLength--;
- RemainingDataLength--;
- }
- return size;
- }
-
- int TCPClient::delimited_receive(char* bfr, int size, char delimiter) {
- if(ReadBufferIsEmpty()) {
- fillReadBuffer();
- }
- if(DataLength < size) {
- size = DataLength;
- }
- int Count = 0;
- bool DelimiterNotReached = true;
- while((Count < size) && DelimiterNotReached) {
- *bfr = *ReadPointer;
- DelimiterNotReached = (delimiter != (*bfr));
- bfr++; ReadPointer++;
- DataLength--;
- Count++;
- }
- return Count;
- }
-
-
-
-
-
- TCPHost::TCPHost(unsigned short Port) {
- RemoteAddress.setPort(Port);
- RemoteAddress.setAddress(LOCALHOST);
- ReadPointer = ReadBuffer;
- DataLength = 0;
- ReuseAddress = false;
- OpenStage1Complete = false;
-
-
-
- LastError = 0;
-
- Handle = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
- if(0 > Handle) {
- LastError = Network.getLastError();
- throw Networking::SocketCreationError(
- Network.DescriptiveError(
- "TCPHost::TCPHost().socket()", LastError));
- }
- }
-
- TCPHost::TCPHost(SocketAddress& Remote) {
- RemoteAddress = Remote;
- ReadPointer = ReadBuffer;
- DataLength = 0;
- ReuseAddress = false;
- OpenStage1Complete = false;
-
-
-
- LastError = 0;
-
- Handle = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
- if(0 > Handle) {
- LastError = Network.getLastError();
- throw Networking::SocketCreationError(
- Network.DescriptiveError(
- "TCPHost::TCPHost().socket()", LastError));
- }
- }
-
-
-
- void TCPHost::open() {
-
- if(OpenSucceeded) return;
-
- LastError = 0;
- bool SuccessFlag = true;
-
-
-
- if(!OpenStage1Complete) {
-
-
-
- int ReuseAddress_Flag = (ReuseAddress? 1:0);
- int result =
- setsockopt(
- Handle,
- SOL_SOCKET,
- SO_REUSEADDR,
- (char*) &ReuseAddress_Flag,
- sizeof(ReuseAddress_Flag));
-
- if(0 > result) {
- SuccessFlag = false;
- LastError = Network.getLastError();
- throw Networking::SocketSetSockOptError(
- Network.DescriptiveError(
- "TCPHost::open().setsockopt(SO_REUSEADDR)", LastError));
- }
-
-
-
- if(
- 0 != SO_NOSIGPIPE &&
- 0 == MSG_NOSIGNAL
- ) {
- int TurnedOn = 1;
- int result =
- setsockopt(
- Handle,
- SOL_SOCKET,
- SO_NOSIGPIPE,
- (char*) &TurnedOn,
- sizeof(TurnedOn));
-
- if(0 > result) {
- SuccessFlag = false;
- LastError = Network.getLastError();
- throw Networking::SocketSetSockOptError(
- Network.DescriptiveError(
- "TCPHost::open().setsockopt(SO_NOSIGPIPE)", LastError));
- }
- }
-
- OpenStage1Complete = true;
- }
-
-
-
- int result =
- connect(
- Handle,
- RemoteAddress.getPtr_sockaddr(),
- RemoteAddress.getAddressSize());
-
- if(0 > result) {
- SuccessFlag = false;
- LastError = Network.getLastError();
- if(Network.IsConnected(LastError)) {
- SuccessFlag = true;
- } else
- if(
- !Network.WouldBlock(LastError) &&
- !Network.InProgress(LastError)
- ) {
- throw Networking::SocketConnectError(
- Network.DescriptiveError(
- "TCPHost::open().connect()", LastError));
- }
- }
-
- OpenSucceeded = SuccessFlag;
- }
-
- int TCPHost::transmit(const char* bfr, int size) {
- LastError = 0;
- if(0 == size) return 0;
- if(0 == bfr)
- throw Networking::SocketWriteError("TCPHost::transmit() NULL Bfr!");
- if(0 > size)
- throw Networking::SocketWriteError("TCPHost::transmit() 0 > size!");
-
- int ByteCount = send(Handle, bfr, size, MSG_NOSIGNAL);
- if(0 > ByteCount) ByteCount = 0;
-
- if(size > ByteCount) {
- LastError = Network.getLastError();
- if(Network.WouldBlock(LastError)) {
- return ByteCount;
- } else {
- throw Networking::SocketWriteError(
- Network.DescriptiveError(
- "TCPHost::transmit().send()", LastError));
- }
- }
- return ByteCount;
- }
-
- int TCPHost::receive(char* bfr, int size) {
- if(ReadBufferIsEmpty()) {
- fillReadBuffer();
- }
- if(DataLength < size) {
- size = DataLength;
- }
- int RemainingDataLength = size;
- while(0 < RemainingDataLength) {
- *bfr = *ReadPointer;
- bfr++; ReadPointer++;
- DataLength--;
- RemainingDataLength--;
- }
- return size;
- }
-
- int TCPHost::delimited_receive(char* bfr, int size, char delimiter) {
- if(ReadBufferIsEmpty()) {
- fillReadBuffer();
- }
- if(DataLength < size) {
- size = DataLength;
- }
- int Count = 0;
- bool DelimiterNotReached = true;
- while((Count < size) && DelimiterNotReached) {
- *bfr = *ReadPointer;
- DelimiterNotReached = (delimiter != (*bfr));
- bfr++; ReadPointer++;
- DataLength--;
- Count++;
- }
- return Count;
- }
-
-
-
|