conn: clear system handlers on reconnect
xmpp_conn_t object can be reused with saving user's handlers. However, saving system handlers can lead to a fail during connection process. This is because old object may contain timed handlers for missed features or other handlers that would handle incoming stanzas incorrectly.
This commit is contained in:
@@ -4,6 +4,8 @@
|
|||||||
- OpenSSL tls module disables insecure SSLv2 SSLv3 and TLSv1
|
- OpenSSL tls module disables insecure SSLv2 SSLv3 and TLSv1
|
||||||
- Support of handlers with the same callback function, but different
|
- Support of handlers with the same callback function, but different
|
||||||
userdata
|
userdata
|
||||||
|
- System handlers are deleted on xmpp_conn_t reconnection. Old system
|
||||||
|
handlers could cause problems
|
||||||
- New public function xmpp_sha1_digest()
|
- New public function xmpp_sha1_digest()
|
||||||
|
|
||||||
0.9.1
|
0.9.1
|
||||||
|
|||||||
@@ -266,6 +266,7 @@ void handler_add(xmpp_conn_t * const conn,
|
|||||||
const char * const name,
|
const char * const name,
|
||||||
const char * const type,
|
const char * const type,
|
||||||
void * const userdata);
|
void * const userdata);
|
||||||
|
void handler_system_delete_all(xmpp_conn_t *conn);
|
||||||
|
|
||||||
/* utility functions */
|
/* utility functions */
|
||||||
void disconnect_mem_error(xmpp_conn_t * const conn);
|
void disconnect_mem_error(xmpp_conn_t * const conn);
|
||||||
|
|||||||
@@ -1215,6 +1215,8 @@ static void _conn_reset(xmpp_conn_t * const conn)
|
|||||||
conn->secured = 0;
|
conn->secured = 0;
|
||||||
conn->tls_failed = 0;
|
conn->tls_failed = 0;
|
||||||
conn->error = 0;
|
conn->error = 0;
|
||||||
|
|
||||||
|
handler_system_delete_all(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _conn_connect(xmpp_conn_t * const conn,
|
static int _conn_connect(xmpp_conn_t * const conn,
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ void handler_fire_stanza(xmpp_conn_t * const conn,
|
|||||||
head_old = head;
|
head_old = head;
|
||||||
_handler_item_remove(&head, item);
|
_handler_item_remove(&head, item);
|
||||||
if (head != head_old) {
|
if (head != head_old) {
|
||||||
|
/* TODO implement hash_replace() */
|
||||||
hash_drop(conn->id_handlers, id);
|
hash_drop(conn->id_handlers, id);
|
||||||
hash_add(conn->id_handlers, id, head);
|
hash_add(conn->id_handlers, id, head);
|
||||||
}
|
}
|
||||||
@@ -614,3 +615,73 @@ void handler_add(xmpp_conn_t * const conn,
|
|||||||
{
|
{
|
||||||
_handler_add(conn, handler, ns, name, type, userdata, 0);
|
_handler_add(conn, handler, ns, name, type, userdata, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Delete all system handlers.
|
||||||
|
* This function is used to reset conn object before re-connecting.
|
||||||
|
*
|
||||||
|
* @param conn a Strophe connection object
|
||||||
|
*/
|
||||||
|
void handler_system_delete_all(xmpp_conn_t *conn)
|
||||||
|
{
|
||||||
|
xmpp_handlist_t *item, *next, *head, *head_old;
|
||||||
|
hash_iterator_t *iter;
|
||||||
|
const char *key;
|
||||||
|
char *key2;
|
||||||
|
|
||||||
|
/* TODO unify all kinds of handlers and avoid copy-paste below */
|
||||||
|
|
||||||
|
item = conn->handlers;
|
||||||
|
while (item) {
|
||||||
|
if (!item->user_handler) {
|
||||||
|
next = item->next;
|
||||||
|
_handler_item_remove(&conn->handlers, item);
|
||||||
|
if (item->ns) xmpp_free(conn->ctx, item->ns);
|
||||||
|
if (item->name) xmpp_free(conn->ctx, item->name);
|
||||||
|
if (item->type) xmpp_free(conn->ctx, item->type);
|
||||||
|
xmpp_free(conn->ctx, item);
|
||||||
|
item = next;
|
||||||
|
} else
|
||||||
|
item = item->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
item = conn->timed_handlers;
|
||||||
|
while (item) {
|
||||||
|
if (!item->user_handler) {
|
||||||
|
next = item->next;
|
||||||
|
_handler_item_remove(&conn->timed_handlers, item);
|
||||||
|
xmpp_free(conn->ctx, item);
|
||||||
|
item = next;
|
||||||
|
} else
|
||||||
|
item = item->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
iter = hash_iter_new(conn->id_handlers);
|
||||||
|
key = iter == NULL ? NULL : hash_iter_next(iter);
|
||||||
|
while (key != NULL) {
|
||||||
|
head = head_old = (xmpp_handlist_t *)hash_get(conn->id_handlers, key);
|
||||||
|
item = head;
|
||||||
|
while (item) {
|
||||||
|
if (!item->user_handler) {
|
||||||
|
next = item->next;
|
||||||
|
_handler_item_remove(&head, item);
|
||||||
|
xmpp_free(conn->ctx, item->id);
|
||||||
|
xmpp_free(conn->ctx, item);
|
||||||
|
item = next;
|
||||||
|
} else
|
||||||
|
item = item->next;
|
||||||
|
}
|
||||||
|
if (head != head_old)
|
||||||
|
key2 = xmpp_strdup(conn->ctx, key);
|
||||||
|
/* Hash table implementation is not perfect, so we need to find next
|
||||||
|
key before dropping current one. Otherwise, we will get access to
|
||||||
|
freed memory. */
|
||||||
|
key = hash_iter_next(iter);
|
||||||
|
if (head != head_old) {
|
||||||
|
/* TODO implement hash_replace() to reduce number of allocations */
|
||||||
|
hash_drop(conn->id_handlers, key2);
|
||||||
|
if (head != NULL)
|
||||||
|
hash_add(conn->id_handlers, key2, head);
|
||||||
|
xmpp_free(conn->ctx, key2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user