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"
#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 <CString> 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 <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.");
@@ -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;
+4 -3
View File
@@ -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();
+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
Designed by Josh Allen and Charles
@@ -16,15 +13,17 @@
********************************************/
// We need the WinSock32 Library on Windows
#include <cstring>
#include "ezsockets.h"
#include <iostream>
using namespace std;
#if defined(WIN32)
#pragma comment(lib,"wsock32.lib")
#endif
#include <iostream>//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()<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;
return addr.sin_addr.s_addr;
}
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 )
{
@@ -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()<bytes) && !IsError())
pUpdateRead();
else
{
while (CanRead()&&!IsError())
pUpdateRead();
}
int bytesRead = bytes;
if (inBuffer.length()<bytes)
bytesRead = inBuffer.length();
//YES! I know this is a crappy way to do it, but
//until someone tells me better... DON'T COMPLAIN
memcpy(data,(inBuffer.substr(0,bytesRead)).c_str(),bytesRead);
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";
}
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<<readString;
return os;
}
+114 -58
View File
@@ -1,24 +1,26 @@
/*******************************************
ezsockets.h -- Header for sockets.cpp
Designed by Josh Allen and Charles
Lohr. Socket programming methods based
on Charles Lohr's EZW progam.
You may freely destribute this code
if this message is retained.
This code is distributed on an as-is
basis with no gaurentees whatsoever.
EzSockets - a multiplatform generic
sockets class (Version 2)
Original code by Josh Allen
Modified by Charles Lohr
Modified by Charles Lohr for use on
windows and Unix.
Modified by Charles Lohr for use with
Macromedia Flash.
All contents of this file Copyright
2003-2004 Charles Lohr
Joshua Allen
This file may be used under what
license the StepMania project is using.
********************************************/
#ifndef __EZSOCKETS_H
#define __EZSOCKETS_H
#include <sstream>
#include <string>
#include <vector>
#include <fcntl.h>
#include <ctype.h>
#if defined(WIN32)
#include <winsock2.h>
@@ -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<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);
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