diff --git a/stepmania/src/ezsockets.cpp b/stepmania/src/ezsockets.cpp index 31a5145a2b..d84d623f67 100644 --- a/stepmania/src/ezsockets.cpp +++ b/stepmania/src/ezsockets.cpp @@ -1,458 +1,405 @@ -/******************************************* - ezsockets.cpp -- Header for sockets.cpp - Designed by Josh Allen and Charles - Lohr. Socket programming methods based - on Charles Lohr's EZW progam. - - Modified by Charles Lohr for use with - Windows-Based OSes. -********************************************/ - -// StepMania only includes -#include "global.h" +/*******************************************************************\ +| ezsockets.cpp: EzSockets Class Source | +| Designed by Josh Allen, Charles Lohr and Adam Lowman. | +| Socket programming methods based on Charles Lohr's EZW progam. | +| Modified by Charles Lohr for use with Windows-Based OSes. | +| UDP/NON-TCP Support by Adam Lowman. | +\*******************************************************************/ #include "ezsockets.h" -// We need the WinSock32 Library on Windows +#include "global.h" // StepMania only includes + #if defined(_XBOX) -#elif defined(_WINDOWS) -#pragma comment(lib,"wsock32.lib") +#elif defined(_WINDOWS) // We need the WinSock32 Library on Windows + #pragma comment(lib,"wsock32.lib") #else -#include -#include -#include -#include + #include + #include + #include + #include #endif -EzSockets::EzSockets() -{ - MAXCON = 5; - memset ( &addr, 0, sizeof(addr) ); //Clear the sockaddr_in structure +EzSockets::EzSockets() { + MAXCON = 5; + memset (&addr,0,sizeof(addr)); //Clear the sockaddr_in structure - // Windows REQUIRES WinSock Startup -#if defined(_WINDOWS) || defined(_XBOX) - WSAStartup( MAKEWORD(1,1), &wsda ); + #if defined(_WINDOWS) || defined(_XBOX) // Windows REQUIRES WinSock Startup + WSAStartup( MAKEWORD(1,1), &wsda ); + #endif + + sock = -1; + blocking = true; + scks = new fd_set; + times = new timeval; + times->tv_sec = 0; + times->tv_usec = 0; + state = skDISCONNECTED; +} + +EzSockets::~EzSockets() { + close(); + delete scks; + delete times; +} + +//Check to see if the socket has been created +bool EzSockets::check() { + return(sock>0); +} + +bool EzSockets::create() { + return create(IPPROTO_TCP, SOCK_STREAM); +} + +bool EzSockets::create(int Protocol) { + switch(Protocol) { + case IPPROTO_TCP: + return create(IPPROTO_TCP, SOCK_STREAM); + case IPPROTO_UDP: + return create(IPPROTO_UDP, SOCK_DGRAM); + default: + return create(Protocol, SOCK_RAW); + } +} + +bool EzSockets::create(int Protocol, int Type) { + state = skDISCONNECTED; + sock = socket(AF_INET, Type, Protocol); + return(sock>0); +} + + +bool EzSockets::bind(unsigned short port) { + if(!check()) + return false; + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = htons(port); + + return(::bind(sock,(struct sockaddr*)&addr, sizeof(addr))>0); +} + +bool EzSockets::listen() { + if(::listen(sock,MAXCON)<=0) + return false; + + state = skLISTENING; + return true; +} + +/************************************************************************\ +| To whomever edited this: | +| Please do not assume LINUX is defined if you're compiling on Linux! | +| It will not compile properly. | +\************************************************************************/ +#if defined(WIN32) || defined(DARWIN) // glibc already has socklen_t defined + typedef int socklen_t; #endif - sock = -1; - blocking=true; +bool EzSockets::accept(EzSockets &socket) { + int length = sizeof(socket); + socket.sock = ::accept(sock,(struct sockaddr*) &socket.addr,(socklen_t*) &length); - scks = new fd_set; - times = new timeval; - - - times->tv_sec = 0; - times->tv_usec = 0; - - state = skDISCONNECTED; -} - -EzSockets::~EzSockets() -{ - close(); - delete scks; - delete times; -} - -bool EzSockets::check() -{ - //Check to see if the socket has been created - if ( sock < 0 ) - return false; - return true; -} - -int EzSockets::create() -{ - state = skDISCONNECTED; - sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); - return (true); -} - -bool EzSockets::bind( unsigned short port ) -{ - if ( !check() ) - return false; - - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl( INADDR_ANY ); - addr.sin_port = htons( port ); - - int desc = ::bind( sock, (struct sockaddr *)&addr, sizeof(addr) ); - if ( desc < 0 ) - return false; - return true; -} - -bool EzSockets::listen() -{ - int desc = ::listen( sock, MAXCON ); - - if ( desc < 0 ) - return false; - - state = skLISTENING; - return true; -} - -// glibc already has socklen_t defined -// to whoever edited this: -// please do not assume LINUX is defined if you're compiling on linux! -// it will not compile properly. -#if defined(WIN32) || defined(DARWIN) - typedef int socklen_t; -#endif - -bool EzSockets::accept( EzSockets &socket ) -{ - // Windows wants it defined as a signed int - // As does everything else -- Steve - int length = sizeof( socket ); - - socket.sock = ::accept( sock, (struct sockaddr *)&socket.addr,(socklen_t *)&length ); - socket.state = skCONNECTED; - if ( socket.sock < 0 ) - return false; - - return true; + if(socket.sock<=0) + return false; + + socket.state = skCONNECTED; + return true; } void EzSockets::close() { - state = skDISCONNECTED; - inBuffer = ""; - outBuffer = ""; - // The close socket command is different in Windows -#if defined(WIN32) - ::closesocket( sock ); -#else - ::close( sock ); -#endif + state = skDISCONNECTED; + inBuffer = ""; + outBuffer = ""; + + #if defined(WIN32) // The close socket command is different in Windows + ::closesocket(sock); + #else + ::close(sock); + #endif } -long EzSockets::uAddr() -{ - return addr.sin_addr.s_addr; +long EzSockets::uAddr() { + return addr.sin_addr.s_addr; } -bool EzSockets::connect( const std::string& host, unsigned short port ) -{ - if (! check() ) - return false; +bool EzSockets::connect(const std::string& host,unsigned short port) { + if(!check()) + return false; -#if defined(_XBOX) + #if defined(_XBOX) // FIXME: Xbox doesn't have gethostbyname or any way to get a hostent. // Investigate the samples and figure out how this is supposed to work. return false; -#elif defined(_WINDOWS) + #elif defined(_WINDOWS) struct hostent* phe; + phe = gethostbyname(host.c_str()); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = (unsigned long) *((LPIN_ADDR*)phe->h_addr_list); + addr.sin_port = htons(port); + #else + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + inet_pton(AF_INET,host.c_str(),&addr.sin_addr); + #endif - addr.sin_family = AF_INET; - addr.sin_port = htons( port ); - phe = gethostbyname( host.c_str() ); - addr.sin_addr = *( (LPIN_ADDR)*phe->h_addr_list ); + if(::connect(sock,(struct sockaddr*)&addr,sizeof(addr))<=0) + return false; - int desc = ::connect( sock, (struct sockaddr *)&addr, sizeof(addr) ); - if (!desc) - state = skCONNECTED; - return !desc; -#else - addr.sin_family = AF_INET; - addr.sin_port = htons( port ); - inet_pton( AF_INET, host.c_str(), &addr.sin_addr ); + state = skCONNECTED; + return true; +} - int desc = ::connect( sock, (struct sockaddr *)&addr, sizeof(addr) ); - if (!desc) - state = skCONNECTED; - return !desc; -#endif +bool EzSockets::CanRead() { + FD_ZERO(scks); + FD_SET((unsigned)sock,scks); + + return(select(sock+1,scks,NULL,NULL,times)>0); +} + +bool EzSockets::IsError() { + if(state == skERROR) + return true; + + FD_ZERO(scks); + FD_SET((unsigned)sock,scks); + + return(select(sock+1,NULL,NULL,scks,times)<=0); +} + +bool EzSockets::CanWrite() { + FD_ZERO(scks); + FD_SET((unsigned)sock,scks); + + return(select(sock+1,NULL,scks,NULL,times)>0); +} + +void EzSockets::update() { + if(state == skERROR) //If socket is in error, don't bother. + return; + + if(IsError()) { + state=skERROR; + return; + } + + while(CanRead() && !IsError()) //Check for Reading + if(pUpdateRead()<1) + break; + + if (CanWrite() && (outBuffer.length()>0)) + pUpdateWrite(); } - -bool EzSockets::CanRead() -{ - FD_ZERO(scks); - FD_SET((unsigned)sock,scks); - - return select(sock+1, scks, NULL, NULL, times) > 0; +/*********************\ +| Raw Data System | +\*********************/ +void EzSockets::SendData(string &outData) { + outBuffer.append(outData); + if(blocking) + while ((outBuffer.length()>0) && !IsError()) + pUpdateWrite(); + else + update(); } -bool EzSockets::IsError() -{ - if (state == skERROR) - return true; - - FD_ZERO(scks); - FD_SET((unsigned)sock,scks); - - /* What is this trying to do? Errors are returned by read/write functions, not via - * the select() exception field. */ - return !!select(sock+1, NULL, NULL, scks, times); -} -bool EzSockets::CanWrite() -{ - FD_ZERO(scks); - FD_SET((unsigned)sock,scks); - - return select(0, NULL, scks, NULL, times) > 0; +void EzSockets::SendData(const char* data,unsigned int bytes) { + outBuffer.append(data,bytes); + if(blocking) + while ((outBuffer.length()>0) && !IsError()) + pUpdateWrite(); + else + update(); } -void EzSockets::update() -{ - if (state==skERROR) - return; - //If socket is in error, don't bother. +int EzSockets::ReadData(char* data,unsigned int bytes) { + int bytesRead = PeekData(data,bytes); + inBuffer = inBuffer.substr(bytesRead); + return bytesRead; +} - if (IsError()) - { - state=skERROR; - return; - } - - //Check for reading +int EzSockets::PeekData(char* data,unsigned int bytes) { + if(blocking) + while ((inBuffer.length()0)) - pUpdateWrite(); + if (pUpdateRead()<1) + break; + + int bytesRead = bytes; + if(inBuffer.length()0) && !IsError()) - pUpdateWrite(); - else - update(); - +/**********************************\ +| Packet/Structure Data System | +\**********************************/ +void EzSockets::SendPack(char* data,unsigned int bytes) { + unsigned int SendSize = htonl(bytes); + SendData((char*)&SendSize,sizeof(int)); + SendData(data,bytes); } -void EzSockets::SendData(const char *data, unsigned int bytes) -{ - outBuffer.append(data,bytes); - if (blocking) - while ((outBuffer.length()>0) && !IsError()) - pUpdateWrite(); - else - update(); +int EzSockets::ReadPack(char* data,unsigned int max) { + int size = PeekPack(data,max); + if(size!=-1) + inBuffer=inBuffer.substr(size+4); + + return size; } -int EzSockets::ReadData(char *data, unsigned int bytes) -{ - int bytesRead = PeekData(data,bytes); +int EzSockets::PeekPack(char* data,unsigned int max) { + if(CanRead()) + pUpdateRead(); - inBuffer = inBuffer.substr(bytesRead); + if(blocking) { + while((inBuffer.length()<4)&& !IsError()) + pUpdateRead(); - return bytesRead; + if(IsError()) + return -1; + } + + unsigned int size=0; + PeekData((char*)&size,4); + size=ntohl(size); + + if(blocking) + while ((inBuffer.length()<(size+4)) && !IsError()) + pUpdateRead(); + else if(inBuffer.length()>3) + if((inBuffer.length()<(size+4)) || (inBuffer.length()<=4)) + return -1; + + string tBuff(inBuffer.substr(4,size)); + if(tBuff.length()>max) + tBuff.substr(0,max); + memcpy (data,tBuff.c_str(),tBuff.length()); + return size; } -int EzSockets::PeekData(char *data, unsigned int bytes) -{ - if (blocking) - while ((inBuffer.length()=0) + inBuffer = inBuffer.substr(t+1); + return t; } -int EzSockets::ReadPack(char * data, unsigned int max) -{ - int size = PeekPack(data,max); - if (size!=-1) - inBuffer = inBuffer.substr(size+4); - return size; -} - -int EzSockets::PeekPack(char * data, unsigned int max) -{ - if (CanRead()) - pUpdateRead(); - - if (blocking) - { - while ((inBuffer.length()<4)&& !IsError()) - pUpdateRead(); - - if (IsError()) - return (-1); - -// LOG->Info("TTY:%d",inBuffer.length() - unsigned int size=0; - PeekData((char*)&size,4); - size = ntohl(size); -// LOG->Info("TXA:%d",size); - while ((inBuffer.length()<(size+4)) && !IsError()) - pUpdateRead(); - - string tBuff(inBuffer.substr(4,size)); - - if (tBuff.length()>max) - tBuff.substr(0,max); - - memcpy (data,tBuff.c_str(),tBuff.length()); - - return (size); - } - else if (inBuffer.length()>3) - { - unsigned int size=0; - PeekData((char*)&size,4); - size = ntohl(size); - if ((inBuffer.length()<(size+4)) || (inBuffer.length()<=4)) - return -1; - - string tBuff(inBuffer.substr(4,size)); - - if (tBuff.length()>max) - tBuff.substr(0,max); - - memcpy (data,tBuff.c_str(),tBuff.length()); - - return size; +int EzSockets::PeekStr(string& data, char delim) { + int t = inBuffer.find(delim,0); + if(blocking) { + while ((t==-1) && !IsError()) { + pUpdateRead(); + t = inBuffer.find(delim,0); } - return -1; + data = inBuffer.substr(0,t); + } + + if(t>=0) + data = inBuffer.substr(0,t); + return t; } -//String (Flash) system / Null-terminated strings -void EzSockets::SendStr(string & data, char delim) -{ - char tDr[1]; - tDr[0] = delim; - SendData(data.c_str(),data.length()); - SendData(tDr,1); +/************************\ +| Stream Data System | +\************************/ +istream& operator >>(istream &is,EzSockets &obj) { + string writeString; + obj.SendStr(writeString); + is >> writeString; + return is; } -int EzSockets::ReadStr(string & data, char delim) -{ - int t = PeekStr (data, delim); - if (t!=-1) - inBuffer = inBuffer.substr(t+1); - return t; -} -int EzSockets::PeekStr(string & data, char delim) -{ - int t; - t = inBuffer.find(delim,0); - if (blocking) - { - while ((t==-1) && !IsError()) - { - pUpdateRead(); - t = inBuffer.find(delim,0); - } - data = inBuffer.substr(0,t); - } - else - { - if (t == -1) - return -1; - data = inBuffer.substr(0,t); - } - return t; +ostream& operator <<(ostream &os, EzSockets &obj) { + string readString; + obj.ReadStr(readString); + os << readString; + return os; } +/**************************\ +| Internal Data System | +\**************************/ +int EzSockets::pUpdateRead() { + char tempData[1024]; + int bytes = pReadData(tempData); - -int EzSockets::pUpdateRead() -{ - char tempData[1024]; - int bytes = pReadData(tempData); - if (bytes>0) - inBuffer.append(tempData,bytes); - - //You cannot read - bytes! - //0 bytes may happen under non-blocking circuimstances - if (bytes<0) - state = skERROR; - - return bytes; + if(bytes>0) + inBuffer.append(tempData,bytes); + else + state = skERROR; + return bytes; } -int EzSockets::pUpdateWrite() -{ - int bytes = pWriteData(outBuffer.c_str(),outBuffer.length()); - if (bytes>0) - outBuffer = outBuffer.substr(bytes); - if (bytes<0) - state = skERROR; - return bytes; +int EzSockets::pUpdateWrite() { + int bytes = pWriteData(outBuffer.c_str(),outBuffer.length()); + + if (bytes>0) + outBuffer = outBuffer.substr(bytes); + else + state = skERROR; + return bytes; } -int EzSockets::pReadData(char * data) -{ - return recv( sock, data,1024, 0 ); +int EzSockets::pReadData(char* data) { + if((state == skCONNECTED)||(state == skLISTENING)) + return recv(sock,data,1024,0); + else { + fromAddr_len = sizeof(SOCKADDR_IN); + return recvfrom(sock,data,1024,0,(SOCKADDR*)&fromAddr,(int*)&fromAddr_len); + } } -int EzSockets::pWriteData(const char * data, int dataSize) -{ - return send( sock, data, dataSize, 0 ); +int EzSockets::pWriteData(const char* data,int dataSize) { + return send(sock,data,dataSize,0); } -istream& operator >>(istream &is,EzSockets &obj) -{ - string writeString; - obj.SendStr(writeString); - is>>writeString; - return is; -} -ostream& operator <<(ostream &os, EzSockets &obj) -{ - string readString; - obj.ReadStr(readString); - os<