-
-
Save roxlu/5c13f2a9ef905e115219 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <string.h> | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <rxs_streamer/rxs_stun_io.h> | |
/* --------------------------------------------------------------------------- */ | |
static void on_resolved(uv_getaddrinfo_t* resolver, int status, struct addrinfo* addr); /* gets called when the stun server domain has been resolved. */ | |
static void on_read(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags); | |
static void on_alloc(uv_handle_t* handle, size_t nbytes, uv_buf_t* buf); | |
static rxs_stun_mem* find_free_mem_block(rxs_stun_io* io); | |
/* --------------------------------------------------------------------------- */ | |
int rxs_stun_io_init(rxs_stun_io* io, const char* server, const char* port) { | |
int r; | |
int i; | |
struct addrinfo hints; | |
if (!io) { return -1; } | |
if (rxs_stun_init(&io->stun) < 0) { | |
printf("Error: cannot init stun.\n"); | |
return -2; | |
} | |
io->loop = uv_default_loop(); | |
if (!io->loop) { | |
printf("Error: cannot get uv loop.\n"); | |
return -3; | |
} | |
/* init the memory blocks */ | |
for(i = 0; i < RXS_STUN_IO_NUM_MEM_BLOCKS; ++i) { | |
io->mem[i].is_free = 0; | |
io->mem[i].io = io; | |
} | |
/* hints for resolver */ | |
hints.ai_family = AF_INET; | |
hints.ai_socktype = SOCK_DGRAM; | |
hints.ai_protocol = IPPROTO_UDP; | |
hints.ai_flags = 0; | |
/* set user data */ | |
io->resolver.data = (void*)io; | |
io->port = atoi(port); | |
r = uv_getaddrinfo(io->loop, &io->resolver, | |
on_resolved, server, port, &hints); | |
if (r != 0){ | |
printf("Error: cannot start resolving stun server. %s\n", uv_strerror(r)); | |
return -4; | |
} | |
return 0; | |
} | |
void rxs_stun_io_update(rxs_stun_io* io) { | |
#if !defined(NDEBUG) | |
if (!io) { | |
printf("Error: rxs_stun_io, cannot update; invalid io.\n"); | |
exit(1); | |
} | |
#endif | |
uv_run(io->loop, UV_RUN_NOWAIT); | |
} | |
int rxs_stun_io_clear(rxs_stun_io* io) { | |
if (!io) { return -1; } | |
if (rxs_stun_clear(&io->stun) < 0) { | |
printf("Error: cannot clear rxs_stun in rxs_stun_io.\n"); | |
return -2; | |
} | |
return 0; | |
} | |
/* --------------------------------------------------------------------------- */ | |
/* | |
Finds a free memory block in rxs_stun_io. We're using a very | |
basic memory system for now. We just have a big array with block | |
of some kb. | |
*/ | |
static rxs_stun_mem* find_free_mem_block(rxs_stun_io* io) { | |
int i; | |
if (!io) { return NULL; } | |
for (i = 0; i < RXS_STUN_IO_NUM_MEM_BLOCKS; ++i) { | |
if (io->mem[i].is_free) { | |
return &io->mem[i]; | |
} | |
} | |
return NULL; | |
} | |
/* --------------------------------------------------------------------------- */ | |
static void on_resolved(uv_getaddrinfo_t* resolver, int status, struct addrinfo* addr) { | |
int r = 0; | |
rxs_stun_io* io; | |
if(status < 0) { | |
printf("Error: Something went wrong when resolving the host in rxs_stun_io.\n"); | |
exit(1); | |
} | |
io = (rxs_stun_io*) resolver->data; | |
/* get IP */ | |
uv_ip4_name((struct sockaddr_in*)addr->ai_addr, io->ip, 16); | |
io->ip[16] = '\0'; | |
/* create our send sockaddr */ | |
r = uv_ip4_addr(io->ip, io->port, &io->saddr); | |
if (r != 0) { | |
printf("Error: cannot create ip4 addr struct. %s\n", uv_strerror(r)); | |
exit(1); | |
} | |
printf("Resolved host: %s\n", io->ip); | |
/* init UDP sock */ | |
r = uv_udp_init(io->loop, &io->sock); | |
if(r != 0) { | |
printf("Error: cannot create sock for stun io: %s\n", uv_strerror(r)); | |
exit(1); | |
} | |
/* create our receiver sockaddr; this will receive data */ | |
struct sockaddr_in raddr; | |
r = uv_ip4_addr("0.0.0.0", io->port, &raddr); | |
if (r != 0) { | |
printf("Error: cannot init ip4 addr.\n"); | |
exit(1); | |
} | |
r = uv_udp_bind(&io->sock, (const struct sockaddr*)&raddr, 0); | |
if(r < 0) { | |
printf("Error: cannot bind: %s, in rxs_stun_io\n", uv_strerror(r)); | |
exit(1); | |
} | |
/* start receiving data. */ | |
r = uv_udp_recv_start(&io->sock, on_alloc, on_read); | |
if(r < 0) { | |
printf("Error: cannot start recieving: %s\n", uv_strerror(r)); | |
} | |
/* @todo --> ready to kickoff stun */ | |
} | |
static void on_alloc(uv_handle_t* handle, size_t nbytes, uv_buf_t* buf) { | |
rxs_stun_io* io = (rxs_stun_io*) handle->data; | |
if (nbytes > RXS_STUN_IO_MEM_BLOCK_SIZE) { | |
printf("Error: rxs_stun_io needs a memory block bigger then the anticipated on.\n"); | |
exit(1); | |
} | |
rxs_stun_mem* mem = find_free_mem_block(io); | |
if (!mem) { | |
printf("Error: cannot find any new memory block for rxs_stun_io. Need to allocate more!\n"); | |
exit(1); | |
} | |
buf->base = (char*)mem->data; | |
buf->len = nbytes; | |
mem->nbytes = nbytes; | |
} | |
static void on_send(uv_udp_send_t* req, int status) { | |
printf("Send some data: %d\n", status); | |
if(status < 0) { | |
printf("Error: while sending some data in rxs_stun_io. %s\n", uv_strerror(status)); | |
exit(1); | |
} | |
/* @todo -> set memory block free */ | |
} | |
static void on_read(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags) { | |
printf("Read some data: %ld\n", nread); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment