Moved network related functions to GLib signal handlers

connect, recv and close events are now handled by GLib signals
(connect, net-recv and net-hup, respectively)
This commit is contained in:
Gergely Polonkai 2013-01-05 22:56:42 +01:00
parent b99f9e1ea2
commit 54b5fe00aa
3 changed files with 205 additions and 110 deletions

View File

@ -73,6 +73,12 @@ remove_client(WmudClient *client, gboolean send_quitmessage)
wmud_client_close(client, send_quitmessage); wmud_client_close(client, send_quitmessage);
} }
static void
hup_client(WmudClient *client)
{
remove_client(client, FALSE);
}
/** /**
* wmud_client_callback: * wmud_client_callback:
* @client: the socket of the client on which the data arrived * @client: the socket of the client on which the data arrived
@ -80,29 +86,23 @@ remove_client(WmudClient *client, gboolean send_quitmessage)
* @client: the WmudClient structure of the client * @client: the WmudClient structure of the client
* *
* Processes incoming client data, and client hangup * Processes incoming client data, and client hangup
*
* Return value: %FALSE if the connection is closed after this call, %TRUE
* otherwise
*/ */
static gboolean static void
wmud_client_callback(GSocket *client_socket, GIOCondition condition, WmudClient *client) recv_client(WmudClient *client)
{ {
GError *err = NULL; GError *err = NULL;
GSocket *client_socket;
if (condition & G_IO_HUP) {
remove_client(client, FALSE);
return FALSE;
} else if ((condition & G_IO_IN) || (condition & G_IO_PRI)) {
gssize len; gssize len;
gchar *buf2; gchar *buf2;
gchar *buf = g_malloc0(sizeof(gchar) * (MAX_RECV_LEN + 1)); gchar *buf = g_malloc0(sizeof(gchar) * (MAX_RECV_LEN + 1));
client_socket = wmud_client_get_socket(client);
if ((len = g_socket_receive(client_socket, buf, MAX_RECV_LEN, NULL, &err)) == 0) { if ((len = g_socket_receive(client_socket, buf, MAX_RECV_LEN, NULL, &err)) == 0) {
g_free(buf); g_free(buf);
remove_client(client, FALSE); remove_client(client, FALSE);
return FALSE; return;
} }
buf2 = buf; buf2 = buf;
@ -187,9 +187,6 @@ wmud_client_callback(GSocket *client_socket, GIOCondition condition, WmudClient
} }
g_free(buf); g_free(buf);
}
return TRUE;
} }
/** /**
@ -207,7 +204,6 @@ gboolean
game_source_callback(GSocket *socket, GIOCondition condition, struct AcceptData *accept_data) game_source_callback(GSocket *socket, GIOCondition condition, struct AcceptData *accept_data)
{ {
GSocket *client_socket; GSocket *client_socket;
GSource *client_source;
GError *err = NULL; GError *err = NULL;
GSocketAddress *remote_addr; GSocketAddress *remote_addr;
WmudClient *client; WmudClient *client;
@ -218,13 +214,12 @@ game_source_callback(GSocket *socket, GIOCondition condition, struct AcceptData
client = wmud_client_new(); client = wmud_client_new();
wmud_client_set_socket(WMUD_CLIENT(client), client_socket); wmud_client_set_socket(WMUD_CLIENT(client), client_socket);
client_source = wmud_client_get_socket_source(client); wmud_client_set_context(client, accept_data->context);
g_signal_connect(client, "net-hup", G_CALLBACK(hup_client), NULL);
g_signal_connect(client, "net-recv", G_CALLBACK(recv_client), NULL);
clients = g_slist_prepend(clients, client); clients = g_slist_prepend(clients, client);
g_source_set_callback(client_source, (GSourceFunc)wmud_client_callback, client, NULL);
g_source_attach(client_source, accept_data->context);
g_clear_error(&err); g_clear_error(&err);
if ((remote_addr = g_socket_get_remote_address(client_socket, &err)) != NULL) { if ((remote_addr = g_socket_get_remote_address(client_socket, &err)) != NULL) {

View File

@ -16,10 +16,29 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "wmudclient.h"
#include "wmudclient.h"
#include "players.h" #include "players.h"
/**
* SECTION:wmudclient
* @short_description: wMUD Client
* @inclide: wmudclient.h
*
* #WmudClient is for storing an active client connection
**/
G_DEFINE_TYPE(WmudClient, wmud_client, G_TYPE_OBJECT);
enum {
SIG_CONNECTED,
SIG_NET_HUP,
SIG_NET_RECV,
SIG_LAST
};
static guint signals[SIG_LAST] = { 0 };
#define WMUD_CLIENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WMUD_TYPE_CLIENT, WmudClientPrivate)) #define WMUD_CLIENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WMUD_TYPE_CLIENT, WmudClientPrivate))
struct _WmudClientPrivate struct _WmudClientPrivate
@ -33,10 +52,9 @@ struct _WmudClientPrivate
gboolean bademail; gboolean bademail;
gint login_try_count; gint login_try_count;
WmudClientYesnoCallback yesno_callback; WmudClientYesnoCallback yesno_callback;
time_t last_recv;
}; };
G_DEFINE_TYPE(WmudClient, wmud_client, G_TYPE_OBJECT);
static void static void
wmud_client_dispose(GObject *gobject) wmud_client_dispose(GObject *gobject)
{ {
@ -62,6 +80,12 @@ wmud_client_finalize(GObject *gobject)
G_OBJECT_CLASS(wmud_client_parent_class)->finalize(gobject); G_OBJECT_CLASS(wmud_client_parent_class)->finalize(gobject);
} }
static void net_recv(WmudClient *self)
{
self->priv->last_recv = time(NULL);
g_message("net-recv");
}
static void static void
wmud_client_class_init(WmudClientClass *klass) wmud_client_class_init(WmudClientClass *klass)
{ {
@ -70,6 +94,47 @@ wmud_client_class_init(WmudClientClass *klass)
gobject_class->dispose = wmud_client_dispose; gobject_class->dispose = wmud_client_dispose;
gobject_class->finalize = wmud_client_finalize; gobject_class->finalize = wmud_client_finalize;
/**
* WmudClient::connected:
* @client: The client emitting the signal
*
* Emitted when a new client connection is accepted
**/
signals[SIG_CONNECTED] = g_signal_newv("connected",
WMUD_TYPE_CLIENT,
G_SIGNAL_RUN_LAST,
NULL,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 0, NULL);
/**
* WmudClient::net-hup:
* @client: The client emitting the signal
*
* Emitted when the remote side closes the connection
**/
signals[SIG_NET_HUP] = g_signal_newv("net-hup",
WMUD_TYPE_CLIENT,
G_SIGNAL_RUN_LAST,
NULL,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 0, NULL);
/**
* WmudClient::net-recv:
* @client: The client emitting the signal
*
* Emitted when data is received through the client socket
**/
signals[SIG_NET_RECV] = g_signal_newv("net-recv",
WMUD_TYPE_CLIENT,
G_SIGNAL_RUN_LAST,
g_cclosure_new(G_CALLBACK(net_recv), NULL, NULL),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0, NULL);
g_type_class_add_private(klass, sizeof(WmudClientPrivate)); g_type_class_add_private(klass, sizeof(WmudClientPrivate));
} }
@ -80,6 +145,20 @@ wmud_client_init(WmudClient *self)
self->priv->socket_source = NULL; self->priv->socket_source = NULL;
self->priv->state = WMUD_CLIENT_STATE_FRESH; self->priv->state = WMUD_CLIENT_STATE_FRESH;
self->priv->buffer = g_string_new(""); self->priv->buffer = g_string_new("");
self->priv->last_recv = time(NULL);
g_signal_emit_by_name(self, "connected", G_TYPE_NONE);
}
static gboolean
net_emitter(GSocket *client_socket, GIOCondition condition, WmudClient *self)
{
if (condition & G_IO_HUP)
g_signal_emit_by_name(self, "net-close", G_TYPE_NONE);
else if ((condition & G_IO_IN) || (condition & G_IO_PRI))
g_signal_emit_by_name(self, "net-recv", G_TYPE_NONE);
return TRUE;
} }
WmudClient * WmudClient *
@ -94,6 +173,8 @@ wmud_client_set_socket(WmudClient *self, GSocket *socket)
/* TODO: Check if a socket is already set! */ /* TODO: Check if a socket is already set! */
self->priv->socket = socket; self->priv->socket = socket;
self->priv->socket_source = g_socket_create_source(socket, G_IO_IN | G_IO_OUT | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL, NULL); self->priv->socket_source = g_socket_create_source(socket, G_IO_IN | G_IO_OUT | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL, NULL);
g_source_set_callback(self->priv->socket_source, (GSourceFunc)net_emitter, self, NULL);
} }
GSocket * GSocket *
@ -233,3 +314,15 @@ wmud_client_get_bademail(WmudClient *self)
return self->priv->bademail; return self->priv->bademail;
} }
void
wmud_client_set_context(WmudClient *self, GMainContext *context)
{
g_source_attach(self->priv->socket_source, context);
}
guint32
wmud_client_get_last_recv_age(WmudClient *self)
{
return (time(NULL) - self->priv->last_recv);
}

