about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorlatex <latex@disroot.org>2023-01-29 18:17:44 +0100
committerlatex <latex@disroot.org>2023-01-29 18:17:44 +0100
commit2ed3e247d3e5040eedb8a845e1d5ca8744a65436 (patch)
tree4fa8b06c12e6521b8e57e2e2b4954427bb63a585
parent00ab224d50784df9672b7947b48ef7a9f46f0066 (diff)
downloadlibumumble-2ed3e247d3e5040eedb8a845e1d5ca8744a65436.tar.gz
add mumble_connect to connect to TCP
-rw-r--r--include/libumumble.h31
-rw-r--r--src/connection.c103
-rw-r--r--src/ctx.c20
-rw-r--r--tests/test.c11
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);
 }