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
20 * Author: Martin Kelm <martinkelm@idxsolutions.de>
24 #include <loudmouth/loudmouth.h>
28 #include "connection.h"
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
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
);
58 debug("Authentificated with: %s", c_user
);
60 g_print("Couldn't authenticate with '%s':\n%s\n", c_user
, error
->message
);
62 g_main_loop_quit(main_loop
);
66 static void conn_open_cb (
67 LmConnection
*connection
, gboolean success
, gpointer user_data
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
);
75 g_printerr("Failed to connect to %s: %s\n", c_host
, error
->message
);
77 g_main_loop_quit(main_loop
);
81 static void conn_close_cb (
82 LmConnection
*connection
, LmDisconnectReason reason
, gpointer user_data
84 lm_connection_close(conn
, NULL
);
85 lm_connection_unref(conn
);
91 case LM_DISCONNECT_REASON_OK
:
92 str
= "LM_DISCONNECT_REASON_OK";
94 case LM_DISCONNECT_REASON_PING_TIME_OUT
:
95 str
= "LM_DISCONNECT_REASON_PING_TIME_OUT";
97 case LM_DISCONNECT_REASON_HUP
:
98 str
= "LM_DISCONNECT_REASON_HUP";
100 case LM_DISCONNECT_REASON_ERROR
:
101 str
= "LM_DISCONNECT_REASON_ERROR";
103 case LM_DISCONNECT_REASON_UNKNOWN
:
105 str
= "LM_DISCONNECT_REASON_UNKNOWN";
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
);
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
);
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
);
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
;
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
++) {
170 to
= g_strdup_printf(
171 "%s", g_array_index(mysqlFields
, gchar
*, fieldsIndex
+j
)
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",
193 mysql_trunk_table("queue_out");
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
) {
204 if (strlen(c_user
) > 0) {
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
);
213 debug("Send loopback message to own user.");
222 static LmSSLResponse
conn_ssl_response(LmSSL
*ssl
, LmSSLStatus status
, gpointer data
) {
223 g_print("SSL Status: %d -> ", status
);
226 case LM_SSL_STATUS_NO_CERT_FOUND
:
227 g_print("No certificate found!\n");
229 case LM_SSL_STATUS_UNTRUSTED_CERT
:
230 g_print("Certificate is not trusted!\n");
232 case LM_SSL_STATUS_CERT_EXPIRED
:
233 g_print("Certificate has expired!\n");
235 case LM_SSL_STATUS_CERT_NOT_ACTIVATED
:
236 g_print("Certificate has not been activated!\n");
238 case LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH
:
239 g_print("Certificate hostname does not match expected hostname!\n");
241 case LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH
:
242 g_print("Certificate fingerprint does not match expected fingerprint!\n");
244 case LM_SSL_STATUS_GENERIC_ERROR
:
245 g_print("Generic SSL error!\n");
249 return LM_SSL_RESPONSE_CONTINUE
;
252 int conn_create(char *host
, int port
, int ssl
,
253 char *user
, char *resource
, char *password
) {
257 c_resource
= resource
;
258 c_password
= password
;
260 debug("Set lm connection and connection data");
262 conn
= lm_connection_new(c_host
);
264 conn_ssl
= lm_ssl_new(NULL
, conn_ssl_response
, NULL
, NULL
);
266 lm_connection_set_ssl(conn
, conn_ssl
);
267 lm_ssl_unref(conn_ssl
);
269 debug("Failed to create ssl connection");
273 lm_connection_set_port(conn
, c_port
);
274 LmMessageHandler
*handler
;
277 jid
= g_strdup_printf("%s@%s", c_user
, c_host
);
278 lm_connection_set_jid(conn
, 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
296 g_print("Couldn't open connection to '%s':\n%s\n", host
, error
->message
);
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
);