View File

@ -31,6 +31,11 @@
#define WMUD_IS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WMUD_TYPE_CLIENT)) #define WMUD_IS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WMUD_TYPE_CLIENT))
#define WMUD_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WMUT_TYPE_CLIENT, WmudClientClass)) #define WMUD_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WMUT_TYPE_CLIENT, WmudClientClass))
/**
* WmudClient:
*
* A connected game client
*/
typedef struct _WmudClient WmudClient; typedef struct _WmudClient WmudClient;
typedef struct _WmudClientClass WmudClientClass; typedef struct _WmudClientClass WmudClientClass;
typedef struct _WmudClientPrivate WmudClientPrivate; typedef struct _WmudClientPrivate WmudClientPrivate;
@ -102,6 +107,8 @@ void wmud_client_increase_login_fail_count(WmudClient *client);
gint wmud_client_get_login_fail_count(WmudClient *client); gint wmud_client_get_login_fail_count(WmudClient *client);
void wmud_client_set_bademail(WmudClient *client, gboolean bademail); void wmud_client_set_bademail(WmudClient *client, gboolean bademail);
gboolean wmud_client_get_bademail(WmudClient *client); gboolean wmud_client_get_bademail(WmudClient *client);
guint32 wmud_client_get_last_recv_age(WmudClient *client);
void wmud_client_set_context(WmudClient *client, GMainContext *context);
#endif /* __WMUD_WMUDCLIENT_H__ */ #endif /* __WMUD_WMUDCLIENT_H__ */