From 8729c58972d65ab4b4b7ef3da9bcaf0d7f237d4c Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Sun, 2 Nov 2008 10:55:34 -0200 Subject: [PATCH] Added support for resouce binding and session establishment --- Makefile | 2 +- bind.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ bind.h | 30 ++++++++++++++++++++++ features.c | 40 ++++++++++++++++++++++++++--- sasl.c | 2 ++ tictactoe.c | 50 +++++++++++++++++++++++++++++++----- xmpp.c | 18 +++++++++++++ xmpp.h | 8 +++++- xmpp_internal.h | 2 ++ 9 files changed, 209 insertions(+), 11 deletions(-) create mode 100644 bind.c create mode 100644 bind.h diff --git a/Makefile b/Makefile index 275426f..f45bdd9 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ OBJECTS = sort_udns.o tcp_connect.o iksemel_extra.o tictactoe.o \ - xmpp.o features.o sasl.o + xmpp.o features.o sasl.o bind.o CC = gcc CFLAGS = -g -Wall `pkg-config --cflags iksemel libgsasl` LIBS = -ludns `pkg-config --libs iksemel libgsasl` diff --git a/bind.c b/bind.c new file mode 100644 index 0000000..f4a760e --- /dev/null +++ b/bind.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2008 Thadeu Lima de Souza Cascardo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + +#include "xmpp_internal.h" +#include "bind.h" + +void +hc_xmpp_bind (hc_xmpp_t *xmpp) +{ + iks *iqbind; + iks *query; + iqbind = iks_new ("iq"); + iks_insert_attrib (iqbind, "type", "set"); + query = iks_insert (iqbind, "bind"); + iks_insert_attrib (query, "xmlns", HC_XMPP_NS_BIND); + hc_xmpp_send_iks (xmpp, iqbind); + iks_delete (iqbind); +} + +void +hc_xmpp_bind_result (hc_xmpp_t *xmpp, iks *result) +{ + if (!iks_strcmp (iks_find_attrib (result, "type"), "result")) + { + xmpp->status = HC_XMPP_BOUND; + xmpp->bind |= ENABLED; + } +} + +void +hc_xmpp_session (hc_xmpp_t *xmpp) +{ + iks *iqsession; + iks *query; + iqsession = iks_new ("iq"); + iks_insert_attrib (iqsession, "type", "set"); + query = iks_insert (iqsession, "session"); + iks_insert_attrib (query, "xmlns", HC_XMPP_NS_SESSION); + hc_xmpp_send_iks (xmpp, iqsession); + iks_delete (iqsession); +} + +void +hc_xmpp_session_result (hc_xmpp_t *xmpp, iks *result) +{ + if (!iks_strcmp (iks_find_attrib (result, "type"), "result")) + { + xmpp->status = HC_XMPP_SESSION; + xmpp->session |= ENABLED; + } +} + diff --git a/bind.h b/bind.h new file mode 100644 index 0000000..a77ab77 --- /dev/null +++ b/bind.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2008 Thadeu Lima de Souza Cascardo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + +#ifndef HC_XMPP_BIND_H +#define HC_XMPP_BIND_H + +#include "xmpp.h" + +void hc_xmpp_bind (hc_xmpp_t *); +void hc_xmpp_bind_result (hc_xmpp_t *, iks *); +void hc_xmpp_session (hc_xmpp_t *); +void hc_xmpp_session_result (hc_xmpp_t*, iks *); + +#endif diff --git a/features.c b/features.c index 3fd1896..a4427ce 100644 --- a/features.c +++ b/features.c @@ -19,7 +19,35 @@ #include "xmpp_internal.h" -void +static void +session (hc_xmpp_t *xmpp, iks *f) +{ + iks *c; + xmpp->session |= SUPPORTED; + for (c = iks_child (f); c != NULL; c = iks_next (c)) + { + if (!iks_strcmp (iks_name (c), "optional")) + xmpp->session |= OPTIONAL; + else if (!iks_strcmp (iks_name (c), "required")) + xmpp->session |= REQUIRED; + } +} + +static void +xmpp_bind (hc_xmpp_t *xmpp, iks *f) +{ + iks *c; + xmpp->bind |= SUPPORTED; + for (c = iks_child (f); c != NULL; c = iks_next (c)) + { + if (!iks_strcmp (iks_name (c), "optional")) + xmpp->bind |= OPTIONAL; + else if (!iks_strcmp (iks_name (c), "required")) + xmpp->bind |= REQUIRED; + } +} + +static void sasl (hc_xmpp_t *xmpp, iks *f) { iks *c; @@ -33,7 +61,7 @@ sasl (hc_xmpp_t *xmpp, iks *f) } } -void +static void tls (hc_xmpp_t *xmpp, iks *f) { iks *c; @@ -56,8 +84,14 @@ hc_xmpp_features (hc_xmpp_t *xmpp, iks *features) if (!iks_strcmp (iks_name (c), "starttls") && !iks_strcmp (iks_find_attrib (c, "xmlns"), HC_XMPP_NS_TLS)) tls (xmpp, c); - if (!iks_strcmp (iks_name (c), "mechanisms") && + else if (!iks_strcmp (iks_name (c), "mechanisms") && !iks_strcmp (iks_find_attrib (c, "xmlns"), HC_XMPP_NS_SASL)) sasl (xmpp, c); + else if (!iks_strcmp (iks_name (c), "bind") && + !iks_strcmp (iks_find_attrib (c, "xmlns"), HC_XMPP_NS_BIND)) + xmpp_bind (xmpp, c); + else if (!iks_strcmp (iks_name (c), "session") && + !iks_strcmp (iks_find_attrib (c, "xmlns"), HC_XMPP_NS_SESSION)) + session (xmpp, c); } } diff --git a/sasl.c b/sasl.c index dd93367..42cdc6a 100644 --- a/sasl.c +++ b/sasl.c @@ -38,6 +38,7 @@ hc_xmpp_sasl_authenticate (hc_xmpp_t *xmpp) iks_insert_cdata (auth, p, 0); hc_xmpp_send_iks (xmpp, auth); free (p); + iks_delete (auth); } void @@ -45,6 +46,7 @@ hc_xmpp_sasl_iterate (hc_xmpp_t *xmpp, iks *stanza) { if (!iks_strcmp (iks_name (stanza), "success")) { + xmpp->sasl |= ENABLED; xmpp->status = HC_XMPP_AUTHENTICATED; } } diff --git a/tictactoe.c b/tictactoe.c index 700a269..b57c1b9 100644 --- a/tictactoe.c +++ b/tictactoe.c @@ -27,23 +27,61 @@ #include "iksemel_extra.h" #include "xmpp.h" #include "sasl.h" +#include "bind.h" -int +static void write_stream (hc_xmpp_t *); + +static void +send_message_test (hc_xmpp_t *xmpp) +{ + iks *msg; + msg = iks_new ("message"); + iks_insert_attrib (msg, "to", "metal@jabber-br.org"); + iks_insert_cdata (iks_insert (msg, "body"), "pubsub", 0); + hc_xmpp_send_iks (xmpp, msg); + iks_delete (msg); +} + +static int myhook (void *data, int type, iks *stanza) { - if (!iks_strcmp (iks_name (stanza), "stream:features")) + if (!iks_strcmp (iks_name (stanza), "iq")) + { + char *ns = iks_find_attrib (iks_child (stanza), "xmlns"); + if (!iks_strcmp (ns, HC_XMPP_NS_BIND)) + { + hc_xmpp_bind_result (data, stanza); + if (hc_xmpp_status (data) == HC_XMPP_BOUND && + hc_xmpp_is_session_supported (data)) + hc_xmpp_session (data); + } + else if (!iks_strcmp (ns, HC_XMPP_NS_SESSION)) + { + hc_xmpp_session_result (data, stanza); + if (hc_xmpp_status (data) == HC_XMPP_SESSION) + send_message_test (data); + } + } + else if (!iks_strcmp (iks_name (stanza), "stream:features")) { hc_xmpp_features (data, stanza); - if (hc_xmpp_is_sasl_supported (data)) + if (hc_xmpp_is_sasl_supported (data) & !hc_xmpp_is_sasl_enabled (data)) { hc_xmpp_sasl_authenticate (data); } + if (hc_xmpp_is_bind_supported (data)) + { + hc_xmpp_bind (data); + } } else if (!iks_strcmp (iks_find_attrib (stanza, "xmlns"), HC_XMPP_NS_SASL)) { hc_xmpp_sasl_iterate (data, stanza); if (hc_xmpp_status (data) == HC_XMPP_AUTHENTICATED) - fprintf (stdout, "Authenticated\n"); + { + write_stream (data); + fprintf (stdout, "Authenticated\n"); + } } else { @@ -52,7 +90,7 @@ myhook (void *data, int type, iks *stanza) return IKS_OK; } -void +static void write_stream (hc_xmpp_t *xmpp) { char *buffer = NULL; @@ -63,7 +101,7 @@ write_stream (hc_xmpp_t *xmpp) free (buffer); } -void +static void loop (hc_xmpp_t *xmpp) { while (1) diff --git a/xmpp.c b/xmpp.c index ca9501e..8e37c78 100644 --- a/xmpp.c +++ b/xmpp.c @@ -89,6 +89,24 @@ hc_xmpp_is_sasl_enabled (hc_xmpp_t *xmpp) return xmpp->sasl & ENABLED; } +int +hc_xmpp_is_bind_supported (hc_xmpp_t *xmpp) +{ + return xmpp->bind & SUPPORTED; +} + +int +hc_xmpp_is_session_supported (hc_xmpp_t *xmpp) +{ + return xmpp->session & SUPPORTED; +} + +int +hc_xmpp_is_session_required (hc_xmpp_t *xmpp) +{ + return xmpp->session & REQUIRED; +} + char * hc_xmpp_server (hc_xmpp_t *xmpp) { diff --git a/xmpp.h b/xmpp.h index 7a0e0d0..706f15c 100644 --- a/xmpp.h +++ b/xmpp.h @@ -26,13 +26,16 @@ enum { HC_XMPP_NONE, HC_XMPP_AUTHENTICATED, - HC_XMPP_BOUND + HC_XMPP_BOUND, + HC_XMPP_SESSION }; typedef struct _hc_xmpp_t hc_xmpp_t; #define HC_XMPP_NS_TLS "urn:ietf:params:xml:ns:xmpp-tls" #define HC_XMPP_NS_SASL "urn:ietf:params:xml:ns:xmpp-sasl" +#define HC_XMPP_NS_BIND "urn:ietf:params:xml:ns:xmpp-bind" +#define HC_XMPP_NS_SESSION "urn:ietf:params:xml:ns:xmpp-session" hc_xmpp_t * hc_xmpp_new (iksStreamHook *, char *, char *, char *); int hc_xmpp_is_tls_supported (hc_xmpp_t *); @@ -43,6 +46,9 @@ int hc_xmpp_is_sasl_supported (hc_xmpp_t *); int hc_xmpp_is_sasl_required (hc_xmpp_t *); int hc_xmpp_is_sasl_optional (hc_xmpp_t *); int hc_xmpp_is_sasl_enabled (hc_xmpp_t *); +int hc_xmpp_is_bind_supported (hc_xmpp_t *); +int hc_xmpp_is_session_supported (hc_xmpp_t *); +int hc_xmpp_is_session_required (hc_xmpp_t *); char *hc_xmpp_server (hc_xmpp_t *); void hc_xmpp_send_buffer (hc_xmpp_t *, char *, size_t); void hc_xmpp_send_iks (hc_xmpp_t *, iks *); diff --git a/xmpp_internal.h b/xmpp_internal.h index df8790c..d46fcf9 100644 --- a/xmpp_internal.h +++ b/xmpp_internal.h @@ -44,6 +44,8 @@ struct _hc_xmpp_t int fd; int tls; int sasl; + int bind; + int session; int status; }; -- 2.20.1