Add command menu for messages received from loopback.
[cascardo/f2fchat.git] / message.c
1 /*
2  *  Copyright (C) 2013  Thadeu Lima de Souza Cascardo <cascardo@cascardo.info>
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 3 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 along
15  *  with this program; if not, write to the Free Software Foundation, Inc.,
16  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18
19 #include "message.h"
20 #include "friend.h"
21 #include "menu.h"
22 #include <glib.h>
23 #include <gio/gio.h>
24
25 #include <stdio.h>
26
27 gboolean ping_timeout(gpointer data)
28 {
29         struct friend *friend = data;
30         friend_timeout(friend);
31         return G_SOURCE_REMOVE;
32 }
33
34 static GIOChannel *uchannel;
35 static GSocket *gusock;
36
37 static void command(char *buffer, size_t len, GSocketAddress *address)
38 {
39         gchar **args;
40         args = g_strsplit(buffer, " ", -1);
41         menu_run(args, address);
42         g_strfreev(args);
43 }
44
45 gboolean message_incoming(GIOChannel *channel, GIOCondition cond, gpointer data)
46 {
47         size_t len;
48         char *buffer;
49         GSocketAddress *address;
50         GInetAddress *iaddress;
51         if (!gusock) {
52                 gusock = g_socket_new_from_fd(g_io_channel_unix_get_fd(channel), NULL);
53         }
54         len = g_socket_get_available_bytes(gusock);
55         if (len <= 0) {
56                 goto out;
57         }
58         buffer = g_malloc(len);
59         len = g_socket_receive_from(gusock, &address, buffer, len, NULL, NULL);
60         iaddress = g_inet_socket_address_get_address(G_INET_SOCKET_ADDRESS(address));
61         if (g_inet_address_get_is_loopback(iaddress)) {
62                 command(buffer, len, address);
63         } else {
64                 struct friend *friend;
65                 uint16_t port = g_inet_socket_address_get_port(G_INET_SOCKET_ADDRESS(address));
66                 friend = friend_get_by_address(iaddress, port);
67                 if (friend) {
68                         printf("got message from %s\n", friend_get_name(friend));
69                         friend_got_message(friend, buffer, len);
70                 } else {
71                         printf("could not find friend from address %s\n", g_inet_address_to_string(iaddress));
72                 }
73         }
74         g_object_unref(address);
75         g_free(buffer);
76 out:
77         return TRUE;
78 }
79
80 int message_init(GSocket *sock)
81 {
82         uchannel = g_io_channel_unix_new(g_socket_get_fd(sock));
83         g_io_add_watch(uchannel, G_IO_IN, message_incoming, NULL);
84         return 0;
85 }
86
87 int ping(struct friend *friend)
88 {
89         int err;
90         char ping[5] = "PING";
91         err = friend_send_message(friend, ping, 4);
92         if (!err)
93                 g_timeout_add(2000, ping_timeout, friend);
94         return err;
95 }
96
97 int pong(struct friend *friend)
98 {
99         char pong[5] = "PONG";
100         return friend_send_message(friend, pong, 4);
101 }