RNZJGWTBAY5JIEQP7E3VMAQBZCNJ2BA6Z3F2YDDBLKOAWE5AUI4QC
*(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr;
a->port = ((struct sockaddr_in *)s)->sin_port;
// } else if(s->sa_family == AF_IPX) {
// a->type = NA_IPX;
// memcpy(&a->ipx[0], ((struct sockaddr_ipx *)s)->sa_netnum, 4);
// memcpy(&a->ipx[4], ((struct sockaddr_ipx *)s)->sa_nodenum, 6);
// a->port = ((struct sockaddr_ipx *)s)->sa_socket;
*(uint32_t *)&a->ip = in->sin_addr.s_addr;
a->port = in->sin_port;
static void NetadrToSockadr(const netadr_t *a, struct sockaddr *s) {
alias_memory_clear(s, sizeof(s));
struct sockaddr_in * in = (struct sockaddr_in *)s;
in->sin_family = AF_INET;
in->sin_port = a->port;
in->sin_addr.s_addr = (a->type == NA_BROADCAST) ? INADDR_BROADCAST : *(uint32_t *)&a->ip;
}
void NET_Sleep(int msec) {
#define NET__MAILBOX_SIZE__LOG2 4
#define NET__MAILBOX_SIZE (1 << NET__MAILBOX_SIZE__LOG2)
struct NET_MailboxMessage {
byte data[MAX_MSGLEN];
uint32_t length;
netadr_t from;
};
struct NET_Mailbox {
struct NET_MailboxMessage messages[NET__MAILBOX_SIZE];
uint32_t get;
uint32_t send;
};
static bool NET_Mailbox__get(struct NET_Mailbox *mailbox, netadr_t *from, sizebuf_t *message) {
if(mailbox->send - mailbox->get > NET__MAILBOX_SIZE) {
mailbox->get = mailbox->send - NET__MAILBOX_SIZE;
}
if(mailbox->get >= mailbox->send) {
return false;
}
uint32_t index = mailbox->get & (NET__MAILBOX_SIZE - 1);
mailbox->get++;
alias_memory_copy(message->data, message->maxsize, mailbox->messages[index].data, mailbox->messages[index].length);
message->cursize = mailbox->messages[index].length;
*from = mailbox->messages[index].from;
return true;
}
static void NET_Mailbox__send(struct NET_Mailbox *mailbox, const void * data, uint32_t length, netadr_t from) {
uint32_t index = mailbox->send & (NET__MAILBOX_SIZE - 1);
mailbox->send++;
alias_memory_copy(mailbox->messages[index].data, sizeof(mailbox->messages[index].data), data, length);
mailbox->messages[index].length = length;
mailbox->messages[index].from = from;
}
static struct NET_Mailbox net__mailboxes[NETSRC_COUNT];
static uv_udp_t net__udp_handles[NETSRC_COUNT];
bool NET_GetPacket(netsrc_t sock, netadr_t *from, sizebuf_t *message) {
struct NET_Mailbox *mailbox = &net__mailboxes[sock];
return NET_Mailbox__get(mailbox, from, message);
bool NET_GetPacket(netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message) {
return false;
static void NET__udp_send_cb(uv_udp_send_t* req, int status) {
// TODO
alias_free(NULL, req, sizeof(*req), alignof(*req));
}
static void net__udp_recv_alloc_cb(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
buf->base = alias_malloc(NULL, suggested_size, 1);
buf->len = suggested_size;
if(to.type == NA_LOOPBACK) {
NET_Mailbox__send(&net__mailboxes[!sock], data, length, to);
}
uv_udp_t *handle = &net__udp_handles[sock];
struct sockaddr address;
NetadrToSockadr(&to, &address);
uv_udp_send_t *req = alias_malloc(NULL, sizeof(*req), alignof(*req));
uv_buf_t buf = uv_buf_init(data, length);
int err = uv_udp_send(req, handle, &buf, 1, &address, NET__udp_send_cb);
if(err != 0) {
// TODO
}
}
void NET_Sleep(int msec) {
}
static const char * net__get_ip(void) {
cvar_t *ip = Cvar_Get("ip", "localhost", CVAR_NOSET);
return ip->string;
}
#define TO_STRING(X) TO_STRING__0(X)
#define TO_STRING__0(X) TO_STRING__1(X)
#define TO_STRING__1(X) #X
static int net__get_server_port(void) {
int port = Cvar_Get("ip_hostport", "0", CVAR_NOSET)->value;
if(port != 0) {
return port;
}
port = Cvar_Get("hostport", "0", CVAR_NOSET)->value;
if(port != 0) {
return port;
}
return Cvar_Get("port", TO_STRING(PORT_SERVER), CVAR_NOSET)->value;
static int net__get_client_port(void) {
int port = Cvar_Get("ip_clientport", "0", CVAR_NOSET)->value;
if(port != 0) {
return port;
}
return Cvar_Get("clientport", TO_STRING(CLIENT_SERVER), CVAR_NOSET)->value;
}
static bool net__start_udp(uv_udp_t *handle, struct NET_Mailbox *mailbox, const char *ip, int port) {
int err;
if((err = uv_udp_init(global_uv_loop(), handle)) != 0) {
return false;
}
uv_handle_set_data((uv_handle_t *)handle, mailbox);
if((err = uv_udp_set_broadcast(handle, 1)) != 0) {
return false;
}
struct sockaddr_in address;
if(!ip || !ip[0] || !strcmp(ip, "localhost")) {
address.sin_addr.s_addr = INADDR_ANY;
} else {
NET_StringToSockaddr(ip, (struct sockaddr *)&address);
}
if(port == PORT_ANY) {
address.sin_port = 0;
} else {
address.sin_port = htons((short)port);
}
address.sin_family = AF_INET;
if((err = uv_udp_bind(handle, (const struct sockaddr *)&address, 0)) != 0) {
return false;
}
if((err = uv_udp_recv_start(handle, net__udp_recv_alloc_cb, net__udp_recv_cb)) != 0) {
return false;
}
return true;
}
static bool net__activate_udp(void) {
const char * ip = net__get_ip();
int port = net__get_server_port();
if(!net__start_udp(&net__udp_handles[NS_SERVER], &net__mailboxes[NS_SERVER], ip, port)) {
return false;
}
if(Cvar_VariableValue("dedicated")) {
return true;
}
port = net__get_client_port();
if(!net__start_udp(&net__udp_handles[NS_CLIENT], &net__mailboxes[NS_CLIENT], ip, port)) {
if(!net__start_udp(&net__udp_handles[NS_CLIENT], &net__mailboxes[NS_CLIENT], ip, PORT_ANY)) {
return false;
}
}
return true;
}
static void net__deactivate_udp(void) {
}
void NET_Config(bool active) {
static bool is_active = false;
if(active == is_active) {
return;
}
if(active) {
net__activate_udp();
} else {
net__deactivate_udp();
}
}