1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-29 01:35:06 +01:00

get basic network game working

This commit is contained in:
IntelOrca
2015-02-12 11:30:57 +00:00
committed by zsilencer
parent 7e23d2d013
commit 196e6eb675
6 changed files with 245 additions and 21 deletions

View File

@@ -20,14 +20,24 @@
#ifndef DISABLE_NETWORK
#include "../game.h"
#include "network.h"
#pragma comment(lib, "Ws2_32.lib")
int gNetworkStart = NETWORK_NONE;
char gNetworkStartHost[128];
int gNetworkStartPort = NETWORK_DEFAULT_PORT;
int gNetworkStatus = NETWORK_NONE;
static int _wsaInitialised = 0;
static WSADATA _wsaData;
static SOCKET _serverSocket;
static SOCKET _clientSocket;
static int network_get_next_packet(network_packet *outPacket);
static void network_process_packet(network_packet *packet);
int network_init()
{
if (!_wsaInitialised) {
@@ -44,15 +54,63 @@ int network_init()
void network_close()
{
if (!_wsaInitialised)
return;
if (gNetworkStatus == NETWORK_CLIENT)
network_end_client();
else if (gNetworkStatus == NETWORK_SERVER)
network_end_server();
log_verbose("Closing WSA");
WSACleanup();
_wsaInitialised = 0;
}
int network_begin_client(const char *host, int port)
{
SOCKADDR_IN serverAddress;
u_long iMode;
if (!network_init())
return 0;
_serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (_serverSocket == INVALID_SOCKET) {
log_error("Unable to create socket.");
return 0;
}
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.S_un.S_addr = inet_addr(host);
serverAddress.sin_port = htons(port);
if (connect(_serverSocket, (SOCKADDR*)&serverAddress, sizeof(SOCKADDR_IN)) != 0) {
log_error("Unable to connect to host.");
return 0;
}
iMode = 1;
if (ioctlsocket(_serverSocket, FIONBIO, &iMode) != NO_ERROR) {
closesocket(_serverSocket);
log_error("Failed to set non-blocking mode.");
}
gNetworkStatus = NETWORK_CLIENT;
return 1;
}
void network_end_client()
{
gNetworkStatus = NETWORK_NONE;
closesocket(_serverSocket);
}
int network_begin_server(int port)
{
SOCKET listeningSocket;
SOCKADDR_IN localAddress;
u_long iMode;
if (!network_init())
return 0;
@@ -65,7 +123,7 @@ int network_begin_server(int port)
}
localAddress.sin_family = AF_INET;
localAddress.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
localAddress.sin_addr.S_un.S_addr = INADDR_ANY;
localAddress.sin_port = htons(port);
if (bind(listeningSocket, (SOCKADDR*)&localAddress, sizeof(SOCKADDR_IN)) != 0) {
@@ -89,23 +147,106 @@ int network_begin_server(int port)
}
closesocket(listeningSocket);
printf("Connected to client!");
iMode = 1;
if (ioctlsocket(_clientSocket, FIONBIO, &iMode) != NO_ERROR) {
closesocket(_clientSocket);
log_error("Failed to set non-blocking mode.");
}
printf("Connected to client!\n");
gNetworkStatus = NETWORK_SERVER;
return 1;
}
void network_end_server()
{
gNetworkStatus = NETWORK_NONE;
closesocket(_clientSocket);
}
int network_send_data(uint8 *data, int length)
void network_update()
{
return send(_clientSocket, data, length, 0);
SOCKET socket;
int packetStatus;
network_packet packet;
if (gNetworkStatus == NETWORK_NONE)
return;
socket = gNetworkStatus == NETWORK_CLIENT ? _serverSocket : _clientSocket;
do {
packetStatus = network_get_next_packet(&packet);
if (packetStatus == NETWORK_DISCONNECTED) {
network_print_error();
if (gNetworkStatus == NETWORK_CLIENT) {
network_end_client();
printf("Server disconnected...\n");
return;
} else if (gNetworkStatus == NETWORK_SERVER) {
network_end_server();
printf("client disconnected...\n");
return;
}
} else if (packetStatus == NETWORK_SUCCESS) {
network_process_packet(&packet);
}
} while (packetStatus == NETWORK_SUCCESS);
}
int network_receive_data(uint8 *data, int maxLength)
static int network_get_next_packet(network_packet *outPacket)
{
return recv(_clientSocket, data, maxLength, 0);
SOCKET socket;
int readBytes;
socket = gNetworkStatus == NETWORK_CLIENT ? _serverSocket : _clientSocket;
readBytes = recv(socket, (char*)&outPacket->size, sizeof(outPacket->size), 0);
if (readBytes == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
return NETWORK_DISCONNECTED;
if (readBytes != sizeof(outPacket->size))
return NETWORK_NO_DATA;
readBytes = recv(socket, (char*)&outPacket->data, outPacket->size, 0);
if (readBytes != outPacket->size)
return NETWORK_NO_DATA;
return NETWORK_SUCCESS;
}
static void network_process_packet(network_packet *packet)
{
uint32 *args;
int command;
args = (uint32*)&packet->data;
command = args[0];
if (gNetworkStatus == NETWORK_CLIENT)
command |= (1 << 31);
game_do_command_p(command, &args[1], &args[2], &args[3], &args[4], &args[5], &args[6], &args[7]);
}
void network_send_packet(network_packet *packet)
{
SOCKET socket;
if (gNetworkStatus == NETWORK_NONE)
return;
socket = gNetworkStatus == NETWORK_CLIENT ? _serverSocket : _clientSocket;
send(socket, (char*)packet, 2 + packet->size, 0);
}
void network_print_error()
{
wchar_t *s = NULL;
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&s, 0, NULL);
fprintf(stderr, "%S\n", s);
LocalFree(s);
}
#endif /* DISABLE_NETWORK */

View File

@@ -27,15 +27,41 @@
#include "../common.h"
typedef struct {
uint16 size;
uint8 data[128];
} network_packet;
#define NETWORK_DEFAULT_PORT 11753
enum {
NETWORK_NONE,
NETWORK_CLIENT,
NETWORK_SERVER
};
enum {
NETWORK_SUCCESS,
NETWORK_NO_DATA,
NETWORK_DISCONNECTED
};
extern int gNetworkStart;
extern char gNetworkStartHost[128];
extern int gNetworkStartPort;
extern int gNetworkStatus;
int network_init();
void network_close();
int network_begin_client(const char *host, int port);
void network_end_client();
int network_begin_server(int port);
void network_end_server();
int network_send_data(uint8 *data, int length);
int network_receive_data(uint8 *data, int maxLength);
void network_update();
void network_send_packet(network_packet *packet);
void network_print_error();
#endif /* DISABLE_NETWORK */