diff --git a/src/server/httpapi.c b/src/server/httpapi.c index 96b3dc5..0bbe68d 100644 --- a/src/server/httpapi.c +++ b/src/server/httpapi.c @@ -86,16 +86,19 @@ send_response(struct MHD_Connection* conn, const char* body, int status_code) response = MHD_create_response_from_data(0, NULL, MHD_NO, MHD_YES); } - if (!response) + if (!response) { return MHD_NO; + } int ret = MHD_queue_response(conn, status_code, response); MHD_destroy_response(response); + return ret; } -int connection_cb(void* cls, struct MHD_Connection* conn, const char* url, const char* method, - const char* version, const char* data, size_t* size, void** con_cls) +int +connection_cb(void* cls, struct MHD_Connection* conn, const char* url, const char* method, const char* version, + const char* data, size_t* size, void** con_cls) { #ifdef PLATFORM_OSX pthread_setname_np("http"); @@ -129,55 +132,49 @@ int connection_cb(void* cls, struct MHD_Connection* conn, const char* url, const *size = 0; return MHD_YES; - } else { - const char *id = NULL; - const char *query = NULL; + } - switch (con_info->stbbr_op) { - case STBBR_OP_SEND: - { - server_send(con_info->body->str); - return send_response(conn, NULL, MHD_HTTP_OK); - } - case STBBR_OP_FOR: - { - id = MHD_lookup_connection_value(conn, MHD_GET_ARGUMENT_KIND, "id"); - query = MHD_lookup_connection_value(conn, MHD_GET_ARGUMENT_KIND, "query"); - if (id && query) { - return send_response(conn, NULL, MHD_HTTP_BAD_REQUEST); - } + const char *id = NULL; + const char *query = NULL; + int res = 0; - if (id) { - prime_for_id(id, con_info->body->str); - return send_response(conn, NULL, MHD_HTTP_CREATED); - } - - if (query) { - prime_for_query(query, con_info->body->str); - return send_response(conn, NULL, MHD_HTTP_CREATED); - } + switch (con_info->stbbr_op) { + case STBBR_OP_SEND: + server_send(con_info->body->str); + return send_response(conn, NULL, MHD_HTTP_OK); + case STBBR_OP_FOR: + id = MHD_lookup_connection_value(conn, MHD_GET_ARGUMENT_KIND, "id"); + query = MHD_lookup_connection_value(conn, MHD_GET_ARGUMENT_KIND, "query"); + if (id && query) { return send_response(conn, NULL, MHD_HTTP_BAD_REQUEST); } - case STBBR_OP_VERIFY: - { - int res = verify_any(con_info->body->str, TRUE); - if (res) { - return send_response(conn, "true", MHD_HTTP_OK); - } else { - return send_response(conn, "false", MHD_HTTP_OK); - } + + if (id) { + prime_for_id(id, con_info->body->str); + return send_response(conn, NULL, MHD_HTTP_CREATED); } - default: - { - return send_response(conn, NULL, MHD_HTTP_BAD_REQUEST); + + if (query) { + prime_for_query(query, con_info->body->str); + return send_response(conn, NULL, MHD_HTTP_CREATED); } - } + + return send_response(conn, NULL, MHD_HTTP_BAD_REQUEST); + case STBBR_OP_VERIFY: + res = verify_any(con_info->body->str, TRUE); + if (res) { + return send_response(conn, "true", MHD_HTTP_OK); + } else { + return send_response(conn, "false", MHD_HTTP_OK); + } + default: + return send_response(conn, NULL, MHD_HTTP_BAD_REQUEST); } } -void request_completed(void* cls, struct MHD_Connection* conn, - void** con_cls, enum MHD_RequestTerminationCode termcode) +void +request_completed(void* cls, struct MHD_Connection* conn, void** con_cls, enum MHD_RequestTerminationCode termcode) { ConnectionInfo *con_info = (ConnectionInfo*) *con_cls; if (con_info) { diff --git a/src/server/log.c b/src/server/log.c index 80d58a0..8b017a6 100644 --- a/src/server/log.c +++ b/src/server/log.c @@ -41,75 +41,11 @@ static gboolean logready = FALSE; static stbbr_log_t minlevel; pthread_mutex_t loglock; -gchar * -_xdg_get_data_home(void) -{ - gchar *xdg_data_home = getenv("XDG_DATA_HOME"); - if (xdg_data_home) - g_strstrip(xdg_data_home); - - if (xdg_data_home && (strcmp(xdg_data_home, "") != 0)) { - return strdup(xdg_data_home); - } else { - GString *default_path = g_string_new(getenv("HOME")); - g_string_append(default_path, "/.local/share"); - gchar *result = strdup(default_path->str); - g_string_free(default_path, TRUE); - - return result; - } -} - -static gchar * -_get_main_log_file(void) -{ - gchar *xdg_data = _xdg_get_data_home(); - GString *logfile = g_string_new(xdg_data); - g_string_append(logfile, "/stabber/logs/stabber"); - g_string_append(logfile, ".log"); - gchar *result = strdup(logfile->str); - free(xdg_data); - g_string_free(logfile, TRUE); - - return result; -} - -gboolean -_create_dir(char *name) -{ - struct stat sb; - if (stat(name, &sb) != 0) { - if (errno != ENOENT || mkdir(name, S_IRWXU) != 0) { - return FALSE; - } - } else { - if ((sb.st_mode & S_IFDIR) != S_IFDIR) { - return FALSE; - } - } - - return TRUE; -} - -gboolean -_mkdir_recursive(const char *dir) -{ - int i; - gboolean result = TRUE; - - for (i = 1; i <= strlen(dir); i++) { - if (dir[i] == '/' || dir[i] == '\0') { - gchar *next_dir = g_strndup(dir, i); - result = _create_dir(next_dir); - g_free(next_dir); - if (!result) { - break; - } - } - } - - return result; -} +static gchar* _xdg_get_data_home(void); +static gchar* _get_main_log_file(void); +static gboolean _create_dir(char *name); +static gboolean _mkdir_recursive(const char *dir); +static char* _levelstr(stbbr_log_t loglevel); void log_init(stbbr_log_t loglevel) @@ -131,49 +67,39 @@ log_init(stbbr_log_t loglevel) pthread_mutex_unlock(&loglock); } -static char* -_levelstr(stbbr_log_t loglevel) -{ - switch (loglevel) { - case STBBR_LOGERROR: return "ERR"; - case STBBR_LOGWARN: return "WRN"; - case STBBR_LOGINFO: return "INF"; - case STBBR_LOGDEBUG: return "DBG"; - default: return ""; - } -} - void log_println(stbbr_log_t loglevel, const char * const msg, ...) { - if (logready && loglevel >= minlevel) { - pthread_mutex_lock(&loglock); - va_list arg; - va_start(arg, msg); - GString *fmt_msg = g_string_new(NULL); - g_string_vprintf(fmt_msg, msg, arg); - GTimeZone *tz = g_time_zone_new_local(); - GDateTime *dt = g_date_time_new_now(tz); - gchar *date_fmt = g_date_time_format(dt, "%d/%m/%Y %H:%M:%S"); - char thr_name[16]; + if (!logready || loglevel < minlevel) { + return; + } + + pthread_mutex_lock(&loglock); + va_list arg; + va_start(arg, msg); + GString *fmt_msg = g_string_new(NULL); + g_string_vprintf(fmt_msg, msg, arg); + GTimeZone *tz = g_time_zone_new_local(); + GDateTime *dt = g_date_time_new_now(tz); + gchar *date_fmt = g_date_time_format(dt, "%d/%m/%Y %H:%M:%S"); + char thr_name[16]; #ifdef PLATFORM_OSX - pthread_t self = pthread_self(); - pthread_getname_np(self, thr_name, 16); + pthread_t self = pthread_self(); + pthread_getname_np(self, thr_name, 16); #else - prctl(PR_GET_NAME, thr_name); + prctl(PR_GET_NAME, thr_name); #endif - char *levelstr = _levelstr(loglevel); - fprintf(logp, "%s: [%s] [%s] %s\n", date_fmt, thr_name, levelstr, fmt_msg->str); - g_date_time_unref(dt); - g_time_zone_unref(tz); - fflush(logp); - g_free(date_fmt); - g_string_free(fmt_msg, TRUE); - va_end(arg); - pthread_mutex_unlock(&loglock); - } + char *levelstr = _levelstr(loglevel); + fprintf(logp, "%s: [%s] [%s] %s\n", date_fmt, thr_name, levelstr, fmt_msg->str); + g_date_time_unref(dt); + g_time_zone_unref(tz); + fflush(logp); + g_free(date_fmt); + g_string_free(fmt_msg, TRUE); + va_end(arg); + pthread_mutex_unlock(&loglock); } void @@ -186,3 +112,86 @@ log_close(void) logready = FALSE; pthread_mutex_unlock(&loglock); } + +static gchar* +_xdg_get_data_home(void) +{ + gchar *xdg_data_home = getenv("XDG_DATA_HOME"); + if (xdg_data_home) { + g_strstrip(xdg_data_home); + } + + if (xdg_data_home && (strcmp(xdg_data_home, "") != 0)) { + return strdup(xdg_data_home); + } + + GString *default_path = g_string_new(getenv("HOME")); + g_string_append(default_path, "/.local/share"); + gchar *result = strdup(default_path->str); + g_string_free(default_path, TRUE); + + return result; +} + +static gchar* +_get_main_log_file(void) +{ + gchar *xdg_data = _xdg_get_data_home(); + GString *logfile = g_string_new(xdg_data); + g_string_append(logfile, "/stabber/logs/stabber"); + g_string_append(logfile, ".log"); + gchar *result = strdup(logfile->str); + free(xdg_data); + g_string_free(logfile, TRUE); + + return result; +} + +static gboolean +_create_dir(char *name) +{ + struct stat sb; + if (stat(name, &sb) != 0) { + if (errno != ENOENT || mkdir(name, S_IRWXU) != 0) { + return FALSE; + } + } else { + if ((sb.st_mode & S_IFDIR) != S_IFDIR) { + return FALSE; + } + } + + return TRUE; +} + +static gboolean +_mkdir_recursive(const char *dir) +{ + int i; + gboolean result = TRUE; + + for (i = 1; i <= strlen(dir); i++) { + if (dir[i] == '/' || dir[i] == '\0') { + gchar *next_dir = g_strndup(dir, i); + result = _create_dir(next_dir); + g_free(next_dir); + if (!result) { + break; + } + } + } + + return result; +} + +static char* +_levelstr(stbbr_log_t loglevel) +{ + switch (loglevel) { + case STBBR_LOGERROR: return "ERR"; + case STBBR_LOGWARN: return "WRN"; + case STBBR_LOGINFO: return "INF"; + case STBBR_LOGDEBUG: return "DBG"; + default: return ""; + } +} diff --git a/src/server/prime.c b/src/server/prime.c index c7f9b64..1a382f4 100644 --- a/src/server/prime.c +++ b/src/server/prime.c @@ -67,7 +67,7 @@ prime_required_passwd(char *password) required_passwd = strdup(password); } -char * +char* prime_get_passwd(void) { return required_passwd; @@ -76,11 +76,12 @@ prime_get_passwd(void) void prime_for_id(const char *id, char *stream) { - if (idstubs) { - log_println(STBBR_LOGDEBUG, "Received stub for id: %s, stanza: %s", id, stream); - - g_hash_table_insert(idstubs, strdup(id), strdup(stream)); + if (!idstubs) { + return; } + + log_println(STBBR_LOGDEBUG, "Received stub for id: %s, stanza: %s", id, stream); + g_hash_table_insert(idstubs, strdup(id), strdup(stream)); } char* @@ -92,15 +93,16 @@ prime_get_for_id(const char *id) void prime_for_query(const char *query, char *stream) { - if (querystubs) { - log_println(STBBR_LOGDEBUG, "Received stub for query: %s, stanza: %s", query, stream); - - XMPPStanza *stanza = stanza_parse(stream); - g_hash_table_insert(querystubs, strdup(query), stanza); + if (!querystubs) { + return; } + + log_println(STBBR_LOGDEBUG, "Received stub for query: %s, stanza: %s", query, stream); + XMPPStanza *stanza = stanza_parse(stream); + g_hash_table_insert(querystubs, strdup(query), stanza); } -XMPPStanza * +XMPPStanza* prime_get_for_query(const char *query) { return g_hash_table_lookup(querystubs, query); diff --git a/src/server/server.c b/src/server/server.c index e615526..1cd8a22 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -53,17 +53,17 @@ #define STREAM_END "" pthread_mutex_t send_queue_lock; + static GList *send_queue; - static XMPPClient *client; - -static void _shutdown(void); - static int listen_socket; static pthread_t server_thread; static gboolean kill_recv = FALSE; static gboolean httpapi_run = FALSE; +static void _shutdown(void); +static void* _start_server_cb(void* userdata); + void write_stream(const char * const stream) { @@ -225,23 +225,27 @@ void id_callback(const char *id) { char *stream = prime_get_for_id(id); - if (stream) { - log_println(STBBR_LOGINFO, "--> ID callback fired for '%s'", id); - write_stream(stream); + if (!stream) { + return; } + + log_println(STBBR_LOGINFO, "--> ID callback fired for '%s'", id); + write_stream(stream); } void query_callback(const char *query, const char *id) { XMPPStanza *stanza = prime_get_for_query(query); - if (stanza) { - log_println(STBBR_LOGINFO, "--> QUERY callback fired for '%s'", query); - stanza_set_id(stanza, id); - char *stream = stanza_to_string(stanza); - write_stream(stream); - free(stream); + if (!stanza) { + return; } + + log_println(STBBR_LOGINFO, "--> QUERY callback fired for '%s'", query); + stanza_set_id(stanza, id); + char *stream = stanza_to_string(stanza); + write_stream(stream); + free(stream); } void @@ -258,54 +262,6 @@ server_wait_for(char *id) } } -void* -_start_server_cb(void* userdata) -{ -#ifdef PLATFORM_OSX - pthread_setname_np("stbr"); -#else - prctl(PR_SET_NAME, "stbr"); -#endif - - struct sockaddr_in client_addr; - - // listen socket non blocking - int res = fcntl(listen_socket, F_SETFL, fcntl(listen_socket, F_GETFL, 0) | O_NONBLOCK); - if (res == -1) { - log_println(STBBR_LOGERROR, "Error setting nonblocking on listen socket: %s", strerror(errno)); - return NULL; - } - - log_println(STBBR_LOGINFO, "Waiting for incoming connection..."); - - // wait for connection - int c = sizeof(struct sockaddr_in); - int client_socket; - errno = 0; - while ((client_socket = accept(listen_socket, (struct sockaddr *)&client_addr, (socklen_t*)&c)) == -1) { - if (errno != EAGAIN && errno != EWOULDBLOCK) { - log_println(STBBR_LOGERROR, "Accept failed: %s", strerror(errno)); - return NULL; - } - errno = 0; - usleep(1000 * 5); - } - - // client socket non blocking - res = fcntl(client_socket, F_SETFL, fcntl(client_socket, F_GETFL, 0) | O_NONBLOCK); - if (res == -1) { - log_println(STBBR_LOGERROR, "Error setting nonblocking on client socket: %s", strerror(errno)); - return NULL; - } - - client = xmppclient_new(client_addr, client_socket); - parser_init(stream_start_callback, auth_callback, id_callback, query_callback); - - read_stream(); - - return NULL; -} - int server_run(stbbr_log_t loglevel, int port, int httpport) { @@ -401,11 +357,61 @@ server_send(char *stream) void server_stop(void) { - if (!kill_recv) { - log_println(STBBR_LOGINFO, "SERVER STOP"); - kill_recv = TRUE; - pthread_join(server_thread, NULL); + if (kill_recv) { + return; } + + log_println(STBBR_LOGINFO, "SERVER STOP"); + kill_recv = TRUE; + pthread_join(server_thread, NULL); +} + +static void* +_start_server_cb(void* userdata) +{ +#ifdef PLATFORM_OSX + pthread_setname_np("stbr"); +#else + prctl(PR_SET_NAME, "stbr"); +#endif + + struct sockaddr_in client_addr; + + // listen socket non blocking + int res = fcntl(listen_socket, F_SETFL, fcntl(listen_socket, F_GETFL, 0) | O_NONBLOCK); + if (res == -1) { + log_println(STBBR_LOGERROR, "Error setting nonblocking on listen socket: %s", strerror(errno)); + return NULL; + } + + log_println(STBBR_LOGINFO, "Waiting for incoming connection..."); + + // wait for connection + int c = sizeof(struct sockaddr_in); + int client_socket; + errno = 0; + while ((client_socket = accept(listen_socket, (struct sockaddr *)&client_addr, (socklen_t*)&c)) == -1) { + if (errno != EAGAIN && errno != EWOULDBLOCK) { + log_println(STBBR_LOGERROR, "Accept failed: %s", strerror(errno)); + return NULL; + } + errno = 0; + usleep(1000 * 5); + } + + // client socket non blocking + res = fcntl(client_socket, F_SETFL, fcntl(client_socket, F_GETFL, 0) | O_NONBLOCK); + if (res == -1) { + log_println(STBBR_LOGERROR, "Error setting nonblocking on client socket: %s", strerror(errno)); + return NULL; + } + + client = xmppclient_new(client_addr, client_socket); + parser_init(stream_start_callback, auth_callback, id_callback, query_callback); + + read_stream(); + + return NULL; } static void diff --git a/src/server/stanza.c b/src/server/stanza.c index c8a5208..b7fa116 100644 --- a/src/server/stanza.c +++ b/src/server/stanza.c @@ -32,6 +32,11 @@ typedef struct parse_state_t { XMPPStanza *curr_stanza; } ParseState; +static void _start_element(void *data, const char *element, const char **attributes); +static void _end_element(void *data, const char *element); +static void _handle_data(void *data, const char *content, int length); +static void _attrs_free(XMPPAttr *attr); + XMPPStanza* stanza_new(const char *name, const char **attributes) { @@ -40,20 +45,18 @@ stanza_new(const char *name, const char **attributes) stanza->content = NULL; stanza->children = NULL; stanza->attrs = NULL; - if (attributes[0]) { - int i; - for (i = 0; attributes[i]; i += 2) { - XMPPAttr *attr = malloc(sizeof(XMPPAttr)); - attr->name = strdup(attributes[i]); - attr->value = strdup(attributes[i+1]); - stanza->attrs = g_list_append(stanza->attrs, attr); - } + int i; + for (i = 0; attributes[i]; i += 2) { + XMPPAttr *attr = malloc(sizeof(XMPPAttr)); + attr->name = strdup(attributes[i]); + attr->value = strdup(attributes[i+1]); + stanza->attrs = g_list_append(stanza->attrs, attr); } return stanza; } -char * +char* stanza_to_string(XMPPStanza *stanza) { GString *stanza_str = g_string_new("<"); @@ -168,7 +171,7 @@ stanza_get_child_by_name(XMPPStanza *stanza, char *name) return NULL; } -const char * +const char* stanza_get_id(XMPPStanza *stanza) { if (!stanza) { @@ -213,7 +216,7 @@ stanza_set_id(XMPPStanza *stanza, const char *id) stanza->attrs = g_list_append(stanza->attrs, attrnew); } -const char * +const char* stanza_get_attr(XMPPStanza *stanza, const char *name) { if (!stanza->attrs) { @@ -233,7 +236,7 @@ stanza_get_attr(XMPPStanza *stanza, const char *name) return NULL; } -const char * +const char* stanza_get_query_request(XMPPStanza *stanza) { if (g_strcmp0(stanza->name, "iq") != 0) { @@ -258,32 +261,42 @@ stanza_get_query_request(XMPPStanza *stanza) return xmlns; } -static void -_attrs_free(XMPPAttr *attr) -{ - if (attr) { - free(attr->name); - free(attr->value); - free(attr); - } -} - void stanza_free(XMPPStanza *stanza) { - if (stanza) { - free(stanza->name); - if (stanza->content) { - g_string_free(stanza->content, TRUE); - } - g_list_free_full(stanza->attrs, (GDestroyNotify)_attrs_free); - g_list_free_full(stanza->children, (GDestroyNotify)stanza_free); - free(stanza); + if (!stanza) { + return; } + + free(stanza->name); + if (stanza->content) { + g_string_free(stanza->content, TRUE); + } + g_list_free_full(stanza->attrs, (GDestroyNotify)_attrs_free); + g_list_free_full(stanza->children, (GDestroyNotify)stanza_free); + free(stanza); +} + +XMPPStanza* +stanza_parse(char *stanza_text) +{ + ParseState *state = malloc(sizeof(ParseState)); + state->depth = 0; + state->curr_stanza = NULL; + + XML_Parser parser = XML_ParserCreate(NULL); + XML_SetElementHandler(parser, _start_element, _end_element); + XML_SetCharacterDataHandler(parser, _handle_data); + XML_SetUserData(parser, state); + + XML_Parse(parser, stanza_text, strlen(stanza_text), 0); + XML_ParserFree(parser); + + return state->curr_stanza; } static void -start_element(void *data, const char *element, const char **attributes) +_start_element(void *data, const char *element, const char **attributes) { ParseState *state = data; @@ -300,7 +313,7 @@ start_element(void *data, const char *element, const char **attributes) } static void -end_element(void *data, const char *element) +_end_element(void *data, const char *element) { ParseState *state = data; @@ -313,7 +326,7 @@ end_element(void *data, const char *element) } static void -handle_data(void *data, const char *content, int length) +_handle_data(void *data, const char *content, int length) { ParseState *state = data; @@ -324,20 +337,14 @@ handle_data(void *data, const char *content, int length) g_string_append_len(state->curr_stanza->content, content, length); } -XMPPStanza * -stanza_parse(char *stanza_text) +static void +_attrs_free(XMPPAttr *attr) { - ParseState *state = malloc(sizeof(ParseState)); - state->depth = 0; - state->curr_stanza = NULL; + if (!attr) { + return; + } - XML_Parser parser = XML_ParserCreate(NULL); - XML_SetElementHandler(parser, start_element, end_element); - XML_SetCharacterDataHandler(parser, handle_data); - XML_SetUserData(parser, state); - - XML_Parse(parser, stanza_text, strlen(stanza_text), 0); - XML_ParserFree(parser); - - return state->curr_stanza; + free(attr->name); + free(attr->value); + free(attr); } diff --git a/src/server/stanzas.c b/src/server/stanzas.c index 3f7dc50..b962e5a 100644 --- a/src/server/stanzas.c +++ b/src/server/stanzas.c @@ -32,6 +32,9 @@ pthread_mutex_t stanzas_lock; static GList *stanzas; +static int _xmpp_attr_equal(XMPPAttr *attr1, XMPPAttr *attr2); +static int _stanzas_equal(XMPPStanza *first, XMPPStanza *second); + int stanzas_contains_id(char *id) { @@ -63,6 +66,64 @@ stanzas_add(XMPPStanza *stanza) pthread_mutex_unlock(&stanzas_lock); } +int +stanzas_verify_any(XMPPStanza *stanza) +{ + pthread_mutex_lock(&stanzas_lock); + if (!stanzas) { + pthread_mutex_unlock(&stanzas_lock); + return 0; + } + + GList *curr = g_list_last(stanzas); + while (curr) { + XMPPStanza *curr_stanza = curr->data; + if (_stanzas_equal(stanza, curr_stanza) == 0) { + pthread_mutex_unlock(&stanzas_lock); + return 1; + } + + curr = g_list_previous(curr); + } + + pthread_mutex_unlock(&stanzas_lock); + return 0; +} + +int +stanzas_verify_last(XMPPStanza *stanza) +{ + pthread_mutex_lock(&stanzas_lock); + if (!stanzas) { + pthread_mutex_unlock(&stanzas_lock); + return 0; + } + + GList *last = g_list_last(stanzas); + if (!last) { + pthread_mutex_unlock(&stanzas_lock); + return 0; + } + + XMPPStanza *last_stanza = (XMPPStanza *)last->data; + int res = _stanzas_equal(stanza, last_stanza); + pthread_mutex_unlock(&stanzas_lock); + if (res == 0) { + return 1; + } else { + return 0; + } +} + +void +stanzas_free_all(void) +{ + pthread_mutex_lock(&stanzas_lock); + g_list_free_full(stanzas, (GDestroyNotify)stanza_free); + stanzas = NULL; + pthread_mutex_unlock(&stanzas_lock); +} + static int _xmpp_attr_equal(XMPPAttr *attr1, XMPPAttr *attr2) { @@ -148,61 +209,3 @@ _stanzas_equal(XMPPStanza *first, XMPPStanza *second) return 0; } - -int -stanzas_verify_any(XMPPStanza *stanza) -{ - pthread_mutex_lock(&stanzas_lock); - if (!stanzas) { - pthread_mutex_unlock(&stanzas_lock); - return 0; - } - - GList *curr = g_list_last(stanzas); - while (curr) { - XMPPStanza *curr_stanza = curr->data; - if (_stanzas_equal(stanza, curr_stanza) == 0) { - pthread_mutex_unlock(&stanzas_lock); - return 1; - } - - curr = g_list_previous(curr); - } - - pthread_mutex_unlock(&stanzas_lock); - return 0; -} - -int -stanzas_verify_last(XMPPStanza *stanza) -{ - pthread_mutex_lock(&stanzas_lock); - if (!stanzas) { - pthread_mutex_unlock(&stanzas_lock); - return 0; - } - - GList *last = g_list_last(stanzas); - if (!last) { - pthread_mutex_unlock(&stanzas_lock); - return 0; - } - - XMPPStanza *last_stanza = (XMPPStanza *)last->data; - int res = _stanzas_equal(stanza, last_stanza); - pthread_mutex_unlock(&stanzas_lock); - if (res == 0) { - return 1; - } else { - return 0; - } -} - -void -stanzas_free_all(void) -{ - pthread_mutex_lock(&stanzas_lock); - g_list_free_full(stanzas, (GDestroyNotify)stanza_free); - stanzas = NULL; - pthread_mutex_unlock(&stanzas_lock); -} diff --git a/src/server/stream_parser.c b/src/server/stream_parser.c index cf541e7..0fdc758 100644 --- a/src/server/stream_parser.c +++ b/src/server/stream_parser.c @@ -42,8 +42,59 @@ static auth_func auth_cb = NULL; static id_func id_cb = NULL; static query_func query_cb = NULL; +static void _start_element(void *data, const char *element, const char **attributes); +static void _end_element(void *data, const char *element); +static void _handle_data(void *data, const char *content, int length); + +void +parser_init(stream_start_func startcb, auth_func authcb, id_func idcb, query_func querycb) +{ + if (curr_string) { + g_string_free(curr_string, TRUE); + } + curr_string = g_string_new(""); + + stream_start_cb = startcb; + auth_cb = authcb; + id_cb = idcb; + query_cb = querycb; + + parser = XML_ParserCreate(NULL); + XML_SetElementHandler(parser, _start_element, _end_element); + XML_SetCharacterDataHandler(parser, _handle_data); +} + +int +parser_feed(char *chunk, int len) +{ + g_string_append_len(curr_string, chunk, len); + int res = XML_Parse(parser, chunk, len, 0); + parser_reset(); + + return res; +} + +void +parser_close(void) +{ + XML_ParserFree(parser); + parser = NULL; +} + +void +parser_reset(void) +{ + if (do_reset != 1) { + return; + } + + parser_close(); + parser_init(stream_start_cb, auth_cb, id_cb, query_cb); + do_reset = 0; +} + static void -start_element(void *data, const char *element, const char **attributes) +_start_element(void *data, const char *element, const char **attributes) { if (g_strcmp0(element, "stream:stream") == 0) { log_println(STBBR_LOGINFO, "RECV: %s", curr_string->str); @@ -66,35 +117,35 @@ start_element(void *data, const char *element, const char **attributes) } static void -end_element(void *data, const char *element) +_end_element(void *data, const char *element) { depth--; - if (depth > 0) { stanza_add_child(curr_stanza->parent, curr_stanza); curr_stanza = curr_stanza->parent; - } else { - log_println(STBBR_LOGINFO, "RECV: %s", curr_string->str); - stanzas_add(curr_stanza); - if (stanza_get_child_by_ns(curr_stanza, "jabber:iq:auth")) { - auth_cb(curr_stanza); - } else { - const char *id = stanza_get_id(curr_stanza); - if (id) { - id_cb(id); - } - const char *query = stanza_get_query_request(curr_stanza); - if (query) { - query_cb(query, id); - } - } - - do_reset = 1; + return; } + + log_println(STBBR_LOGINFO, "RECV: %s", curr_string->str); + stanzas_add(curr_stanza); + if (stanza_get_child_by_ns(curr_stanza, "jabber:iq:auth")) { + auth_cb(curr_stanza); + } else { + const char *id = stanza_get_id(curr_stanza); + if (id) { + id_cb(id); + } + const char *query = stanza_get_query_request(curr_stanza); + if (query) { + query_cb(query, id); + } + } + + do_reset = 1; } static void -handle_data(void *data, const char *content, int length) +_handle_data(void *data, const char *content, int length) { if (!curr_stanza->content) { curr_stanza->content = g_string_new(""); @@ -102,47 +153,3 @@ handle_data(void *data, const char *content, int length) g_string_append_len(curr_stanza->content, content, length); } - -void -parser_init(stream_start_func startcb, auth_func authcb, id_func idcb, query_func querycb) -{ - if (curr_string) { - g_string_free(curr_string, TRUE); - } - curr_string = g_string_new(""); - - stream_start_cb = startcb; - auth_cb = authcb; - id_cb = idcb; - query_cb = querycb; - - parser = XML_ParserCreate(NULL); - XML_SetElementHandler(parser, start_element, end_element); - XML_SetCharacterDataHandler(parser, handle_data); -} - -int -parser_feed(char *chunk, int len) -{ - g_string_append_len(curr_string, chunk, len); - int res = XML_Parse(parser, chunk, len, 0); - parser_reset(); - return res; -} - -void -parser_close(void) -{ - XML_ParserFree(parser); - parser = NULL; -} - -void -parser_reset(void) -{ - if (do_reset == 1) { - parser_close(); - parser_init(stream_start_cb, auth_cb, id_cb, query_cb); - do_reset = 0; - } -} diff --git a/src/server/xmppclient.c b/src/server/xmppclient.c index 5cbbfca..0caf25f 100644 --- a/src/server/xmppclient.c +++ b/src/server/xmppclient.c @@ -48,16 +48,18 @@ xmppclient_new(struct sockaddr_in client_addr, int socket) void xmppclient_end_session(XMPPClient *client) { - if (client) { - if (client->sock) { - shutdown(client->sock, 2); - while (recv(client->sock, NULL, 1, 0) > 0) {} - close(client->sock); - } - free(client->ip); - free(client->username); - free(client->password); - free(client->resource); - free(client); + if (!client) { + return; } + + if (client->sock) { + shutdown(client->sock, 2); + while (recv(client->sock, NULL, 1, 0) > 0) {} + close(client->sock); + } + free(client->ip); + free(client->username); + free(client->password); + free(client->resource); + free(client); }