Added ssl status responses
[jimb.git] / src / connection.c
blobf4685e44ee65dd584a189d34c53d1bb87d81d3ed
1 /**
2 * JIMCI (Jabber Instant Messaging Connection Interface)
3 * This file is part of JIMB.
5 * JIMCI is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License Version 3
7 * as published by the Free Software Foundation.
9 * JIMCI 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.
14 * You should have received a copy of the GNU General Public License Version 3
15 * along with JIMCI; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 * File: Connection
19 * Package: JIMCI
20 * Author: Martin Kelm <martinkelm@idxsolutions.de>
22 #include <stdlib.h>
23 #include <glib.h>
24 #include <loudmouth/loudmouth.h>
25 #include <string.h>
27 #include "main.h"
28 #include "connection.h"
29 #include "services.h"
30 #include "mysql.h"
32 LmConnection *conn;
33 LmSSL *conn_ssl;
34 GError *error = NULL;
35 static GMainLoop *main_loop = NULL;
36 static gboolean online = FALSE;
38 static gchar *c_host = NULL;
39 static gint c_port = 0;
40 static gchar *c_user = NULL;
41 static gchar *c_password = NULL;
42 static gchar *c_resource = "";
44 //static const USE_TCP_KEEPALIVES = 1;
46 static void conn_auth_cb(
47 LmConnection *connection, gboolean success, gpointer user_data
48 ) {
49 if (success) {
50 online = TRUE;
52 LmMessage *m;
53 m = lm_message_new_with_sub_type(
54 NULL, LM_MESSAGE_TYPE_PRESENCE, LM_MESSAGE_SUB_TYPE_AVAILABLE
56 lm_connection_send(conn, m, NULL);
57 lm_message_unref(m);
58 debug("Authentificated with: %s", c_user);
59 } else {
60 g_print("Couldn't authenticate with '%s':\n%s\n", c_user, error->message);
61 g_free(error);
62 g_main_loop_quit(main_loop);
66 static void conn_open_cb (
67 LmConnection *connection, gboolean success, gpointer user_data
68 ) {
69 if (success) {
70 lm_connection_authenticate(
71 conn, c_user, c_password, c_resource, conn_auth_cb, NULL, FALSE, NULL
73 debug("Connected to: %s", c_host);
74 } else {
75 g_printerr("Failed to connect to %s: %s\n", c_host, error->message);
76 g_free(error);
77 g_main_loop_quit(main_loop);
81 static void conn_close_cb (
82 LmConnection *connection, LmDisconnectReason reason, gpointer user_data
83 ) {
84 lm_connection_close(conn, NULL);
85 lm_connection_unref(conn);
87 online = FALSE;
89 const char *str;
90 switch (reason) {
91 case LM_DISCONNECT_REASON_OK:
92 str = "LM_DISCONNECT_REASON_OK";
93 break;
94 case LM_DISCONNECT_REASON_PING_TIME_OUT:
95 str = "LM_DISCONNECT_REASON_PING_TIME_OUT";
96 break;
97 case LM_DISCONNECT_REASON_HUP:
98 str = "LM_DISCONNECT_REASON_HUP";
99 break;
100 case LM_DISCONNECT_REASON_ERROR:
101 str = "LM_DISCONNECT_REASON_ERROR";
102 break;
103 case LM_DISCONNECT_REASON_UNKNOWN:
104 default:
105 str = "LM_DISCONNECT_REASON_UNKNOWN";
106 break;
109 g_print("Disconnected, reason %d: %s\n", reason, str);
110 lm_ssl_unref(conn_ssl);
111 g_main_loop_quit(main_loop);
114 static LmHandlerResult conn_handle_messages(
115 LmMessageHandler *handler, LmConnection *connection,
116 LmMessage *m, gpointer user_data
118 LmMessageNode *msgBody = lm_message_node_get_child(m->node, "body");
119 const gchar *msgFromVal = lm_message_node_get_attribute(m->node, "from");
120 const gchar *msgSelfVal = g_strdup_printf("%s@%s/%s", c_user, c_host, c_resource);
122 debug("lm handler result");
123 if (strlen(msgFromVal) > 0 && strcmp(msgFromVal, msgSelfVal) == 0) {
124 debug("Loopback message from %s.", msgFromVal);
125 lm_message_unref(m);
127 } else if (strlen(msgFromVal) > 0 && msgBody) {
128 const gchar *msgBodyVal = lm_message_node_get_value(msgBody);
129 if (strlen(msgBodyVal) > 0) {
130 g_print("Incoming message %s from %s\n", msgBodyVal, msgFromVal);
132 gchar *valuesSql;
133 valuesSql = g_strdup_printf(
134 "NULL, '%s', '%s', NULL, NULL, NULL", msgFromVal, msgBodyVal);
135 if (mysql_insert_values("queue_in", valuesSql) > 0 &&
136 strlen(services_queue_message) > 0) {
138 m = lm_message_new(msgFromVal, LM_MESSAGE_TYPE_MESSAGE);
139 lm_message_node_add_child(m->node, "body", services_queue_message);
141 if (!lm_connection_send(connection, m, &error)) {
142 g_print("Error while sending message to '%s':\n%s\n",
143 msgFromVal, error->message);
144 g_free(error);
146 lm_message_unref(m);
148 g_free(valuesSql);
151 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
154 gboolean conn_send_messages(gpointer data) {
155 debug("conn send messages --- %d : %d", lm_connection_get_state(conn), LM_CONNECTION_STATE_AUTHENTICATED);
156 if (lm_connection_get_state(conn) == LM_CONNECTION_STATE_AUTHENTICATED) {
157 int i, j, fieldsByRow, fieldsIndex;
158 gchar *to, *msg;
159 LmMessage *m;
160 debug("try to fetch outgoing messages");
161 gboolean fetch = mysql_fetch_rows("queue_out", "jid, message");
162 if (fetch == TRUE && mysqlIndexRows->len > 0 && mysqlFields->len > 0) {
163 fieldsByRow = mysqlFields->len / mysqlIndexRows->len;
164 debug("go through entries");
165 for (i = 0; i < mysqlIndexRows->len; i++) {
167 fieldsIndex = g_array_index(mysqlIndexRows, int, i);
168 for (j = 0; j < fieldsByRow; j++) {
169 if (j == 0) {
170 to = g_strdup_printf(
171 "%s", g_array_index(mysqlFields, gchar *, fieldsIndex+j)
173 } else {
174 msg = g_strdup_printf(
175 "%s", g_array_index(mysqlFields, gchar *, fieldsIndex+j)
179 if (strlen(to) > 0 && strlen(msg) > 0) {
180 m = lm_message_new(to, LM_MESSAGE_TYPE_MESSAGE);
181 lm_message_node_add_child(m->node, "body", msg);
182 g_print("Outgoing message %s to %s\n", msg, to);
183 if (!lm_connection_send(conn, m, &error)) {
184 g_print("Error while sending message to '%s':\n%s\n",
185 to, error->message);
186 g_free(error);
188 lm_message_unref(m);
191 g_free(to);
192 g_free(msg);
193 mysql_trunk_table("queue_out");
195 return TRUE;
197 return FALSE;
200 gboolean conn_send_loopback_message(gpointer data) {
201 debug("conn send loopback message");
202 if (lm_connection_get_state(conn) == LM_CONNECTION_STATE_AUTHENTICATED) {
203 LmMessage *m;
204 if (strlen(c_user) > 0) {
205 m = lm_message_new(
206 g_strdup_printf("%s@%s/%s", c_user, c_host, c_resource),
207 LM_MESSAGE_TYPE_MESSAGE
209 if (!lm_connection_send(conn, m, &error)) {
210 g_print("Error while sending loopback message:\n%s\n", error->message);
211 g_free(error);
212 } else {
213 debug("Send loopback message to own user.");
215 lm_message_unref(m);
217 return TRUE;
219 return FALSE;
222 static LmSSLResponse conn_ssl_response(LmSSL *ssl, LmSSLStatus status, gpointer data) {
223 g_print("SSL Status: %d -> ", status);
225 switch (status) {
226 case LM_SSL_STATUS_NO_CERT_FOUND:
227 g_print("No certificate found!\n");
228 break;
229 case LM_SSL_STATUS_UNTRUSTED_CERT:
230 g_print("Certificate is not trusted!\n");
231 break;
232 case LM_SSL_STATUS_CERT_EXPIRED:
233 g_print("Certificate has expired!\n");
234 break;
235 case LM_SSL_STATUS_CERT_NOT_ACTIVATED:
236 g_print("Certificate has not been activated!\n");
237 break;
238 case LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH:
239 g_print("Certificate hostname does not match expected hostname!\n");
240 break;
241 case LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH:
242 g_print("Certificate fingerprint does not match expected fingerprint!\n");
243 break;
244 case LM_SSL_STATUS_GENERIC_ERROR:
245 g_print("Generic SSL error!\n");
246 break;
249 return LM_SSL_RESPONSE_CONTINUE;
252 int conn_create(char *host, int port, int ssl,
253 char *user, char *resource, char *password) {
254 c_host = host;
255 c_port = port;
256 c_user = user;
257 c_resource = resource;
258 c_password = password;
260 debug("Set lm connection and connection data");
261 gboolean result;
262 conn = lm_connection_new(c_host);
263 if (ssl > 0) {
264 conn_ssl = lm_ssl_new(NULL, conn_ssl_response, NULL, NULL);
265 if (conn_ssl) {
266 lm_connection_set_ssl(conn, conn_ssl);
267 lm_ssl_unref(conn_ssl);
268 } else {
269 debug("Failed to create ssl connection");
273 lm_connection_set_port(conn, c_port);
274 LmMessageHandler *handler;
276 gchar *jid;
277 jid = g_strdup_printf("%s@%s", c_user, c_host);
278 lm_connection_set_jid(conn, jid);
279 g_free(jid);
281 debug("Set lm messages handler");
282 handler = lm_message_handler_new(conn_handle_messages, NULL, NULL);
283 lm_connection_register_message_handler(
284 conn, handler, LM_MESSAGE_TYPE_MESSAGE, LM_HANDLER_PRIORITY_NORMAL
286 lm_message_handler_unref(handler);
288 debug("Set lm disconnect function");
289 lm_connection_set_disconnect_function(conn, conn_close_cb, NULL, NULL);
291 debug("Try to open lm connection");
292 result = lm_connection_open(
293 conn, (LmResultFunction)conn_open_cb, NULL, NULL, &error
295 if (!result) {
296 g_print("Couldn't open connection to '%s':\n%s\n", host, error->message);
297 g_free(error);
298 return -1;
300 debug("Lm connection established");
302 debug("Set send messages / loopback messages timeouts and main loop");
303 gint func_ref = g_timeout_add(1000, conn_send_messages, NULL);
304 gint func_loopback_ref = g_timeout_add(30000, conn_send_loopback_message, NULL);
305 lm_connection_set_keep_alive_rate(conn, 30);
307 main_loop = g_main_loop_new(NULL, FALSE);
308 g_main_loop_run(main_loop);