[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: 2 Player mode
On 07.10.2006 10:26, Jens Granseuer wrote:
> Anyway, I'm currently working on getting proper net infrastructure
> support into the code.
I feel very much like I'm moving in baby steps. Does this look sane
so far?
Jens
// Crimson Fields -- a game of tactical warfare
// Copyright (C) 2000-2006 Jens Granseuer
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
////////////////////////////////////////////////////////////////////////
// network.cpp - networking
////////////////////////////////////////////////////////////////////////
#include "network.h"
////////////////////////////////////////////////////////////////////////
// NAME : NetBuffer::NetBuffer
// DESCRIPTION: Create a new buffer in memory.
// PARAMETERS : size - desired buffer size
// RETURNS : -
////////////////////////////////////////////////////////////////////////
NetBuffer::NetBuffer( int size ) : size(size) {
buffer = new char[size];
fh = SDL_RWFromMem( buffer, size );
}
////////////////////////////////////////////////////////////////////////
// NAME : NetBuffer::~NetBuffer
// DESCRIPTION: Free the buffer.
// PARAMETERS : -
// RETURNS : -
////////////////////////////////////////////////////////////////////////
NetBuffer::~NetBuffer( void ) {
delete buffer;
SDL_FreeRW( fh );
}
extern "C" {
struct PacketHeader {
Uint32 id;
Uint16 type;
Uint8 version;
Uint8 reserved;
Uint32 size;
Uint32 crc;
};
}
////////////////////////////////////////////////////////////////////////
// NAME : TCPConnection::TCPConnection
// DESCRIPTION: Create a new TCP/IP client connection.
// PARAMETERS : server - IP address or name of server to connect to
// port - port to connect to
// RETURNS : -
////////////////////////////////////////////////////////////////////////
TCPConnection::TCPConnection( const string &server, Uint16 port ) : client(0), server(false) {
Init( server.c_str(), port );
}
////////////////////////////////////////////////////////////////////////
// NAME : TCPConnection::TCPConnection
// DESCRIPTION: Create a new TCP/IP server connection.
// PARAMETERS : port - port to accept clients on
// RETURNS : -
////////////////////////////////////////////////////////////////////////
TCPConnection::TCPConnection( Uint16 port ) : client(0), server(true) {
Init( NULL, port );
}
////////////////////////////////////////////////////////////////////////
// NAME : TCPConnection::~TCPConnection
// DESCRIPTION: Destroy the connection.
// PARAMETERS : -
// RETURNS : -
////////////////////////////////////////////////////////////////////////
TCPConnection::~TCPConnection( void ) {
Close();
if (socket) SDLNet_TCP_Close( socket );
}
////////////////////////////////////////////////////////////////////////
// NAME : TCPConnection::Init
// DESCRIPTION: Initialize the connection.
// PARAMETERS : ipaddr - IP address/name of server for client connection
// NULL for server connection
// port - port to acceptr clients on
// RETURNS : -
////////////////////////////////////////////////////////////////////////
int TCPConnection:Init( const char *ipaddr, Uint16 port ) {
IPaddress ip;
// create the socket
if ( !SDLNet_ResolveHost( &ip, ipaddr, port ) ) {
socket = SDLNet_TCP_Open( &ip );
if (!socket) {
printf( "SDLNet_TCP_Open: %s\n", SDLNet_GetError() );
}
} else {
printf( "SDLNet_ResolveHost: %s\n", SDLNet_GetError() );
}
}
////////////////////////////////////////////////////////////////////////
// NAME : TCPConnection::Open
// DESCRIPTION: Open the connection. For a server this means wait for
// client connection. For a client, this is almost a no-op.
// PARAMETERS : -
// RETURNS : TRUE if open succeeded, FALSE on error
////////////////////////////////////////////////////////////////////////
bool TCPConnection:Open( void ) {
bool rc = false;
if ( socket != NULL ) {
if ( server ) {
client = SDLNet_TCP_Accept( socket );
if ( client) rc = true;
else printf( "SDLNet_Accept: %s\n", SDLNet_GetError() );
} else rc = true;
}
return rc;
}
////////////////////////////////////////////////////////////////////////
// NAME : TCPConnection::Close
// DESCRIPTION: Close the connection.
// PARAMETERS : -
// RETURNS : -
////////////////////////////////////////////////////////////////////////
void TCPConnection:Close( void ) {
if (client) {
SDLNet_TCP_Close( client );
client = NULL;
}
}
////////////////////////////////////////////////////////////////////////
// NAME : TCPConnection::Send
// DESCRIPTION: Send a buffer over the network.
// PARAMETERS : buf - buffer to send
// RETURNS : TRUE if buffer was sent successfully, FALSE on error
////////////////////////////////////////////////////////////////////////
bool TCPConnection::Send( const NetBuffer &buf, Uint16 type ) {
bool rc = false;
TCPSocket dest = NULL;
if (server && (client || Open())) {
dest = client;
} else {
dest = socket;
}
if (dest) {
int len;
struct PacketHeader hdr;
hdr.id = SDL_SwapLE32(0xdeadbeef); // FIXME
hdr.type = SDL_SwapLE16(type);
hdr.version = 0;
hdr.reserved = 0;
hdr.size = SDL_SwapLE32(buf.size);
hdr.crc = SDL_SwapLE32(0); // FIXME
len = SDLNet_TCP_Send( dest, &hdr, sizeof(struct PacketHeader) );
if ( len < sizeof(struct PacketHeader) )
printf( "SDLNet_TCP_Send (header): %s\n", SDLNet_GetError() );
else
{
len = SDLNet_TCP_Send( dest, buf.GetData(), buf.Size() );
if ( len < buf.Size() )
printf( "SDLNet_TCP_Send (data): %s\n", SDLNet_GetError() );
else
rc = true;
}
}
return rc;
}
////////////////////////////////////////////////////////////////////////
// NAME : TCPConnection::Receive
// DESCRIPTION: Receive a buffer over the network. If a buffer is
// returned, it must be freed by the caller after use.
// PARAMETERS : -
// RETURNS : received buffer or NULL on error
////////////////////////////////////////////////////////////////////////
NetBuffer *TCPConnection::Receive( void ) {
NetBuffer *buf = NULL;
TCPsocket src = NULL;
if (server && (client || Open())) {
src = client;
} else {
src = socket;
}
if (src) {
struct PacketHeader hdr;
char *buf = (char *)&hdr;
int len, read = 0;
do {
len = SDLNet_TCP_Recv( src, buf, sizeof(struct PacketHeader) - read );
if ( len <= 0 ) {
printf( "SDLNet_TCP_Recv (header): %s\n", SDLNet_GetError() );
return NULL;
}
read += len;
} while (read < sizeof(struct PacketHeader));
hdr.id = SDL_SwapLE32(hdr.id);
hdr.type = SDL_SwapLE16(hdr.type);
hdr.size = SDL_SwapLE32(hdr.size);
hdr.crc = SDL_SwapLE32(hdr.crc);
if (hdr.id != 0xdeadbeef) { // FIXME
printf( "TCP_Receive: Received unknown ID %ld\n", hdr.id );
return NULL;
}
// FIXME: check crc
buf = new NetBuffer( hdr.size );
read = 0;
do {
len = SDLNet_TCP_Recv( src, buf.GetData(), hdr.size - read );
if ( len <= 0 ) {
printf( "SDLNet_TCP_Recv (data): %s\n", SDLNet_GetError() );
delete buf;
return NULL;
}
read += len;
} while (read < hdr.size);
}
return buf;
}
// Crimson Fields -- a game of tactical warfare
// Copyright (C) 2000-2006 Jens Granseuer
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
///////////////////////////////////////////////////////////////
// network.h - networking
///////////////////////////////////////////////////////////////
#ifndef _INCLUDE_NETWORK_H
#define _INCLUDE_NETWORK_H
#include <string>
#include <vector>
using namespace std;
#include "SDL_net.h"
#include "fileio.h"
class NetBuffer : public MemBuffer {
public:
NetBuffer( int size );
~NetBuffer( void );
int Size( void ) const { return size; }
void *GetData( void ) const { return buffer; }
private:
int size;
void *buffer;
}
class TCPConnection {
public:
TCPConnection( const string &server, Uint16 port );
TCPConnection( Uint16 port );
~TCPConnection( void );
bool Open( void );
void Close( void );
bool Send( const NetBuffer &buf );
NetBuffer *Receive( void );
private:
int Init( const char *ipaddr, Uint16 port );
TCPsocket socket;
TCPsocket client;
bool server;
};
#endif /* _INCLUDE_NETWORK_H */