2 * Copyright (C) 2003-2004 Imendio AB
3 * Copyright (C) 2008 Carl Worth
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see http://www.gnu.org/licenses/ .
19 * Carl Worth <cworth@cworth.org>
30 loudgame_quit (loudgame_t *lg, int return_value)
34 lg->return_value = return_value;
38 if (! lm_connection_close (lg->connection, &error))
40 g_print ("An error occurred during lm_connection_close: %s\n",
43 lm_connection_unref (lg->connection);
44 lg->connection = NULL;
47 g_main_loop_quit (lg->main_loop);
51 authentication_cb (LmConnection *connection, gboolean result, gpointer closure)
54 loudgame_t *lg = closure;
57 g_print ("Authentication for %s failed\n", lg->name);
58 loudgame_quit (lg, 1);
62 m = lm_message_new_with_sub_type (NULL,
63 LM_MESSAGE_TYPE_PRESENCE,
64 LM_MESSAGE_SUB_TYPE_AVAILABLE);
66 lm_connection_send (connection, m, NULL);
71 connection_open_cb (LmConnection *connection, gboolean result, loudgame_t *lg)
73 lm_connection_authenticate (connection,
74 lg->name, lg->passwd, "loudgame",
75 authentication_cb, lg, FALSE, NULL);
79 loudgame_send (loudgame_t *lg,
87 reply = lm_message_new (peer, LM_MESSAGE_TYPE_MESSAGE);
89 lm_message_node_add_child (reply->node, "body", message);
91 result = lm_connection_send (lg->connection, reply, &error);
92 lm_message_unref (reply);
95 g_error ("lm_connection_send failed: %s\n",
97 loudgame_quit (lg, 1);
102 loudgame_vsendf (loudgame_t *lg,
109 str = g_strdup_vprintf (format, va);
111 loudgame_send (lg, peer, str);
117 loudgame_sendf (loudgame_t *lg,
124 va_start (va, format);
126 loudgame_vsendf (lg, peer, format, va);
131 typedef struct _loudgame_broadcast_data
135 } loudgame_broadcast_data_t;
138 loudgame_broadcast_cb (void *key,
142 loudgame_broadcast_data_t *lbd = closure;
145 loudgame_send (lbd->lg, peer, lbd->message);
149 loudgame_broadcast (loudgame_t *lg,
152 loudgame_broadcast_data_t lbd;
155 lbd.message = message;
157 g_hash_table_foreach (lg->players,
158 loudgame_broadcast_cb, &lbd);
162 loudgame_vbroadcastf (loudgame_t *lg,
168 str = g_strdup_vprintf (format, va);
170 loudgame_broadcast (lg, str);
176 loudgame_broadcastf (loudgame_t *lg,
182 va_start (va,format);
184 loudgame_vbroadcastf (lg, format, va);
190 handle_command (loudgame_t *lg,
194 if (strcmp (command, "quit") == 0) {
195 loudgame_quit (lg, 0);
199 loudgame_sendf (lg, "Unknown command: '%s'", command);
203 handle_say (loudgame_t *lg,
207 loudgame_broadcastf (lg, "%s: %s", peer, message);
211 handle_whisper (loudgame_t *lg,
215 const char *recipient, *space, *message;
217 space = strchr (body, ' ');
219 loudgame_sendf (lg, peer,
220 "Error: whisper should be of the form 'user message'");
224 recipient = g_strndup (body, space - body);
228 loudgame_sendf (lg, recipient, "*%s*: %s", peer, message);
231 static LmHandlerResult
232 handle_messages (LmMessageHandler *handler,
233 LmConnection *connection,
237 loudgame_t *lg = closure;
240 const char *body_str;
242 peer = lm_message_node_get_attribute (m->node, "from");
244 body = lm_message_node_get_child (m->node, "body");
246 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
248 if (! g_hash_table_lookup_extended (lg->players, peer,
251 char *peer_copy = g_strdup (peer);
252 g_hash_table_insert (lg->players, peer_copy, NULL);
253 loudgame_broadcastf (lg, "%s has joined the game", peer);
256 body_str = lm_message_node_get_value (body);
259 if (body_str[0] == '%')
260 handle_command (lg, peer, body_str + 1);
261 else if (strncmp (body_str, "say ", 4) == 0)
262 handle_say (lg, peer, body_str + 4);
263 else if (strncmp (body_str, "whisper ", 8) == 0)
264 handle_whisper (lg, peer, body_str + 8);
265 else if (lg->handle_message)
266 (lg->handle_message) (lg, peer, body_str);
269 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
273 make_connection (gpointer closure)
276 LmMessageHandler *handler;
278 GError *error = NULL;
282 lg->connection = lm_connection_new (lg->server);
284 jid = g_strdup_printf ("%s@%s", lg->name, lg->server);
285 lm_connection_set_jid (lg->connection, jid);
288 handler = lm_message_handler_new (handle_messages, lg, NULL);
289 lm_connection_register_message_handler (lg->connection,
291 LM_MESSAGE_TYPE_MESSAGE,
292 LM_HANDLER_PRIORITY_NORMAL);
294 lm_message_handler_unref (handler);
296 if (! lm_connection_open (lg->connection,
297 (LmResultFunction) connection_open_cb,
300 g_print ("Failed to open connection to %s: %s.\n",
301 lg->server, error->message);
302 loudgame_quit (lg, 1);
305 /* It seems to be necessary to explicitly tell the server we're
306 * still here. Let's see if one keep-alive every 60 seconds is
308 lm_connection_set_keep_alive_rate (lg->connection, 60);
310 /* Return false to not schedule another call. */
315 loudgame_init (loudgame_t *lg, int argc, char **argv)
318 g_print ("Usage: %s <server> <username> <password>\n", argv[0]);
322 lg->server = argv[1];
324 lg->passwd = argv[3];
326 lg->connection = NULL;
328 lg->main_loop = g_main_loop_new (NULL, FALSE);
329 lg->players = g_hash_table_new_full (g_str_hash, g_str_equal,
330 g_free, /* key_destroy */
331 NULL /*value_destroy */);
333 lg->return_value = 0;
335 lg->handle_message = NULL;
341 loudgame_fini (loudgame_t *lg)
343 g_main_loop_unref (lg->main_loop);
344 g_hash_table_destroy (lg->players);
348 loudgame_run (loudgame_t *lg)
350 g_idle_add (make_connection, lg);
352 g_main_loop_run (lg->main_loop);
356 return lg->return_value;