diff options
author | xengineering <me@xengineering.eu> | 2022-08-20 17:52:16 +0200 |
---|---|---|
committer | xengineering <me@xengineering.eu> | 2022-08-20 17:52:16 +0200 |
commit | 4e61f83b432350303aee5635e98d3bc147e8fffa (patch) | |
tree | 4ac40e73bbdc648b4cafefd4917df6cd6d1a5983 /net.c | |
parent | b661cc4bde4004f4d7085716680969f4659222a1 (diff) | |
download | limox-4e61f83b432350303aee5635e98d3bc147e8fffa.tar limox-4e61f83b432350303aee5635e98d3bc147e8fffa.tar.zst limox-4e61f83b432350303aee5635e98d3bc147e8fffa.zip |
Rename limox.{c,h} to net.{c,h}
Diffstat (limited to 'net.c')
-rw-r--r-- | net.c | 217 |
1 files changed, 217 insertions, 0 deletions
@@ -0,0 +1,217 @@ + + +#include <time.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <signal.h> + +#include <strophe.h> + +#include <gui.h> +#include <net.h> +#include <data.h> + + +// the state of net +typedef enum { + DISCONNECTED, // initial state + CONNECTING, // connection was requested but is not yet established + CONNECTED, // there is an active XMPP connetion to the server + SUSPENDED // not connected, but there is an open XMPP stream to be + // reconnected (see XEP-0198 for details) +} net_state_t; + + +// these variables stay initialized for the whole runtime +static net_state_t state; +static xmpp_log_t* log; +static xmpp_ctx_t* ctx; + +// these variables stay initialized while the application is not disconnected +static xmpp_conn_t* conn; +static long flags; + +// this variable stays initialized while the connection is suspended +static xmpp_sm_state_t* sm_state; + + +static int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, + void *userdata) { + + xmpp_stanza_t* body = xmpp_stanza_get_child_by_name(stanza, "body"); + if (body == NULL) { + printf("DEBUG: Got message stanza of type char without body!\n"); + return 1; + } + + const char* content = xmpp_stanza_get_text(body); + const char* sender = xmpp_stanza_get_from(stanza); + + data_add_incoming_message(sender, content); + + return 1; +} + +static int roster_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, + void *userdata) { + + // iterate over roster result + xmpp_stanza_t* query = xmpp_stanza_get_child_by_name(stanza, "query"); + for (xmpp_stanza_t* item = xmpp_stanza_get_children(query); item; + item = xmpp_stanza_get_next(item)) { + + data_add_roster_item(xmpp_stanza_get_attribute(item, "jid"), + xmpp_stanza_get_attribute(item, "subscription"), + xmpp_stanza_get_attribute(item, "name")); + } + + return 1; +} + +static void conn_handler(xmpp_conn_t *conn, xmpp_conn_event_t status,int error, + xmpp_stream_error_t *stream_error, void *userdata) { + + switch (status) { + + case XMPP_CONN_CONNECT: + printf("DEBUG: Got XMPP_CONN_CONNECT\n"); + + // add handler for <message> stanzas + xmpp_handler_add(conn, message_handler, NULL, "message", "chat", + NULL); + + // add handler for roster response + xmpp_handler_add(conn, roster_handler, "jabber:iq:roster", "iq", + "result", NULL); + + // send initial presence + xmpp_stanza_t* presence; + presence = xmpp_presence_new(ctx); + xmpp_send(conn, presence); + xmpp_stanza_release(presence); + + // send roster request + xmpp_stanza_t* iq = xmpp_iq_new(ctx, "get", "initial_roster"); + xmpp_stanza_t* query = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(query, "query"); + xmpp_stanza_set_ns(query, XMPP_NS_ROSTER); + xmpp_stanza_add_child(iq, query); + xmpp_stanza_release(query); + xmpp_send(conn, iq); + xmpp_stanza_release(iq); + + break; + + case XMPP_CONN_RAW_CONNECT: + printf("DEBUG: Got XMPP_CONN_RAW_CONNECT\n"); + break; + + case XMPP_CONN_DISCONNECT: + printf("DEBUG: Got XMPP_CONN_DISCONNECT\n"); + break; + + case XMPP_CONN_FAIL: + printf("DEBUG: Got XMPP_CONN_FAIL\n"); + break; + + default: + printf("DEBUG: Got unknown connection status '%d'!\n", status); + exit(1); + } +} + +void net_init(void) { + + printf("net_init()\n"); + + xmpp_initialize(); + log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG); // or NULL for silence + ctx = xmpp_ctx_new(NULL, log); + + state = DISCONNECTED; + +} + +static void delay(unsigned long int micros) { + + unsigned long int now = clock(); + while ((clock() - now) < micros) {} + +} + +void net_run_once(void) { + + if (state == CONNECTING) { + if (xmpp_connect_client(conn, NULL, 0, conn_handler, NULL) + == XMPP_EOK) { + state = CONNECTED; + } else { + net_disconnect(); + } + } + + if (state != DISCONNECTED) { + xmpp_run_once(ctx, 200); + } + + // TODO This delay is useless. But without it this function gets only + // called once by GTK. This could be a GTK bug. + delay(10000); + +} + +void net_quit(void) { + + printf("net_quit()\n"); + + net_disconnect(); + // TODO is it possible to free xmpp_log_t ? + log = NULL; + xmpp_ctx_free(ctx); + xmpp_shutdown(); + +} + +void net_connect(const char* jid, const char* password) { + + printf("net_connect()\n"); + + conn = xmpp_conn_new(ctx); + + flags = 0; + flags |= XMPP_CONN_FLAG_MANDATORY_TLS; + xmpp_conn_set_flags(conn, flags); + + xmpp_conn_set_jid(conn, jid); + xmpp_conn_set_pass(conn, password); + + state = CONNECTING; + +} + +void net_disconnect(void) { + + printf("net_disconnect()\n"); + + if (sm_state) { + xmpp_free_sm_state(sm_state); + sm_state = NULL; + } + + if (conn != NULL && xmpp_conn_is_connected(conn)) { + xmpp_disconnect(conn); + while (xmpp_conn_is_connected(conn)) { + xmpp_run_once(ctx, 200); // TODO avoid with additional + // state "disconnecting" + } + if (!xmpp_conn_release(conn)) { + printf("DEBUG: Could not free connection!\n"); + } + } + + flags = 0; + state = DISCONNECTED; + +} |