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);
|
||||
}
|
||||
|
||||
static void
|
||||
hup_client(WmudClient *client)
|
||||
{
|
||||
remove_client(client, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* wmud_client_callback:
|
||||
* @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
|
||||
*
|
||||
* Processes incoming client data, and client hangup
|
||||
*
|
||||
* Return value: %FALSE if the connection is closed after this call, %TRUE
|
||||
* otherwise
|
||||
*/
|
||||
static gboolean
|
||||
wmud_client_callback(GSocket *client_socket, GIOCondition condition, WmudClient *client)
|
||||
static void
|
||||
recv_client(WmudClient *client)
|
||||
{
|
||||
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);
|
||||
|
||||
return FALSE;
|
||||
} 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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
GSocket *client_socket;
|
||||
GSource *client_source;
|
||||
GError *err = NULL;
|
||||
GSocketAddress *remote_addr;
|
||||
WmudClient *client;
|
||||
@ -218,13 +214,12 @@ game_source_callback(GSocket *socket, GIOCondition condition, struct AcceptData
|
||||
|
||||
client = wmud_client_new();
|
||||
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);
|
||||
|
||||
g_source_set_callback(client_source, (GSourceFunc)wmud_client_callback, client, NULL);
|
||||
g_source_attach(client_source, accept_data->context);
|
||||
|
||||
g_clear_error(&err);
|
||||
|
||||
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
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "wmudclient.h"
|
||||
|
||||
#include "wmudclient.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))
|
||||
|
||||
struct _WmudClientPrivate
|
||||
@ -33,10 +52,9 @@ struct _WmudClientPrivate
|
||||
gboolean bademail;
|
||||
gint login_try_count;
|
||||
WmudClientYesnoCallback yesno_callback;
|
||||
time_t last_recv;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(WmudClient, wmud_client, G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
wmud_client_dispose(GObject *gobject)
|
||||
{
|
||||
@ -62,6 +80,12 @@ wmud_client_finalize(GObject *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
|
||||
wmud_client_class_init(WmudClientClass *klass)
|
||||
{
|
||||
@ -70,6 +94,47 @@ wmud_client_class_init(WmudClientClass *klass)
|
||||
gobject_class->dispose = wmud_client_dispose;
|
||||
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));
|
||||
}
|
||||
|
||||
@ -80,6 +145,20 @@ wmud_client_init(WmudClient *self)
|
||||
self->priv->socket_source = NULL;
|
||||
self->priv->state = WMUD_CLIENT_STATE_FRESH;
|
||||
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 *
|
||||
@ -94,6 +173,8 @@ wmud_client_set_socket(WmudClient *self, GSocket *socket)
|
||||
/* TODO: Check if a socket is already set! */
|
||||
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);
|
||||
|
||||
g_source_set_callback(self->priv->socket_source, (GSourceFunc)net_emitter, self, NULL);
|
||||
}
|
||||
|
||||
GSocket *
|
||||
@ -233,3 +314,15 @@ wmud_client_get_bademail(WmudClient *self)
|
||||
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_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 _WmudClientClass WmudClientClass;
|
||||
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);
|
||||
void wmud_client_set_bademail(WmudClient *client, gboolean bademail);
|
||||
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__ */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user