diff --git a/stepmania/src/NetworkSyncManager.cpp b/stepmania/src/NetworkSyncManager.cpp index 9d6ec18a62..86617db5b6 100644 --- a/stepmania/src/NetworkSyncManager.cpp +++ b/stepmania/src/NetworkSyncManager.cpp @@ -34,9 +34,6 @@ #include "Steps.h" -#define NEXT_SCREEN THEME->GetMetric ("ScreenSelectMusic","NextScreen") - //Used for advancing to gameplay screen - NetworkSyncManager::NetworkSyncManager() { NetPlayerClient = new EzSockets; @@ -91,11 +88,14 @@ void NetworkSyncManager::PostStartUp(CString ServerIP) useSMserver = true; m_startupStatus = 1; //Connection attepmpt sucessful - + LOG->Info("CNConnected!"); int ClientCommand=3; - NetPlayerClient->send((char*) &ClientCommand, 4); + NetPlayerClient->SendPack((char*) &ClientCommand, 4); + LOG->Info("CNCHECKPOINT"); + + NetPlayerClient->ReadData((char*)&m_ServerVersion,4); + LOG->Info("CNCHECKPOINT:%d",NetPlayerClient->inBuffer.length()); - NetPlayerClient->receive(m_ServerVersion); // If network play is desired and the connection works, // halt until we know what server version we're dealing with vector ProfileNames; @@ -109,7 +109,7 @@ void NetworkSyncManager::PostStartUp(CString ServerIP) for( i=0; i < strlen(ProfileNames[0]); i++ ) PlayerName.m_data[i] = ProfileNames[0][i]; PlayerName.m_data[i] = 0; - NetPlayerClient->send((char*) &PlayerName,20); + NetPlayerClient->SendPack((char*) &PlayerName,20); } if( ProfileNames.size() > 1 ) { @@ -118,7 +118,7 @@ void NetworkSyncManager::PostStartUp(CString ServerIP) for( i=0; i < strlen(ProfileNames[1]); i++ ) PlayerName.m_data[i] = ProfileNames[1][i]; PlayerName.m_data[i] = 0; - NetPlayerClient->send( (char*) &PlayerName,20 ); + NetPlayerClient->SendPack( (char*) &PlayerName,20 ); } LOG->Info("Server Version: %d",m_ServerVersion); @@ -150,12 +150,6 @@ bool NetworkSyncManager::Connect(const CString& addy, unsigned short port) //It is this way now for protocol's purpose. //If there is a new protocol developed down the road - //Since under non-lan conditions, the client - //will be connecting to localhost, this port does not matter. - /* What do you mean it doesn't matter if you are connecting to localhost? - * Also, when does it ever connect to localhost? - * -- Steve - */ NetPlayerClient->create(); // Initilize Socket useSMserver = NetPlayerClient->connect(addy, port); @@ -215,7 +209,7 @@ void NetworkSyncManager::ReportScore(int playerID, int step, int score, int comb SendNetPack.m_life=m_playerLife[playerID] + CurGrade*65536; //Send packet to server - NetPlayerClient->send((char*)&SendNetPack, sizeof(netHolder)); + NetPlayerClient->SendPack((char*)&SendNetPack, sizeof(netHolder)); } @@ -236,7 +230,7 @@ void NetworkSyncManager::ReportSongOver() SendNetPack.m_life=0; - NetPlayerClient->send((char*)&SendNetPack, sizeof(netHolder)); + NetPlayerClient->SendPack((char*)&SendNetPack, sizeof(netHolder)); return; } @@ -251,7 +245,7 @@ void NetworkSyncManager::StartRequest() return ; - vector tmp; //Temporary vector used by receive function when waiting + char tmp[4]; //Temporary vector used by receive function when waiting LOG->Trace("Requesting Start from Server."); @@ -278,12 +272,12 @@ void NetworkSyncManager::StartRequest() SendNetPack.m_life=0; SendNetPack.m_combo=0; - NetPlayerClient->send((char*)&SendNetPack, sizeof(netHolder)); + NetPlayerClient->SendPack((char*)&SendNetPack, sizeof(netHolder)); LOG->Trace("Waiting for RECV"); //Block until go is recieved. - NetPlayerClient->receive(tmp); + NetPlayerClient->ReadData((char *)tmp, 4); LOG->Trace("Starting Game."); } @@ -322,10 +316,10 @@ void NetworkSyncManager::SendSongs() toSend[2]=char(0); toSend[3]=char(0); - NetPlayerClient->send (toSend,SongInfo.length()+4); + NetPlayerClient->SendPack (toSend,SongInfo.length()+4); } toSend[0]=char(36); - NetPlayerClient->send (toSend,4); + NetPlayerClient->SendPack (toSend,4); //Exit because this is ONLY for use with SMOnline //If admins feel strongly, this can be exported @@ -358,6 +352,10 @@ void NetworkSyncManager::DisplayStartupStatus() SCREENMAN->SystemMessage(sMessage); } +void NetworkSyncManager::Update(float fDeltaTime) +{ + +} //Global and accessable from anywhere NetworkSyncManager *NSMAN; diff --git a/stepmania/src/NetworkSyncManager.h b/stepmania/src/NetworkSyncManager.h index 0d5599894b..b275ba9554 100644 --- a/stepmania/src/NetworkSyncManager.h +++ b/stepmania/src/NetworkSyncManager.h @@ -15,9 +15,6 @@ #include "PlayerNumber.h" -void NSSendSongs(); -void ArgStartCourse(CString CourseName); - class EzSockets; class NetworkSyncManager @@ -34,12 +31,16 @@ public: void SendSongs(); //Send song list to server (And exit) void PostStartUp(CString ServerIP); + void CloseConnection(); void DisplayStartupStatus(); //Used to note user if connect attempt was sucessful or not. int m_playerLife[NUM_PLAYERS]; //Life + + void Update(float fDeltaTime); + private: void StartUp(); diff --git a/stepmania/src/ezsockets.cpp b/stepmania/src/ezsockets.cpp index d78d7a1e28..fc41879e02 100644 --- a/stepmania/src/ezsockets.cpp +++ b/stepmania/src/ezsockets.cpp @@ -1,6 +1,3 @@ -//#include "global.h" -//Commented out because there is no StepMania here. - /******************************************* ezsockets.cpp -- Header for sockets.cpp Designed by Josh Allen and Charles @@ -16,15 +13,17 @@ ********************************************/ // We need the WinSock32 Library on Windows + +#include +#include "ezsockets.h" + +#include + +using namespace std; #if defined(WIN32) #pragma comment(lib,"wsock32.lib") #endif -#include //REMOVE SOON - - -#include "ezsockets.h" - EzSockets::EzSockets() { MAXCON = 5; @@ -36,6 +35,17 @@ EzSockets::EzSockets() #endif sock = -1; + blocking=true; + + + scks = new fd_set; + times = new timeval; + + + times->tv_sec = 0; + times->tv_usec = 0; + + state = skDISCONNECTED; } EzSockets::~EzSockets() @@ -53,6 +63,7 @@ bool EzSockets::check() int EzSockets::create() { + state = skDISCONNECTED; sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); return (true); } @@ -78,6 +89,8 @@ bool EzSockets::listen() if ( desc < 0 ) return false; + + state = skLISTENING; return true; } @@ -96,12 +109,17 @@ bool EzSockets::accept( EzSockets &socket ) 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; } void EzSockets::close() { + state = skDISCONNECTED; + inBuffer = ""; + outBuffer = ""; // The close socket command is different in Windows #if defined(WIN32) ::closesocket( sock ); @@ -110,197 +128,11 @@ void EzSockets::close() { #endif } -bool EzSockets::receiveLength( int &length ) { - length = 0; - -//cannot send in void* in Windows. -#if defined(WIN32) - int desc = recv( sock, (char*)&length, sizeof(int), 0 ); -#else - int desc = recv( sock, (void*)&length, sizeof(int), 0 ); -#endif - - if ( desc <= 0 ) - return false; - return true; -} - -int EzSockets::receive(char *data, int MAXlength) +long EzSockets::uAddr() { - int x=0; - if ( !receiveLength(x)) - return false; - - int desc=1; - std::string outData; - char buf[4]; - - outData = ""; - - - - //YES! I know this is a crappy way to do it, but - //until someone tells me better... DON'T COMPLAIN - - while( (int) outData.length()0 ) - { - desc = ::recv( sock, buf, 1 , 0 ); - if (desc!=0) - outData+=buf[0]; - } - if (desc==0) - { - return false; - } - if (x>MAXlength) - { - return false; - } - - memcpy (data,outData.c_str(),x); - - return true; + return addr.sin_addr.s_addr; } -bool EzSockets::receive( int &x ) -{ - if ( !receiveLength(x) ) - return false; - return true; -} - -bool EzSockets::receive( std::vector &data ) -{ - char buf[1024]; - /* If the length is less than 1024 then receive - all the data in one recv() command. If the - length is greater than 1024 receive data - with multiple recv() commands. */ - int desc = 0; - int length; - - length = 0; - data.resize(0); - if ( !receiveLength(length) ) - return false; - if ( length <= 1024 ) - { - memset( &buf, 0, sizeof(buf) ); - desc = recv( sock, buf, 1024, 0 ); - for ( int x = 0; x < desc; x++ ) - data.push_back(buf[x]); - } else { - while ( int(data.size()) < length ) - { - memset( &buf, 0, sizeof(buf) ); // Flush the buffer - desc = recv( sock, buf, 1024, 0 ); - for ( int x = 0; x < desc; x++ ) - data.push_back(buf[x]); - } - } - if ( desc <= 0 ) - return false; - /* Make sure data is the correct size. - This may be unneeded but seems like - a good idea. */ - data.resize( length ); - return true; -} - -bool EzSockets::send( const std::string& data ) -{ - /* First send the length of the data to the - server. Then if the length is less than or equal - to the 1024 then send data in one sendData() - command. If data is larger then 1024 than - send the data in multiple sendData() commands. - Each sendData() sends as much as 1024 bytes. - HAVE NOT CHECKED TO SEE IF TRANSFER OF LARGE DATA - IS CORRECT. */ - - int desc = sendLength( data.length() ); - if ( desc == 0 ) - return false; - - if (data.length() <= (1024)) - { - desc = sendData( (char*)data.c_str(), data.length() ); - if ( desc == 0 ) - return false; - } else { - for ( int x = 0; x < int(data.length()); x += 1024 ) - desc = sendData( (char*)std::string(data.substr(x, x+1024)).c_str() ); - if (desc == 0) - return false; - } - return true; -} - -bool EzSockets::send( char *data, int length ) -{ - /* Sends the data in chunks of 1024. Appears to - work fine with large and small amounts of data. */ - int desc; - char buf[1024]; - - desc = sendLength( length ); - if ( desc == 0 ) - return false; - for ( int x = 0; x < length; x += 1024 ) - { - memset( &buf, 0, sizeof(buf) ); - for ( int bytes = 0; bytes < 1024; bytes++ ) - buf[bytes] = (char)data[x+bytes]; - if ( length < 1024 ) - desc = sendData( buf, length ); - else - desc = sendData( buf ); - if ( desc == 0 ) - return false; - } - return true; -} - -bool EzSockets::sendLength(int length) -{ -#if defined(WIN32) - int desc = ::send( sock, (char*)&length, sizeof(int), 0 ); -#else - int desc = ::send( sock, (void*)&length, sizeof(int), 0 ); -#endif - - if ( desc <= 0 ) - return false; - return true; -} - -bool EzSockets::send( int x ) -{ - if ( !sendLength(x) ) - return false; - return true; -} - -bool EzSockets::sendData( char data[1024], int size ) -{ - /* This function sends data just fine. - Problem is with the reassemble while - receiving data.*/ - int desc; - int lpos = 0; - - if ( size == 0 ) - return true; - - while (size-lpos > 0) - { - desc = ::send( sock, *((&data)+lpos), size, 0 ); - if ( desc <= 0 ) - return false; - lpos = lpos + desc; - } - return true; -} bool EzSockets::connect( const std::string& host, unsigned short port ) { @@ -327,47 +159,270 @@ bool EzSockets::connect( const std::string& host, unsigned short port ) return desc >= 0; } -bool EzSockets::sendFlash (const std::string & inData) + + +bool EzSockets::CanRead() { - int inDataSize = inData.length(); - int desc = ::send( sock, inData.c_str(), inDataSize+1 , 0 ); - //Over-ride the C-string by one. - if (desc) - return (true); - else - return (false); + FD_ZERO(scks); + FD_SET(sock,scks); + + if (select (0,scks,NULL,NULL,times)==0) + return false; + return true; +} +bool EzSockets::IsError() +{ + if (state == skERROR) + return true; + + FD_ZERO(scks); + FD_SET(sock,scks); + + if (select (0,NULL,NULL,scks,times)==0) + return false; + return true; +} +bool EzSockets::CanWrite() +{ + FD_ZERO(scks); + FD_SET(sock,scks); + + if (select (0,NULL,scks,NULL,times)==0) + return false; + return true; } -std::string EzSockets::recvFlash () +void EzSockets::update() { - int desc=1; - std::string outData; - char buf[4]; + if (state==skERROR) + return; + //If socket is in error, don't bother. - outData = ""; + if (IsError()) + { + state=skERROR; + return; + } + //Check for reading + while (CanRead() && !IsError()) + pUpdateRead(); + + if (CanWrite() && (outBuffer.length()>0)) + pUpdateWrite(); +} + + + +//Raw data system +void EzSockets::SendData(string & outData) +{ + outBuffer.append(outData); + if (blocking) + while ((outBuffer.length()>0) && !IsError()) + pUpdateWrite(); + else + update(); + +} + +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::ReadData(char *data, unsigned int bytes) +{ + int bytesRead = PeekData(data,bytes); + + inBuffer = inBuffer.substr(bytesRead); + + return bytesRead; +} + +int EzSockets::PeekData(char *data, unsigned int bytes) +{ + if (blocking) + while ((inBuffer.length()0)) { - desc = ::recv( sock, buf, 1 , 0 ); - if (desc!=0) - outData+=buf[0]; - } - if (desc==0) - { - outData = "999Data Failure"; - } - return outData; + + return bytesRead; } - - -long EzSockets::uAddr() +//Packet system (for structures and classes) +void EzSockets::SendPack(char * data, unsigned int bytes) { - return addr.sin_addr.s_addr; + SendData ((char *)&bytes,sizeof(int)); + SendData (data,bytes); } +int EzSockets::ReadPack(char * data, unsigned int max) +{ + int size = PeekPack(data,max); + if (size!=-1) + { + int tSize = (int)((inBuffer.substr(0,4)).c_str()); + inBuffer = inBuffer.substr(tSize+4); + } + return size; +} + +int EzSockets::PeekPack(char * data, unsigned int max) +{ + if (CanRead()) + pUpdateRead(); + + if (blocking) + { + while ((inBuffer.length()<4)&& !IsError()) + { + pUpdateRead(); + } + + unsigned int size=0; + PeekData((char*)size,4); + + 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); + if (inBuffer.length()<(size+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); + } else + return (-1); + + +} + + +//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); +} + +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; +} + + + + +int EzSockets::pUpdateRead() +{ + char tempData[1024]; + int bytes = pReadData(tempData); + if (bytes>0) + inBuffer.append(tempData,bytes); + + //You cannot read 0 bytes! + if (bytes<1) + state = skERROR; + + return bytes; +} + +int EzSockets::pUpdateWrite() +{ + int bytes = pWriteData(outBuffer.c_str(),outBuffer.length()); + outBuffer = outBuffer.substr(bytes); + + return bytes; +} + + +int EzSockets::pReadData(char * data) +{ + return recv( sock, data,1024, 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< #include #include +#include +#include #if defined(WIN32) #include @@ -36,58 +38,112 @@ using namespace std; class EzSockets { - private: +public: - #if defined(WIN32) - WSADATA wsda; - #endif + EzSockets(); + ~EzSockets(); + + //Crate the socket + int create(); + + //Bind Socket to local port + bool bind(unsigned short port); + + //Listen with socket + bool listen(); + + //Accept incomming socket + bool accept(EzSockets &socket); + + //Connect + bool connect(const std::string& host, unsigned short port); + + //Kill socket + void close(); + + //see if socket has been created + bool check(); + + long uAddr(); + + bool CanRead(); + bool IsError(); + bool CanWrite(); + + void update(); + + //Raw data system + void SendData(string & outData); + void SendData(const char *data, unsigned int bytes); + int ReadData(char *data, unsigned int bytes); + int PeekData(char *data, unsigned int bytes); + + //Packet system (for structures and classes) + void SendPack(char * data, unsigned int bytes); + int ReadPack(char * data, unsigned int max); + int PeekPack(char * data, unsigned int max); + + //String (Flash) system / Null-terminated strings + void SendStr(string & data, char delim = '\0'); + int ReadStr(string & data, char delim = '\0'); + int PeekStr(string & data, char delim = '\0'); - int MAXCON; - int sock; - struct sockaddr_in addr; + //Operators + char operator[] (int i); //Access buffer + friend istream& operator >>(istream &is,EzSockets &obj); + friend ostream& operator <<(ostream &os,const EzSockets &obj); - bool sendData(char data[1024], int size = 1024); - bool sendLength(int length); - bool receiveLength(int &length); - public: - EzSockets(); - ~EzSockets(); - //Check to see if Socket is active - bool check(); - //Crate the socket - int create(); - //Bind Socket to local port - bool bind(unsigned short port); - //Listen with socket - bool listen(); - //Accept incomming socket - bool accept(EzSockets &socket); - //Receive raw data - bool receive(std::vector &data); - //Receive structure - bool receive(int &x); - //Receive Structure (or other data) - int receive(char *data, int MAXlength); - //Send string - bool send(const std::string& data); - //Send Structure (or other data) - bool send(char *data, int length); - //Send Integer - bool send(int x); - //Connect to remote host - //NOTE: YOU MUST PUT IN IP, NOT NAME - bool connect(const std::string& host, unsigned short port); + bool blocking; - //Used for sending and receiving functions from flash - bool sendFlash (const std::string & inData); - - std::string recvFlash (); - long uAddr(); - //Kill socket - void close(); + //The following possibly should be private. + string inBuffer; + string outBuffer; + + int pUpdateWrite(); + int pUpdateRead(); + + int pReadData(char * data); + int pWriteData(const char * data, int dataSize); + + + enum SockState { + skDISCONNECTED = 0, + skUNDEF1, //Not implemented + skLISTENING, + skUNDEF3, //Not implemented + skUNDEF4, //Not implemented + skUNDEF5, //Not implemented + skUNDEF6, //Not implemented + skCONNECTED, + skERROR + }; + + SockState state; + +private: + + //Only necessiary in windows +#if defined(WIN32) + WSADATA wsda; +#endif + + int MAXCON; + int sock; + struct sockaddr_in addr; + + + //Used for Select() command + fd_set * scks; + timeval * times; + + //Buffers }; + istream& operator >>(istream &is,EzSockets &obj); + ostream& operator <<(ostream &os,EzSockets &obj); + + #endif