ref: f7f82be5007aa3f59409095c64c35c4cb1a10bd7
dir: /src/net_loop.c/
//
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// Loopback network module for server compiled into the client
//
#include <stdio.h>
#include <stdlib.h>
#include "doomtype.h"
#include "i_system.h"
#include "m_misc.h"
#include "net_defs.h"
#include "net_loop.h"
#include "net_packet.h"
#define MAX_QUEUE_SIZE 16
typedef struct
{
net_packet_t *packets[MAX_QUEUE_SIZE];
int head, tail;
} packet_queue_t;
static packet_queue_t client_queue;
static packet_queue_t server_queue;
static net_addr_t client_addr;
static net_addr_t server_addr;
static void QueueInit(packet_queue_t *queue)
{
queue->head = queue->tail = 0;
}
static void QueuePush(packet_queue_t *queue, net_packet_t *packet)
{
int new_tail;
new_tail = (queue->tail + 1) % MAX_QUEUE_SIZE;
if (new_tail == queue->head)
{
// queue is full
return;
}
queue->packets[queue->tail] = packet;
queue->tail = new_tail;
}
static net_packet_t *QueuePop(packet_queue_t *queue)
{
net_packet_t *packet;
if (queue->tail == queue->head)
{
// queue empty
return NULL;
}
packet = queue->packets[queue->head];
queue->head = (queue->head + 1) % MAX_QUEUE_SIZE;
return packet;
}
//-----------------------------------------------------------------------------
//
// Client end code
//
//-----------------------------------------------------------------------------
static boolean NET_CL_InitClient(void)
{
QueueInit(&client_queue);
return true;
}
static boolean NET_CL_InitServer(void)
{
I_Error("NET_CL_InitServer: attempted to initialize client pipe end as a server!");
return false;
}
static void NET_CL_SendPacket(net_addr_t *addr, net_packet_t *packet)
{
QueuePush(&server_queue, NET_PacketDup(packet));
}
static boolean NET_CL_RecvPacket(net_addr_t **addr, net_packet_t **packet)
{
net_packet_t *popped;
popped = QueuePop(&client_queue);
if (popped != NULL)
{
*packet = popped;
*addr = &client_addr;
client_addr.module = &net_loop_client_module;
return true;
}
return false;
}
static void NET_CL_AddrToString(net_addr_t *addr, char *buffer, int buffer_len)
{
M_snprintf(buffer, buffer_len, "local server");
}
static void NET_CL_FreeAddress(net_addr_t *addr)
{
}
static net_addr_t *NET_CL_ResolveAddress(char *address)
{
if (address == NULL)
{
client_addr.module = &net_loop_client_module;
return &client_addr;
}
else
{
return NULL;
}
}
net_module_t net_loop_client_module =
{
NET_CL_InitClient,
NET_CL_InitServer,
NET_CL_SendPacket,
NET_CL_RecvPacket,
NET_CL_AddrToString,
NET_CL_FreeAddress,
NET_CL_ResolveAddress,
};
//-----------------------------------------------------------------------------
//
// Server end code
//
//-----------------------------------------------------------------------------
static boolean NET_SV_InitClient(void)
{
I_Error("NET_SV_InitClient: attempted to initialize server pipe end as a client!");
return false;
}
static boolean NET_SV_InitServer(void)
{
QueueInit(&server_queue);
return true;
}
static void NET_SV_SendPacket(net_addr_t *addr, net_packet_t *packet)
{
QueuePush(&client_queue, NET_PacketDup(packet));
}
static boolean NET_SV_RecvPacket(net_addr_t **addr, net_packet_t **packet)
{
net_packet_t *popped;
popped = QueuePop(&server_queue);
if (popped != NULL)
{
*packet = popped;
*addr = &server_addr;
server_addr.module = &net_loop_server_module;
return true;
}
return false;
}
static void NET_SV_AddrToString(net_addr_t *addr, char *buffer, int buffer_len)
{
M_snprintf(buffer, buffer_len, "local client");
}
static void NET_SV_FreeAddress(net_addr_t *addr)
{
}
static net_addr_t *NET_SV_ResolveAddress(char *address)
{
if (address == NULL)
{
server_addr.module = &net_loop_server_module;
return &server_addr;
}
else
{
return NULL;
}
}
net_module_t net_loop_server_module =
{
NET_SV_InitClient,
NET_SV_InitServer,
NET_SV_SendPacket,
NET_SV_RecvPacket,
NET_SV_AddrToString,
NET_SV_FreeAddress,
NET_SV_ResolveAddress,
};