Remove protocol detection altogether
[cascardo/rnetproxy.git] / jabber.c
1 /*
2 ** Copyright (C) 2006 Thadeu Lima de Souza Cascardo <cascardo@minaslivre.org>
3 **  
4 ** This program is free software; you can redistribute it and/or modify
5 ** it under the terms of the GNU General Public License as published by
6 ** the Free Software Foundation; either version 2 of the License, or
7 ** (at your option) any later version.
8 **  
9 ** This program is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 ** GNU General Public License for more details.
13 **  
14 ** You should have received a copy of the GNU General Public License
15 ** along with this program; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 **  
18 */
19
20 #include <gnet.h>
21 #include <glib.h>
22 #include <iksemel.h>
23 #include <gsasl.h>
24 #include "iksemel_extra.h"
25 #include "jabber.h"
26
27 jabber_data_t* jabber_data_new (gpointer hook, gpointer parser)
28 {
29   jabber_data_t *data;
30   data = g_slice_new0 (jabber_data_t);
31   data->parser = iks_extra_stream_new (hook, parser);
32   gsasl_init (&(data->ctx));
33   return data;
34 }
35
36 void jabber_data_destroy (gpointer data)
37 {
38   jabber_data_t *jdata = (jabber_data_t*) data;
39   if (jdata->parser)
40     iks_parser_delete (jdata->parser);
41   if (jdata->client)
42     gsasl_finish (jdata->client);
43   if (jdata->server)
44     gsasl_finish (jdata->server);
45   if (jdata->ctx)
46     gsasl_done (jdata->ctx);
47   g_slice_free (jabber_data_t, jdata);
48 }
49
50 static void jabber_connect (net_hook_t* hook)
51 {
52 }
53
54 static void jabber_close (net_hook_t* hook)
55 {
56   if (hook->peer)
57     {
58       hook->peer->peer = NULL;
59       gnet_conn_disconnect (hook->peer->conn);
60     }
61   gnet_conn_delete (hook->conn);
62   jabber_data_destroy (hook->data);
63   g_slice_free (net_hook_t, hook);
64 }
65
66 static void jabber_write (net_hook_t* hook)
67 {
68 }
69
70 static void jabber_read (net_hook_t* hook, gchar* buffer, size_t len)
71 {
72   jabber_data_t *jdata = (jabber_data_t*) hook->data;
73   iks_parse (jdata->parser, buffer, len, FALSE);
74 }
75
76 void jabber_error (net_hook_t* hook)
77 {
78   g_message ("Error in jabber client connection.");
79 }
80
81 GString* jabber_new_start (iks* node)
82 {
83   GString* buffer;
84   buffer = g_string_sized_new (256);
85   g_string_append (buffer, iks_string (iks_stack (node), node));
86   g_string_erase (buffer, buffer->len - 2, 1);
87   return buffer;
88 }
89
90 void jabber_connect_server (net_hook_t* hook, char* server, iks* node)
91 {
92   net_hook_t* server_hook;
93   GString* buffer;
94   g_message ("Received new stream.");
95   if (hook->peer == NULL)
96     {
97       server_hook = jabber_server_hook_new (hook, server);
98       hook->peer = server_hook;
99       g_message ("Trying to connect to server %s.", server);
100       gnet_conn_connect (hook->peer->conn);
101       gnet_conn_read (hook->peer->conn);
102     }
103   buffer = jabber_new_start (node);
104   gnet_conn_write (hook->peer->conn, buffer->str, buffer->len);
105   g_string_free (buffer, TRUE);
106 }
107
108 void
109 jabber_sasl_plain_filter (iks *node)
110 {
111   if (g_str_equal (iks_name (node), "auth") &&
112       g_str_equal (iks_find_attrib (node, "xmlns"),
113                                     "urn:ietf:params:xml:ns:xmpp-sasl"))
114     {
115       char *b64;
116       char *uname;
117       gsize uname_len;
118       b64 = iks_cdata (iks_child (node));
119       uname = g_base64_decode (b64, &uname_len);
120       g_message ("User trying authentication as %s", uname);
121       g_free (uname);
122     }
123 }
124
125 void jabber_send (net_hook_t* hook, iks* node)
126 {
127   GString* buffer;
128   jabber_sasl_plain_filter (node);
129   buffer = g_string_new (iks_string (iks_stack (node), node));
130   gnet_conn_write (hook->peer->conn, buffer->str, buffer->len);
131   g_string_free (buffer, TRUE);
132 }
133
134 int jabber_parser (gpointer data, int type, iks* node)
135 {
136   net_hook_t* hook;
137   char* server;
138   hook = (net_hook_t*) data;
139   switch (type)
140     {
141     case IKS_NODE_START:
142       server = iks_find_attrib (node, "to");
143       if (server == NULL)
144         {
145           jabber_error (hook);
146         }
147       jabber_connect_server (hook, server, node);
148       iks_delete (node);
149       break;
150     case IKS_NODE_NORMAL:
151       jabber_send (hook, node);
152       iks_delete (node);
153       break;
154     case IKS_NODE_STOP:
155       gnet_conn_write (hook->peer->conn, "</stream:stream>", 16);
156       break;
157     case IKS_NODE_ERROR:
158       break;
159     }
160   return IKS_OK;
161 }
162
163 net_hook_t* jabber_hook_new (GConn* conn)
164 {
165   net_hook_t* hook;
166   hook = g_slice_new (net_hook_t);
167   hook->conn = conn;
168   hook->peer = NULL;
169   hook->server = FALSE;
170   hook->connect = jabber_connect;
171   hook->close = jabber_close;
172   hook->write = jabber_write;
173   hook->read = jabber_read;
174   hook->data = jabber_data_new (hook, jabber_parser);
175   gnet_conn_set_callback (hook->conn, nethook_event, hook);
176   return hook;
177 }
178
179 void jabber_destroy (net_hook_t* hook)
180 {
181   g_slice_free (net_hook_t, hook);
182 }