diff options
-rw-r--r-- | include/libumumble.h | 31 | ||||
-rw-r--r-- | src/connection.c | 103 | ||||
-rw-r--r-- | src/ctx.c | 20 | ||||
-rw-r--r-- | tests/test.c | 11 |
4 files changed, 151 insertions, 14 deletions
diff --git a/include/libumumble.h b/include/libumumble.h index 3a66099..7bd03b3 100644 --- a/include/libumumble.h +++ b/include/libumumble.h @@ -7,25 +7,42 @@ extern "C" { #include <uv.h> +enum mumble_ctx_status { + UNINITIALIZED = 0, + READY, + CONNECTING, + CONNECTED, + DISCONNECTED +}; + typedef struct mumble_ctx { + enum mumble_ctx_status status; + int error; uv_loop_t uv_loop; + uv_getaddrinfo_t uv_resolver; + uv_connect_t uv_connect_req; + uv_tcp_t uv_tcp_socket; } mumble_ctx_t; /* Initializes a mumble context object. * This function will allocate initial memory needed for storing e.g. the channel layout. - * Make sure to call mumble_free_ctx() when you're done! + * Make sure to call mumble_ctx_close() when you're done! * - * \param ctx pointer to the context object to initialize. + * \param ctx pointer to the context object to initialize * \return int indicating success * \retval 1 error */ -int mumble_init_ctx(mumble_ctx_t *ctx); +int mumble_ctx_init(mumble_ctx_t *ctx); -/* Free a mumble context. +/* Closes a mumble context, deallocating internal objects used by the context. + * This function does not free the memory possibly used to allocate the ctx object. + * If you stored ctx in dynamic memory, make sure to call free(ctx) after calling this function. * - * \param ctx pointer to the context object to free. - */ -void mumble_free_ctx(mumble_ctx_t *ctx); + * \param ctx pointer to the context object to close +*/ +void mumble_ctx_close(mumble_ctx_t *ctx); + +int mumble_connect(mumble_ctx_t *ctx, const char *address, const unsigned short port); #ifdef __cplusplus } diff --git a/src/connection.c b/src/connection.c new file mode 100644 index 0000000..9d64a64 --- /dev/null +++ b/src/connection.c @@ -0,0 +1,103 @@ +#include <stdlib.h> +#include <assert.h> + +#include <libumumble.h> +#include <uv.h> +#include "Mumble.pb.h" + +void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) { + buf->base = malloc(suggested_size); + assert(buf->base != NULL); + if (buf->base == NULL) + return; + buf->len = suggested_size; +} + +void on_read_cb(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) +{ + mumble_ctx_t *ctx = client->data; + + if (nread < 0) { + if (nread != UV_EOF) { + ctx->error = nread; + ctx->status = DISCONNECTED; + } + uv_close((uv_handle_t*) client, NULL); + ctx->status = DISCONNECTED; + free(buf->base); + free(client); + return; + } + + char *data = (char*) malloc(sizeof(char) * (nread+1)); + data[nread] = '\0'; + strncpy(data, buf->base, nread); + + printf("%s", data); + free(data); + free(buf->base); +} + +void on_connect_cb(uv_connect_t *req, int status) +{ + mumble_ctx_t *ctx = req->data; + req->handle->data = ctx; + + printf("Koekje: %d %s\n", status, uv_strerror(status)); + assert(status >= 0); + if (status < 0) { + ctx->error = status; + ctx->status = DISCONNECTED; + return; + } + ctx->status = CONNECTED; + + uv_read_start(req->handle, alloc_buffer, on_read_cb); +} + +void on_resolve_cb(uv_getaddrinfo_t *resolver, int status, struct addrinfo *res) +{ + mumble_ctx_t *ctx = resolver->data; + + printf("bruh momento %d", status); + assert(status >= 0); + if (status < 0) { + ctx->error = status; + ctx->status = DISCONNECTED; + return; + } + + uv_tcp_init(&ctx->uv_loop, &ctx->uv_tcp_socket); + uv_tcp_connect(&ctx->uv_connect_req, &ctx->uv_tcp_socket, + (const struct sockaddr*) res->ai_addr, on_connect_cb); + + uv_freeaddrinfo(res); +} + +int mumble_connect(mumble_ctx_t *ctx, const char *address, unsigned short port) +{ + if (port == 0) + port = 64738; + + struct addrinfo hints; + hints.ai_family = PF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_flags = 0; + + /* convert port to char array */ + char service[6] = { 0 }; + snprintf(service, sizeof(service), "%hu", port); + + int result = uv_getaddrinfo(&ctx->uv_loop, &ctx->uv_resolver, + on_resolve_cb, address, service, &hints); + assert(result == 0); + if (result != 0) { + ctx->error = result; + return result; + } + + ctx->status = CONNECTING; + uv_run(&ctx->uv_loop, UV_RUN_DEFAULT); + return 0; +} diff --git a/src/ctx.c b/src/ctx.c index 0d7651a..35864d1 100644 --- a/src/ctx.c +++ b/src/ctx.c @@ -1,15 +1,29 @@ +#include <assert.h> +#include <string.h> + #include <libumumble.h> #include <uv.h> -int mumble_init_ctx(mumble_ctx_t *ctx) +int mumble_ctx_init(mumble_ctx_t *ctx) { int result; + memset(ctx, 0, sizeof(mumble_ctx_t)); result = uv_loop_init(&ctx->uv_loop); - return result; + assert(result == 0); + if (result != 0) + return result; + + ctx->uv_loop.data = ctx; + ctx->uv_resolver.data = ctx; + ctx->uv_connect_req.data = ctx; + ctx->uv_tcp_socket.data = ctx; + + ctx->status = READY; + return 0; } -void mumble_free_ctx(mumble_ctx_t *ctx) +void mumble_ctx_close(mumble_ctx_t *ctx) { uv_loop_close(&ctx->uv_loop); } diff --git a/tests/test.c b/tests/test.c index d96167c..fc55e90 100644 --- a/tests/test.c +++ b/tests/test.c @@ -3,9 +3,12 @@ int main(int argc, char *argv[]) { mumble_ctx_t ctx; - printf("%ld\n", ctx.uv_loop.time); - mumble_init_ctx(&ctx); - printf("%ld\n", ctx.uv_loop.time); - mumble_free_ctx(&ctx); + printf("%d\n", ctx.status); + mumble_ctx_init(&ctx); + printf("%d\n", ctx.status); + + mumble_connect(&ctx, "127.0.0.1", 0); + + mumble_ctx_close(&ctx); printf("%ld\n", ctx.uv_loop.time); } |