New version of ezsockets for future network features.

This commit is contained in:
Charles Lohr
2004-05-24 13:59:05 +00:00
parent 28a3a099b1
commit 7729bf48b7
4 changed files with 418 additions and 308 deletions
+19 -21
View File
@@ -34,9 +34,6 @@
#include "Steps.h" #include "Steps.h"
#define NEXT_SCREEN THEME->GetMetric ("ScreenSelectMusic","NextScreen")
//Used for advancing to gameplay screen
NetworkSyncManager::NetworkSyncManager() NetworkSyncManager::NetworkSyncManager()
{ {
NetPlayerClient = new EzSockets; NetPlayerClient = new EzSockets;
@@ -91,11 +88,14 @@ void NetworkSyncManager::PostStartUp(CString ServerIP)
useSMserver = true; useSMserver = true;
m_startupStatus = 1; //Connection attepmpt sucessful m_startupStatus = 1; //Connection attepmpt sucessful
LOG->Info("CNConnected!");
int ClientCommand=3; 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, // If network play is desired and the connection works,
// halt until we know what server version we're dealing with // halt until we know what server version we're dealing with
vector <CString> ProfileNames; vector <CString> ProfileNames;
@@ -109,7 +109,7 @@ void NetworkSyncManager::PostStartUp(CString ServerIP)
for( i=0; i < strlen(ProfileNames[0]); i++ ) for( i=0; i < strlen(ProfileNames[0]); i++ )
PlayerName.m_data[i] = ProfileNames[0][i]; PlayerName.m_data[i] = ProfileNames[0][i];
PlayerName.m_data[i] = 0; PlayerName.m_data[i] = 0;
NetPlayerClient->send((char*) &PlayerName,20); NetPlayerClient->SendPack((char*) &PlayerName,20);
} }
if( ProfileNames.size() > 1 ) if( ProfileNames.size() > 1 )
{ {
@@ -118,7 +118,7 @@ void NetworkSyncManager::PostStartUp(CString ServerIP)
for( i=0; i < strlen(ProfileNames[1]); i++ ) for( i=0; i < strlen(ProfileNames[1]); i++ )
PlayerName.m_data[i] = ProfileNames[1][i]; PlayerName.m_data[i] = ProfileNames[1][i];
PlayerName.m_data[i] = 0; PlayerName.m_data[i] = 0;
NetPlayerClient->send( (char*) &PlayerName,20 ); NetPlayerClient->SendPack( (char*) &PlayerName,20 );
} }
LOG->Info("Server Version: %d",m_ServerVersion); 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. //It is this way now for protocol's purpose.
//If there is a new protocol developed down the road //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 NetPlayerClient->create(); // Initilize Socket
useSMserver = NetPlayerClient->connect(addy, port); 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; SendNetPack.m_life=m_playerLife[playerID] + CurGrade*65536;
//Send packet to server //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; SendNetPack.m_life=0;
NetPlayerClient->send((char*)&SendNetPack, sizeof(netHolder)); NetPlayerClient->SendPack((char*)&SendNetPack, sizeof(netHolder));
return; return;
} }
@@ -251,7 +245,7 @@ void NetworkSyncManager::StartRequest()
return ; return ;
vector <char> 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."); LOG->Trace("Requesting Start from Server.");
@@ -278,12 +272,12 @@ void NetworkSyncManager::StartRequest()
SendNetPack.m_life=0; SendNetPack.m_life=0;
SendNetPack.m_combo=0; SendNetPack.m_combo=0;
NetPlayerClient->send((char*)&SendNetPack, sizeof(netHolder)); NetPlayerClient->SendPack((char*)&SendNetPack, sizeof(netHolder));
LOG->Trace("Waiting for RECV"); LOG->Trace("Waiting for RECV");
//Block until go is recieved. //Block until go is recieved.
NetPlayerClient->receive(tmp); NetPlayerClient->ReadData((char *)tmp, 4);
LOG->Trace("Starting Game."); LOG->Trace("Starting Game.");
} }
@@ -322,10 +316,10 @@ void NetworkSyncManager::SendSongs()
toSend[2]=char(0); toSend[2]=char(0);
toSend[3]=char(0); toSend[3]=char(0);
NetPlayerClient->send (toSend,SongInfo.length()+4); NetPlayerClient->SendPack (toSend,SongInfo.length()+4);
} }
toSend[0]=char(36); toSend[0]=char(36);
NetPlayerClient->send (toSend,4); NetPlayerClient->SendPack (toSend,4);
//Exit because this is ONLY for use with SMOnline //Exit because this is ONLY for use with SMOnline
//If admins feel strongly, this can be exported //If admins feel strongly, this can be exported
@@ -358,6 +352,10 @@ void NetworkSyncManager::DisplayStartupStatus()
SCREENMAN->SystemMessage(sMessage); SCREENMAN->SystemMessage(sMessage);
} }
void NetworkSyncManager::Update(float fDeltaTime)
{
}
//Global and accessable from anywhere //Global and accessable from anywhere
NetworkSyncManager *NSMAN; NetworkSyncManager *NSMAN;
+4 -3
View File
@@ -15,9 +15,6 @@
#include "PlayerNumber.h" #include "PlayerNumber.h"
void NSSendSongs();
void ArgStartCourse(CString CourseName);
class EzSockets; class EzSockets;
class NetworkSyncManager class NetworkSyncManager
@@ -34,12 +31,16 @@ public:
void SendSongs(); //Send song list to server (And exit) void SendSongs(); //Send song list to server (And exit)
void PostStartUp(CString ServerIP); void PostStartUp(CString ServerIP);
void CloseConnection(); void CloseConnection();
void DisplayStartupStatus(); //Used to note user if connect attempt was sucessful or not. void DisplayStartupStatus(); //Used to note user if connect attempt was sucessful or not.
int m_playerLife[NUM_PLAYERS]; //Life int m_playerLife[NUM_PLAYERS]; //Life
void Update(float fDeltaTime);
private: private:
void StartUp(); void StartUp();
+281 -226
View File
@@ -1,6 +1,3 @@
//#include "global.h"
//Commented out because there is no StepMania here.
/******************************************* /*******************************************
ezsockets.cpp -- Header for sockets.cpp ezsockets.cpp -- Header for sockets.cpp
Designed by Josh Allen and Charles Designed by Josh Allen and Charles
@@ -16,15 +13,17 @@
********************************************/ ********************************************/
// We need the WinSock32 Library on Windows // We need the WinSock32 Library on Windows
#include <cstring>
#include "ezsockets.h"
#include <iostream>
using namespace std;
#if defined(WIN32) #if defined(WIN32)
#pragma comment(lib,"wsock32.lib") #pragma comment(lib,"wsock32.lib")
#endif #endif
#include <iostream>//REMOVE SOON
#include "ezsockets.h"
EzSockets::EzSockets() EzSockets::EzSockets()
{ {
MAXCON = 5; MAXCON = 5;
@@ -36,6 +35,17 @@ EzSockets::EzSockets()
#endif #endif
sock = -1; sock = -1;
blocking=true;
scks = new fd_set;
times = new timeval;
times->tv_sec = 0;
times->tv_usec = 0;
state = skDISCONNECTED;
} }
EzSockets::~EzSockets() EzSockets::~EzSockets()
@@ -53,6 +63,7 @@ bool EzSockets::check()
int EzSockets::create() int EzSockets::create()
{ {
state = skDISCONNECTED;
sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
return (true); return (true);
} }
@@ -78,6 +89,8 @@ bool EzSockets::listen()
if ( desc < 0 ) if ( desc < 0 )
return false; return false;
state = skLISTENING;
return true; return true;
} }
@@ -96,12 +109,17 @@ bool EzSockets::accept( EzSockets &socket )
int length = sizeof( socket ); int length = sizeof( socket );
socket.sock = ::accept( sock, (struct sockaddr *)&socket.addr,(socklen_t *)&length ); socket.sock = ::accept( sock, (struct sockaddr *)&socket.addr,(socklen_t *)&length );
socket.state = skCONNECTED;
if ( socket.sock < 0 ) if ( socket.sock < 0 )
return false; return false;
return true; return true;
} }
void EzSockets::close() { void EzSockets::close() {
state = skDISCONNECTED;
inBuffer = "";
outBuffer = "";
// The close socket command is different in Windows // The close socket command is different in Windows
#if defined(WIN32) #if defined(WIN32)
::closesocket( sock ); ::closesocket( sock );
@@ -110,197 +128,11 @@ void EzSockets::close() {
#endif #endif
} }
bool EzSockets::receiveLength( int &length ) { long EzSockets::uAddr()
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)
{ {
int x=0; return addr.sin_addr.s_addr;
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()<x && desc>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;
} }
bool EzSockets::receive( int &x )
{
if ( !receiveLength(x) )
return false;
return true;
}
bool EzSockets::receive( std::vector<char> &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 ) 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; return desc >= 0;
} }
bool EzSockets::sendFlash (const std::string & inData)
bool EzSockets::CanRead()
{ {
int inDataSize = inData.length(); FD_ZERO(scks);
int desc = ::send( sock, inData.c_str(), inDataSize+1 , 0 ); FD_SET(sock,scks);
//Over-ride the C-string by one.
if (desc) if (select (0,scks,NULL,NULL,times)==0)
return (true); return false;
else return true;
return (false); }
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; if (state==skERROR)
std::string outData; return;
char buf[4]; //If socket is in error, don't bother.
outData = ""; if (IsError())
//YES! I know this is a crappy way to do it, but
//until someone tells me better... DON'T COMPLAIN
buf[0] = '\r'; //Put something in buf to stop while.
while ((buf[0] != '\0') && (desc>0)) {
desc = ::recv( sock, buf, 1 , 0 );
if (desc!=0)
outData+=buf[0];
}
if (desc==0)
{ {
outData = "999Data Failure"; state=skERROR;
return;
} }
return outData;
//Check for reading
while (CanRead() && !IsError())
pUpdateRead();
if (CanWrite() && (outBuffer.length()>0))
pUpdateWrite();
} }
long EzSockets::uAddr() //Raw data system
void EzSockets::SendData(string & outData)
{ {
return addr.sin_addr.s_addr; 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()<bytes) && !IsError())
pUpdateRead();
else
{
while (CanRead()&&!IsError())
pUpdateRead();
}
int bytesRead = bytes;
if (inBuffer.length()<bytes)
bytesRead = inBuffer.length();
memcpy(data,(inBuffer.substr(0,bytesRead)).c_str(),bytesRead);
return bytesRead;
}
//Packet system (for structures and classes)
void EzSockets::SendPack(char * data, unsigned int bytes)
{
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<<readString;
return os;
}
+112 -56
View File
@@ -1,24 +1,26 @@
/******************************************* /*******************************************
ezsockets.h -- Header for sockets.cpp EzSockets - a multiplatform generic
Designed by Josh Allen and Charles sockets class (Version 2)
Lohr. Socket programming methods based Original code by Josh Allen
on Charles Lohr's EZW progam. Modified by Charles Lohr
You may freely destribute this code
if this message is retained. All contents of this file Copyright
This code is distributed on an as-is 2003-2004 Charles Lohr
basis with no gaurentees whatsoever. Joshua Allen
This file may be used under what
license the StepMania project is using.
Modified by Charles Lohr for use on
windows and Unix.
Modified by Charles Lohr for use with
Macromedia Flash.
********************************************/ ********************************************/
#ifndef __EZSOCKETS_H #ifndef __EZSOCKETS_H
#define __EZSOCKETS_H #define __EZSOCKETS_H
#include <sstream>
#include <string> #include <string>
#include <vector> #include <vector>
#include <fcntl.h>
#include <ctype.h>
#if defined(WIN32) #if defined(WIN32)
#include <winsock2.h> #include <winsock2.h>
@@ -36,58 +38,112 @@
using namespace std; using namespace std;
class EzSockets { class EzSockets {
private: public:
#if defined(WIN32) EzSockets();
WSADATA wsda; ~EzSockets();
#endif
//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; //Operators
int sock; char operator[] (int i); //Access buffer
struct sockaddr_in addr; 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(); bool blocking;
~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<char> &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);
//Used for sending and receiving functions from flash
bool sendFlash (const std::string & inData);
std::string recvFlash (); //The following possibly should be private.
string inBuffer;
string outBuffer;
long uAddr(); int pUpdateWrite();
//Kill socket int pUpdateRead();
void close();
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 #endif