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:
parent
b99f9e1ea2
commit
54b5fe00aa
@ -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,116 +86,107 @@ 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;
|
||||||
|
gssize len;
|
||||||
|
gchar *buf2;
|
||||||
|
gchar *buf = g_malloc0(sizeof(gchar) * (MAX_RECV_LEN + 1));
|
||||||
|
|
||||||
if (condition & G_IO_HUP) {
|
client_socket = wmud_client_get_socket(client);
|
||||||
|
|
||||||
|
if ((len = g_socket_receive(client_socket, buf, MAX_RECV_LEN, NULL, &err)) == 0) {
|
||||||
|
g_free(buf);
|
||||||
remove_client(client, FALSE);
|
remove_client(client, FALSE);
|
||||||
|
|
||||||
return FALSE;
|
return;
|
||||||
} else if ((condition & G_IO_IN) || (condition & G_IO_PRI)) {
|
|
||||||
gssize len;
|
|
||||||
gchar *buf2;
|
|
||||||
gchar *buf = g_malloc0(sizeof(gchar) * (MAX_RECV_LEN + 1));
|
|
||||||
|
|
||||||
if ((len = g_socket_receive(client_socket, buf, MAX_RECV_LEN, NULL, &err)) == 0) {
|
|
||||||
g_free(buf);
|
|
||||||
remove_client(client, FALSE);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf2 = buf;
|
|
||||||
while (TRUE) {
|
|
||||||
char *r = strchr((char *)buf2, '\r'),
|
|
||||||
*n = strchr((char *)buf2, '\n');
|
|
||||||
|
|
||||||
if (r || n) {
|
|
||||||
gint i,
|
|
||||||
sloc = -1;
|
|
||||||
|
|
||||||
if ((r < n) && r) {
|
|
||||||
if (wmud_client_get_buffer_length(client) > 0)
|
|
||||||
g_string_append_len(wmud_client_get_buffer(client), buf2, (r - buf2));
|
|
||||||
else
|
|
||||||
g_string_overwrite_len(wmud_client_get_buffer(client), 0, buf2, (r - buf2));
|
|
||||||
buf2 = r;
|
|
||||||
} else if (n) {
|
|
||||||
if (wmud_client_get_buffer_length(client) > 0)
|
|
||||||
g_string_append_len(wmud_client_get_buffer(client), buf2, (n - buf2));
|
|
||||||
else
|
|
||||||
g_string_overwrite_len(wmud_client_get_buffer(client), 0, buf2, (n - buf2));
|
|
||||||
buf2 = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove telnet codes from the string */
|
|
||||||
for (i = 0; i < wmud_client_get_buffer_length(client); i++) {
|
|
||||||
guchar c = (wmud_client_get_buffer(client)->str)[i];
|
|
||||||
|
|
||||||
if ((c >= 240) || (c == 1)) {
|
|
||||||
if (sloc == -1)
|
|
||||||
sloc = i;
|
|
||||||
} else {
|
|
||||||
if (sloc != -1) {
|
|
||||||
g_string_erase(wmud_client_get_buffer(client), sloc, i - sloc);
|
|
||||||
sloc = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sloc != -1)
|
|
||||||
g_string_erase(wmud_client_get_buffer(client), sloc, -1);
|
|
||||||
|
|
||||||
switch (wmud_client_get_state(client))
|
|
||||||
{
|
|
||||||
case WMUD_CLIENT_STATE_FRESH:
|
|
||||||
state_fresh(client);
|
|
||||||
break;
|
|
||||||
case WMUD_CLIENT_STATE_PASSWAIT:
|
|
||||||
state_passwait(client);
|
|
||||||
break;
|
|
||||||
case WMUD_CLIENT_STATE_MENU:
|
|
||||||
state_menu(client);
|
|
||||||
break;
|
|
||||||
case WMUD_CLIENT_STATE_INGAME:
|
|
||||||
wmud_interpret_game_command(client);
|
|
||||||
break;
|
|
||||||
case WMUD_CLIENT_STATE_YESNO:
|
|
||||||
state_yesno(client);
|
|
||||||
break;
|
|
||||||
case WMUD_CLIENT_STATE_REGISTERING:
|
|
||||||
state_registering(client);
|
|
||||||
break;
|
|
||||||
case WMUD_CLIENT_STATE_REGEMAIL_CONFIRM:
|
|
||||||
state_regemail_confirm(client);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
g_string_erase(wmud_client_get_buffer(client), 0, -1);
|
|
||||||
|
|
||||||
for (; ((*buf2 == '\r') || (*buf2 == '\n')) && *buf2; buf2++);
|
|
||||||
|
|
||||||
if (!*buf2)
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
if (wmud_client_get_buffer_length(client) > 0)
|
|
||||||
g_string_append(wmud_client_get_buffer(client), buf2);
|
|
||||||
else
|
|
||||||
g_string_overwrite(wmud_client_get_buffer(client), 0, buf2);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free(buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
buf2 = buf;
|
||||||
|
while (TRUE) {
|
||||||
|
char *r = strchr((char *)buf2, '\r'),
|
||||||
|
*n = strchr((char *)buf2, '\n');
|
||||||
|
|
||||||
|
if (r || n) {
|
||||||
|
gint i,
|
||||||
|
sloc = -1;
|
||||||
|
|
||||||
|
if ((r < n) && r) {
|
||||||
|
if (wmud_client_get_buffer_length(client) > 0)
|
||||||
|
g_string_append_len(wmud_client_get_buffer(client), buf2, (r - buf2));
|
||||||
|
else
|
||||||
|
g_string_overwrite_len(wmud_client_get_buffer(client), 0, buf2, (r - buf2));
|
||||||
|
buf2 = r;
|
||||||
|
} else if (n) {
|
||||||
|
if (wmud_client_get_buffer_length(client) > 0)
|
||||||
|
g_string_append_len(wmud_client_get_buffer(client), buf2, (n - buf2));
|
||||||
|
else
|
||||||
|
g_string_overwrite_len(wmud_client_get_buffer(client), 0, buf2, (n - buf2));
|
||||||
|
buf2 = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove telnet codes from the string */
|
||||||
|
for (i = 0; i < wmud_client_get_buffer_length(client); i++) {
|
||||||
|
guchar c = (wmud_client_get_buffer(client)->str)[i];
|
||||||
|
|
||||||
|
if ((c >= 240) || (c == 1)) {
|
||||||
|
if (sloc == -1)
|
||||||
|
sloc = i;
|
||||||
|
} else {
|
||||||
|
if (sloc != -1) {
|
||||||
|
g_string_erase(wmud_client_get_buffer(client), sloc, i - sloc);
|
||||||
|
sloc = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sloc != -1)
|
||||||
|
g_string_erase(wmud_client_get_buffer(client), sloc, -1);
|
||||||
|
|
||||||
|
switch (wmud_client_get_state(client))
|
||||||
|
{
|
||||||
|
case WMUD_CLIENT_STATE_FRESH:
|
||||||
|
state_fresh(client);
|
||||||
|
break;
|
||||||
|
case WMUD_CLIENT_STATE_PASSWAIT:
|
||||||
|
state_passwait(client);
|
||||||
|
break;
|
||||||
|
case WMUD_CLIENT_STATE_MENU:
|
||||||
|
state_menu(client);
|
||||||
|
break;
|
||||||
|
case WMUD_CLIENT_STATE_INGAME:
|
||||||
|
wmud_interpret_game_command(client);
|
||||||
|
break;
|
||||||
|
case WMUD_CLIENT_STATE_YESNO:
|
||||||
|
state_yesno(client);
|
||||||
|
break;
|
||||||
|
case WMUD_CLIENT_STATE_REGISTERING:
|
||||||
|
state_registering(client);
|
||||||
|
break;
|
||||||
|
case WMUD_CLIENT_STATE_REGEMAIL_CONFIRM:
|
||||||
|
state_regemail_confirm(client);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
g_string_erase(wmud_client_get_buffer(client), 0, -1);
|
||||||
|
|
||||||
|
for (; ((*buf2 == '\r') || (*buf2 == '\n')) && *buf2; buf2++);
|
||||||
|
|
||||||
|
if (!*buf2)
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (wmud_client_get_buffer_length(client) > 0)
|
||||||
|
g_string_append(wmud_client_get_buffer(client), buf2);
|
||||||
|
else
|
||||||
|
g_string_overwrite(wmud_client_get_buffer(client), 0, buf2);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -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__ */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user