From 4af6c609f92bf265d9a0f43aa877d9ab8e5a0ad7 Mon Sep 17 00:00:00 2001 From: Charles Lohr Date: Tue, 16 Mar 2004 22:34:48 +0000 Subject: [PATCH] These are the files necessiary for making the network work. --- stepmania/src/NetworkSyncManager.cpp | 116 +++++++++++ stepmania/src/NetworkSyncManager.h | 59 ++++++ stepmania/src/ezsockets.cpp | 289 +++++++++++++++++++++++++++ stepmania/src/ezsockets.h | 82 ++++++++ 4 files changed, 546 insertions(+) create mode 100644 stepmania/src/NetworkSyncManager.cpp create mode 100644 stepmania/src/NetworkSyncManager.h create mode 100644 stepmania/src/ezsockets.cpp create mode 100644 stepmania/src/ezsockets.h diff --git a/stepmania/src/NetworkSyncManager.cpp b/stepmania/src/NetworkSyncManager.cpp new file mode 100644 index 0000000000..977f6052c4 --- /dev/null +++ b/stepmania/src/NetworkSyncManager.cpp @@ -0,0 +1,116 @@ + +/* +----------------------------------------------------------------------------- + Class: Network Sync Manager + + Desc: See Header. + + Copyright (c) 2003-2004 by the person(s) listed below. All rights reserved. + Charles Lohr + Joshua Allen +----------------------------------------------------------------------------- +*/ +#include "global.h" +#include "NetworkSyncManager.h" +#include "ezsockets.h" +#include "RageLog.h" + + +NetworkSyncManager::NetworkSyncManager () +{ + //No Code +} + +NetworkSyncManager::~NetworkSyncManager () +{ + if (useSMserver!=1) + return ; + //Close Connection to server nicely. + NetPlayerClient.close(); + return ; +} + +int NetworkSyncManager::Connect(char * addy, int port) +{ + if (port!=8765) + return (-1); + //Make sure using port 8765 + //This may change in future versions + //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. + + + NetPlayerClient.create(); //Initilize Socket + + if(!NetPlayerClient.connect(addy,port)) { + useSMserver = -1; //If connection to socket fails, tell + //other network functions to not do anything + } else { + useSMserver = 1; //Utilize other network funtions + } + return (1); +} + +void NetworkSyncManager::ReportScore (int playerID, int step, int score, int combo) +{ + if (useSMserver!=1) //Make sure that we are using the network + return ; + + netHolder SendNetPack; //Create packet to send to server + + SendNetPack.m_playerID = playerID; + SendNetPack.m_combo=combo; + SendNetPack.m_score=score; //Load packet with aproperate info + SendNetPack.m_step=step-1; + + NetPlayerClient.send((char*)&SendNetPack, sizeof(netHolder)); + //Send packet to server + return; +} + +void NetworkSyncManager::ReportSongOver () +{ + if (useSMserver!=1) //Make sure that we are using the network + return ; + + netHolder SendNetPack; //Create packet to send to server + + SendNetPack.m_playerID = 21; + SendNetPack.m_combo=0; + SendNetPack.m_score=0; //Use PID 21 (Song over Packet) + SendNetPack.m_step=0; + + NetPlayerClient.send((char*)&SendNetPack, sizeof(netHolder)); + return; +} + +void NetworkSyncManager::StartRequest () +{ + if (useSMserver!=1) + return ; + + vector tmp; //Temporary vector used by receive function + //when waiting + + LOG->Trace("Requesting Start from Server."); + + netHolder SendNetPack; + + SendNetPack.m_playerID = 20; + SendNetPack.m_combo=0; + SendNetPack.m_score=0; //PID 20 (Song Start Request Packet) + SendNetPack.m_step=0; + + NetPlayerClient.send((char*)&SendNetPack, sizeof(netHolder)); + + LOG->Trace("Waiting for RECV"); + + //Block until go is recieved. + NetPlayerClient.receive(tmp); + + LOG->Trace("Starting Game."); + return ; +} \ No newline at end of file diff --git a/stepmania/src/NetworkSyncManager.h b/stepmania/src/NetworkSyncManager.h new file mode 100644 index 0000000000..9840b19c41 --- /dev/null +++ b/stepmania/src/NetworkSyncManager.h @@ -0,0 +1,59 @@ +#ifndef NetworkSyncManager_H +#define NetworkSyncManager_H + +/* +----------------------------------------------------------------------------- + Class: NetworkSyncManager (And netholder) + + Desc: Uses ezsockets for primitive song syncing and score reporting. + + Copyright (c) 2003-2004 by the person(s) listed below. All rights reserved. + Charles Lohr + Joshua Allen +----------------------------------------------------------------------------- +*/ + +#include "ezsockets.h" + +static int useSMserver; //Using network or not? +static EzSockets NetPlayerClient; //Socket used for network traffic + +class NetworkSyncManager +{ +public: + NetworkSyncManager(); + ~NetworkSyncManager(); + + void ReportScore(int playerID, int step, int score, int combo); + //If "useSMserver" then send score to server + + void ReportSongOver(); //Report to server that song is over + + void StartRequest(); //Request a start. Block until granted. + + int Connect(char * addy, int port); + //Connect to SM Server + + int m_playerID; //these are currently unused, but need to stay + int m_step; + int m_score; + int m_combo; +private: +}; + +class netHolder //Data structure used for sending data to server +{ +public: + int m_playerID; //PID (also used for Commands) + int m_step; //SID (StepID, 0-6 for Miss to Marv, 7,8 for boo and ok) + int m_score; //Player's Score + int m_combo; //Player's Current Combo +}; + +//Static this class inside itself +//so that other parts of the program that include +//NetworkSyncManager can use "currentNetPlayer" +static NetworkSyncManager currentNetPlayer; + +#endif + diff --git a/stepmania/src/ezsockets.cpp b/stepmania/src/ezsockets.cpp new file mode 100644 index 0000000000..879d9e7c13 --- /dev/null +++ b/stepmania/src/ezsockets.cpp @@ -0,0 +1,289 @@ +/******************************************* + ezsockets.cpp -- 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. + + Modified by Charles Lohr for use with + Windows-Based OSes. +********************************************/ + +#pragma comment(lib,"wsock32.lib") + //We need the Winsock32 Libary + +#include "ezsockets.h" + +EzSockets::EzSockets() { + MAXCON = 5; + memset (&addr, 0, sizeof(addr)); //Clear the sockaddr_in structure + +//Windows REQUIRES WinSock Startup +#if defined(WIN32) + WSAStartup(MAKEWORD(1,1), &wsda); +#endif + + + sock = -1; +} + +EzSockets::~EzSockets() { + close(); +} + +bool EzSockets::check() { + //Check to see if the socket ahs been created + if (sock < 0) { + return false; + } + return true; +} + +int EzSockets::create() { + sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + return (true); +} + +bool EzSockets::bind(int 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; + } + return true; +} + +bool EzSockets::accept(EzSockets &socket) { + + //Windows wants it defined as a signed int +#if defined(WIN32) + int length = sizeof(socket); +#else + unsigned int length = sizeof(socket); +#endif + + socket.sock = ::accept(sock, (struct sockaddr *) & socket.addr,& length); + if (socket.sock < 0) { + return false; + } + return true; +} + +void EzSockets::close() { + //The close socket command is different in Windows +#if defined(WIN32) + ::closesocket(sock); +#else + ::close(sock); +#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; +} + +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 maybe uneeded but seems like + a good idea. + */ + data.resize(length); + return true; +} + +bool EzSockets::send(std::string data) { + /* First send 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() + commans. If data is larger then 1024 than + send the data in multiple sendData() commands. + Each sendData() sends as much data as 1024. + HAVE NOT CHECK 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 data ammounts. + */ + 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(std::string host, int port) { + if (!check()) { + return false; + } + +#if defined(WIN32) + struct hostent* phe; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + phe = gethostbyname(host.c_str()); + addr.sin_addr = *((LPIN_ADDR)*phe->h_addr_list); + + int desc = ::connect(sock,(struct sockaddr *)&addr,sizeof(addr)); +#else + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + int status = inet_pton ( AF_INET, host.c_str(), &addr.sin_addr ); + + int desc = ::connect(sock,(struct sockaddr *)&addr,sizeof(addr)); +#endif + + if (desc < 0) { + return false; + } + return true; +} + +long EzSockets::uAddr() { + return addr.sin_addr.s_addr; +} + diff --git a/stepmania/src/ezsockets.h b/stepmania/src/ezsockets.h new file mode 100644 index 0000000000..b6e5f91929 --- /dev/null +++ b/stepmania/src/ezsockets.h @@ -0,0 +1,82 @@ +/******************************************* + 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. + + Modified by Charles Lohr for use on + windows and Unix. +********************************************/ + +#ifndef __EZSOCKETS_H +#define __EZSOCKETS_H + +#include +#include + +#if defined(WIN32) +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +class EzSockets { + private: + + #if defined(WIN32) + WSADATA wsda; + #endif + + + int MAXCON; + int sock; + struct sockaddr_in addr; + + 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(int 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); + //Send string + bool send(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(std::string host, int port); + + long uAddr(); + //Kill socket + void close(); +}; + +#endif