From f7c4d6ccc1fd3c452481a2d085486f8dec3860fb Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Thu, 10 Oct 2013 18:33:07 -0300 Subject: [PATCH] Respond pings with pongs. Set the state of a friend as offline if timeout goes without receiving PONG. If PING is received, send PONG. If PONG is received, set state as online. --- friend.c | 24 ++++++++++++++++++++++++ friend.h | 3 +++ message.c | 16 +++++++++++++--- message.h | 1 + 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/friend.c b/friend.c index 68deccd..03d306d 100644 --- a/friend.c +++ b/friend.c @@ -27,11 +27,18 @@ #include #include "message.h" +enum { + STATE_OFFLINE, + STATE_PINGED, + STATE_ONLINE, +}; + struct friend { char *name; char *address; uint16_t port; GInetSocketAddress *saddr; + int state; }; static GSocket *usock; @@ -64,6 +71,22 @@ int friend_send_message(struct friend *friend, char *buffer, size_t len) return 0; } +void friend_timeout(struct friend *friend) +{ + if (friend->state == STATE_PINGED) { + friend->state = STATE_OFFLINE; + } +} + +void friend_got_message(struct friend *friend, char *buffer, size_t len) +{ + if (len >= 4 && !strncmp(buffer, "PING", 4)) { + pong(friend); + } else if (len >= 4 && !strncmp(buffer, "PONG", 4)) { + friend->state = STATE_ONLINE; + } +} + struct cache { GList *friends; }; @@ -123,6 +146,7 @@ int cache_add_friend(struct cache *cache, char *name, char *address, uint16_t po g_object_unref(addr); cache->friends = g_list_append(cache->friends, friend); ping(friend); + friend->state = STATE_PINGED; return 0; } diff --git a/friend.h b/friend.h index 76a22bd..efe5f65 100644 --- a/friend.h +++ b/friend.h @@ -38,4 +38,7 @@ struct friend *friend_get_by_address(GInetAddress *address, uint16_t port); char *friend_get_name(); +void friend_timeout(struct friend *friend); +void friend_got_message(struct friend *friend, char *buffer, size_t len); + #endif diff --git a/message.c b/message.c index 25b5160..8c6dafd 100644 --- a/message.c +++ b/message.c @@ -26,6 +26,7 @@ gboolean ping_timeout(gpointer data) { struct friend *friend = data; + friend_timeout(friend); return G_SOURCE_REMOVE; } @@ -58,7 +59,7 @@ gboolean message_incoming(GIOChannel *channel, GIOCondition cond, gpointer data) friend = friend_get_by_address(iaddress, port); if (friend) { printf("got message from %s\n", friend_get_name(friend)); - g_source_remove_by_user_data(friend); + friend_got_message(friend, buffer, len); } else { printf("could not find friend from address %s\n", g_inet_address_to_string(iaddress)); } @@ -77,7 +78,16 @@ int message_init(GSocket *sock) int ping(struct friend *friend) { + int err; char ping[5] = "PING"; - friend_send_message(friend, ping, 4); - g_timeout_add(2000, ping_timeout, friend); + err = friend_send_message(friend, ping, 4); + if (!err) + g_timeout_add(2000, ping_timeout, friend); + return err; +} + +int pong(struct friend *friend) +{ + char pong[5] = "PONG"; + return friend_send_message(friend, pong, 4); } diff --git a/message.h b/message.h index d2fbcc1..cd018c9 100644 --- a/message.h +++ b/message.h @@ -24,5 +24,6 @@ int message_init(GSocket *sock); int ping(struct friend *friend); +int pong(struct friend *friend); #endif -- 2.20.1