diff --git a/src/ZE_ZClient.cpp b/src/ZE_ZClient.cpp new file mode 100755 index 0000000..3e58cbf --- /dev/null +++ b/src/ZE_ZClient.cpp @@ -0,0 +1,170 @@ +/******************************************************************************* + This file is Part of the ZEngine Library for 2D game development. + Copyright (C) 2002, 2003 James Turk + + Licensed under a BSD-style license. + + The maintainer of this library is James Turk (james@conceptofzero.net) + and the home of this Library is http://www.zengine.sourceforge.net +*******************************************************************************/ + +/*! +\par File Header: +File: ZE_ZClient.cpp
+Description: Implementation source file for core ZEngine TCP Client Object.
+Author(s): James Turk
+$Id:
+ + \file ZE_ZClient.cpp + \brief Source file for ZClient. + + Implementation file for ZClient, the TCP Client class for ZEngine. +**/ + +#include "ZE_ZClient.h" + +namespace ZE +{ + +string num2dotted4(unsigned int num) +{ + vector ip; + int d=256*256*256; + int m; + + while(d > 0) + { + m = num/d; + num %= d; + ip.push_back(m); + d /= 256; + } + + return FormatStr("%d.%d.%d.%d",ip[3],ip[2],ip[1],ip[0]); +} + +ZClient::ZClient(bool verbose) +{ + rEngine = ZEngine::GetInstance(); + rSocket = NULL; + rSocketSet = NULL; + rVerbose = verbose; + rWaitTime = 0; +} + +ZClient::~ZClient() +{ + Disconnect(); +} + +bool ZClient::Connect(char *server, Uint16 port) +{ + IPaddress ip; + + if(SDLNet_ResolveHost(&ip,server,port) < 0) + rEngine->ReportError(ZERR_NET_CLIENT,FormatStr("Failed to resolve host: %s:%d",server,port)); + else if(rVerbose) + rEngine->WriteLog(FormatStr("ZClient: resolved host: %s:%d",server,port)); + + rEngine->WriteLog(FormatStr("IP: %s",num2dotted4(ip.host).c_str())); + + rSocket = SDLNet_TCP_Open(&ip); //try to open rSocket + + if(!rSocket) + { + rEngine->ReportError(ZERR_NET_CLIENT,"Failed to open TCP socket."); + Disconnect(); + return false; + } + + rSocketSet = SDLNet_AllocSocketSet(1); //get a set for the single socket + if(!rSocketSet || SDLNet_TCP_AddSocket(rSocketSet,rSocket) == -1) + { + rEngine->ReportError(ZERR_NET_CLIENT,"Failed to create socket set."); + Disconnect(); + return false; + } + + return true; +} + +void ZClient::Disconnect() +{ + if(rSocket) + { + SDLNet_TCP_Close(rSocket); + rSocket = NULL; + } + if(rSocketSet) + { + SDLNet_FreeSocketSet(rSocketSet); + rSocketSet = NULL; + } +} + +void ZClient::SetWaitTime(int wait) +{ + rWaitTime = wait; +} + +bool ZClient::Send(ZByte *data, int size) +{ + int sent = 0; + + if(rSocket) + { + sent = SDLNet_TCP_Send(rSocket,data,size); + + if(sent < size) + { + rEngine->ReportError(ZERR_NET_CLIENT,FormatStr("Failed to send data, closing socket: %s", SDLNet_GetError())); + Disconnect(); + return false; + } + else if(rVerbose) + rEngine->WriteLog(FormatStr("ZClient: Sent %d bytes to server.",sent)); + + return true; + } + else + { + rEngine->ReportError(ZERR_NOSOCKET,"Send"); + return false; + } +} + +int ZClient::Receive(ZByte *data) +{ + int received = 0; + + if(rSocket) + { + if(SDLNet_CheckSockets(rSocketSet, rWaitTime) > 0 && SDLNet_SocketReady(rSocket)) + { + received = SDLNet_TCP_Recv(rSocket,data,MAX_MSG_LEN); + if(received <= 0) + { + Disconnect(); + rEngine->ReportError(ZERR_NET_CLIENT,FormatStr("TCP_Recv failed [%s]",SDLNet_GetError())); + } + else if(rVerbose) + rEngine->WriteLog(FormatStr("ZClient: received %d bytes.",received)); + } + } + else + rEngine->ReportError(ZERR_NOSOCKET,"Receive"); + + return received; +} + +bool ZClient::Connected() +{ + return rSocket?true:false; +} + +int ZClient::WaitTime() +{ + return rWaitTime; +} + +} //namespace ZE diff --git a/src/ZE_ZServer.cpp b/src/ZE_ZServer.cpp new file mode 100755 index 0000000..03d9942 --- /dev/null +++ b/src/ZE_ZServer.cpp @@ -0,0 +1,196 @@ +/******************************************************************************* + This file is Part of the ZEngine Library for 2D game development. + Copyright (C) 2002, 2003 James Turk + + Licensed under a BSD-style license. + + The maintainer of this library is James Turk (james@conceptofzero.net) + and the home of this Library is http://www.zengine.sourceforge.net +*******************************************************************************/ + +/*! +\par File Header: +File: ZE_ZServer.cpp
+Description: Implementation source file for core ZEngine TCP Server Object.
+Author(s): James Turk
+$Id:
+ + \file ZE_ZServer.cpp + \brief Source file for ZServer. + + Implementation file for ZServer, the TCP Server class for ZEngine. +**/ + +#include "ZE_ZServer.h" + +namespace ZE +{ + +void ZServer::CloseSocket(int num) +{ + SDLNet_TCP_Close(rClientSockets[num]); + rClientSockets[num] = NULL; + if(rVerbose) + rEngine->WriteLog(FormatStr("Closing socket #%d",num)); +} + +ZServer::ZServer(bool v) +{ + rEngine = ZEngine::GetInstance(); + + rSocket = NULL; + rSocketSet = NULL; + rClientSockets = NULL; + rMaxClients = 0; + rVerbose = v; + rWaitTime = 0; +} + +ZServer::~ZServer() +{ + Stop(); +} + +bool ZServer::Start(int maxClients, Uint16 port) +{ + IPaddress ip; + + rMaxClients = maxClients; + rClientSockets = new TCPsocket[rMaxClients]; + + rSocketSet = SDLNet_AllocSocketSet(rMaxClients+1); //need one more (for server socket) + if(!rSocketSet) + { + rEngine->ReportError(ZERR_NET_SERVER,FormatStr("Failed to create sockets (%s).",SDLNet_GetError())); + Stop(); + return false; + } + else if(rVerbose) + rEngine->WriteLog(FormatStr("ZServer: Created server with %d available sockets.",rMaxClients)); + + for(int i=0; i < rMaxClients; i++) + rClientSockets[i] = NULL; + + if(SDLNet_ResolveHost(&ip,NULL,port) < 0) //try to resolve the host + rEngine->ReportError(ZERR_NET_SERVER,FormatStr("Failed to create host server on port %d (%s).",port,SDLNet_GetError())); + else if(rVerbose) + rEngine->WriteLog(FormatStr("ZServer: Created host server on port %d.",port)); + + rSocket = SDLNet_TCP_Open(&ip); //try to open socket + if(!rSocket || SDLNet_TCP_AddSocket(rSocketSet,rSocket) == -1) + { + rEngine->ReportError(ZERR_NET_SERVER,"Failed to open server TCP socket."); + Stop(); + return false; + } + + return true; +} + +void ZServer::Stop() +{ + if(rSocket) + { + SDLNet_TCP_Close(rSocket); + rSocket = NULL; + } + if(rSocketSet) + { + SDLNet_FreeSocketSet(rSocketSet); + rSocketSet = NULL; + } + if(rClientSockets) + { + for(int i=0; i < rMaxClients; i++) + { + if(rClientSockets[i]) + { + CloseSocket(i); + } + } + delete[] rClientSockets; + } + + rMaxClients = 0; +} + +void ZServer::SetWaitTime(int wait) +{ + rWaitTime = wait; +} + +void ZServer::CheckSockets() +{ + ZByte buf[MAX_MSG_LEN]; + int result,size,count; + + SDLNet_CheckSockets(rSocketSet, rWaitTime); + + if(SDLNet_SocketReady(rSocket)) //new client + { + for(count=0; count < rMaxClients; count++) //find first open socket + { + if(!rClientSockets[count]) + break; + } + + if(rClientSockets[count]) //if it exists the set is full + { + rEngine->ReportError(ZERR_NET_SERVER,FormatStr("All %d ports full.",rMaxClients)); + } + else + { + rClientSockets[count] = SDLNet_TCP_Accept(rSocket); + SDLNet_TCP_AddSocket(rSocketSet, rClientSockets[count]); + if(rVerbose) + rEngine->WriteLog(FormatStr("ZServer: Adding socket #%d.",count+1)); + } + } + + //check all sockets for activity// + for(int i=0; i < rMaxClients; i++) + { + if(SDLNet_SocketReady(rClientSockets[i])) //incoming message + { + result = SDLNet_TCP_Recv(rClientSockets[i], buf, MAX_MSG_LEN); + + if(result <= 0) //disconnect bad sockets + CloseSocket(i); + else if(rVerbose) + rEngine->WriteLog(FormatStr("ZServer: Received %d bytes on Port %d",result,i)); + + size = result; + if(rVerbose) + rEngine->WriteLog("ZServer: Mirroring data: "); + for(int j=0; j < rMaxClients; j++) + { + if(rClientSockets[j] && i != j) //send to open sockets that aren't the same + { + result = SDLNet_TCP_Send(rClientSockets[j],buf,size); + if(rVerbose) + rEngine->WriteLog(FormatStr(" +%d bytes on socket %d.",size,j)); + } + } + } + } +} + +int ZServer::Clients() +{ + int numClients=0; + + for(int i=0; i < rMaxClients; i++) + { + if(rClientSockets[i]) + numClients++; + } + + return numClients; +} + +int ZServer::WaitTime() +{ + return rWaitTime; +} + +} //namespace ZE