diff options
Diffstat (limited to 'src/engine/e_network_client.c')
| -rw-r--r-- | src/engine/e_network_client.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/src/engine/e_network_client.c b/src/engine/e_network_client.c new file mode 100644 index 00000000..df7e4c26 --- /dev/null +++ b/src/engine/e_network_client.c @@ -0,0 +1,148 @@ +#include <base/system.h> +#include "e_network.h" +#include "e_network_internal.h" + +struct NETCLIENT +{ + NETADDR server_addr; + NETSOCKET socket; + + NETRECVINFO recv; + NETCONNECTION conn; +}; + +NETCLIENT *netclient_open(NETADDR bindaddr, int flags) +{ + NETCLIENT *client = (NETCLIENT *)mem_alloc(sizeof(NETCLIENT), 1); + mem_zero(client, sizeof(NETCLIENT)); + client->socket = net_udp_create(bindaddr); + conn_init(&client->conn, client->socket); + return client; +} + +int netclient_close(NETCLIENT *c) +{ + /* TODO: implement me */ + return 0; +} + + +int netclient_disconnect(NETCLIENT *c, const char *reason) +{ + dbg_msg("netclient", "disconnected. reason=\"%s\"", reason); + conn_disconnect(&c->conn, reason); + return 0; +} + +int netclient_update(NETCLIENT *c) +{ + conn_update(&c->conn); + if(c->conn.state == NET_CONNSTATE_ERROR) + netclient_disconnect(c, conn_error(&c->conn)); + return 0; +} + +int netclient_connect(NETCLIENT *c, NETADDR *addr) +{ + conn_connect(&c->conn, addr); + return 0; +} + +int netclient_recv(NETCLIENT *c, NETCHUNK *chunk) +{ + while(1) + { + NETADDR addr; + int bytes; + + /* check for a chunk */ + if(recvinfo_fetch_chunk(&c->recv, chunk)) + return 1; + + /* TODO: empty the recvinfo */ + bytes = net_udp_recv(c->socket, &addr, c->recv.buffer, NET_MAX_PACKETSIZE); + + /* no more packets for now */ + if(bytes <= 0) + break; + + if(unpack_packet(c->recv.buffer, bytes, &c->recv.data) == 0) + { + if(c->recv.data.flags&NET_PACKETFLAG_CONNLESS) + { + chunk->flags = NETSENDFLAG_CONNLESS; + chunk->client_id = -1; + chunk->address = addr; + chunk->data_size = c->recv.data.data_size; + chunk->data = c->recv.data.chunk_data; + return 1; + } + else + { + if(conn_feed(&c->conn, &c->recv.data, &addr)) + recvinfo_start(&c->recv, &addr, &c->conn, 0); + } + } + } + return 0; +} + +int netclient_send(NETCLIENT *c, NETCHUNK *chunk) +{ + if(chunk->data_size >= NET_MAX_PAYLOAD) + { + dbg_msg("netclient", "chunk payload too big. %d. dropping chunk", chunk->data_size); + return -1; + } + + if(chunk->flags&NETSENDFLAG_CONNLESS) + { + /* send connectionless packet */ + send_packet_connless(c->socket, &chunk->address, chunk->data, chunk->data_size); + } + else + { + int f = 0; + dbg_assert(chunk->client_id == 0, "errornous client id"); + + if(chunk->flags&NETSENDFLAG_VITAL) + f = NET_CHUNKFLAG_VITAL; + + conn_queue_chunk(&c->conn, f, chunk->data_size, chunk->data); + + if(chunk->flags&NETSENDFLAG_FLUSH) + conn_flush(&c->conn); + } + return 0; +} + +int netclient_state(NETCLIENT *c) +{ + if(c->conn.state == NET_CONNSTATE_ONLINE) + return NETSTATE_ONLINE; + if(c->conn.state == NET_CONNSTATE_OFFLINE) + return NETSTATE_OFFLINE; + return NETSTATE_CONNECTING; +} + +int netclient_flush(NETCLIENT *c) +{ + return conn_flush(&c->conn); +} + +int netclient_gotproblems(NETCLIENT *c) +{ + if(time_get() - c->conn.last_recv_time > time_freq()) + return 1; + return 0; +} + +void netclient_stats(NETCLIENT *c, NETSTATS *stats) +{ + *stats = c->conn.stats; +} + +const char *netclient_error_string(NETCLIENT *c) +{ + return conn_error(&c->conn); +} |