IOChannel and UDP
- From: Jochen Friedrich <jochen+gtk-devel-list scram de>
- To: gtk-devel-list redhat com
- Subject: IOChannel and UDP
- Date: Mon, 6 Mar 2000 16:20:58 +0100 (CET)
Hi there,
in order to use UDP with glib, currently you can use the IOChannel, but
most of the provided methods don't make sense (you can't just read or
write to an unconnected socket, and even on a connected socket you would
loose information).
I thought about adding a similar architecture like GIOChannel /
GIOUnixChannel for UDP (see attached files for a rough idea. I called the
general layer GIOMessage and the UDP implementation GIODgram).
David Helder pointed out that we might better derive from GIOChannel and
disable the methods that are impossible for datagrams. I'm not sure which
approach is the cleaner one. In one case you might end up with some
duplicate code, in the other case we have "dummy" methods we carry around
in the object.
Which approach do you prefer?
Thanks,
Jochen
#include <glib.h>
#include "giomessage.h"
void
g_io_message_init (GIOMessage *message)
{
message->message_flags = 0;
message->ref_count = 1;
}
void
g_io_message_ref (GIOMessage *message)
{
g_return_if_fail (message != NULL);
message->ref_count++;
}
void
g_io_message_unref (GIOMessage *message)
{
g_return_if_fail (message != NULL);
message->ref_count--;
if (message->ref_count == 0)
message->funcs->io_free (message);
}
GIOError
g_io_message_recv (GIOMessage *message,
gchar *buf,
guint count,
guint *bytes_read,
GIOAddress sender)
{
g_return_val_if_fail (message != NULL, G_IO_ERROR_UNKNOWN);
return message->funcs->io_recv (message, buf, count, bytes_read, sender);
}
GIOError
g_io_message_send (GIOMessage *message,
gchar *buf,
guint count,
guint *bytes_written,
GIOAddress recipient)
{
g_return_val_if_fail (message != NULL, G_IO_ERROR_UNKNOWN);
return message->funcs->io_send (message, buf, count, bytes_written, recipient);
}
void
g_io_message_close (GIOMessage *message)
{
g_return_if_fail (message != NULL);
message->funcs->io_close (message);
}
guint
g_io_madd_watch_full (GIOMessage *message,
gint priority,
GIOCondition condition,
GIOMFunc func,
gpointer user_data,
GDestroyNotify notify)
{
g_return_val_if_fail (message != NULL, 0);
return message->funcs->io_add_watch (message, priority, condition,
func, user_data, notify);
}
guint
g_io_madd_watch (GIOMessage *message,
GIOCondition condition,
GIOMFunc func,
gpointer user_data)
{
return g_io_madd_watch_full (message, 0, condition, func, user_data, NULL);
}
/* GIOMessage
*/
typedef struct _GIOMFuncs GIOMFuncs;
typedef struct _GIOMessage GIOMessage;
typedef gpointer GIOAddress;
struct _GIOMessage
{
guint message_flags;
guint ref_count;
GIOMFuncs *funcs;
};
typedef gboolean (*GIOMFunc) (GIOMessage *source,
GIOCondition condition,
gpointer data);
struct _GIOMFuncs
{
GIOError (*io_recv) (GIOMessage *message,
gchar *buf,
guint count,
guint *bytes_read,
GIOAddress sender);
GIOError (*io_send) (GIOMessage *message,
gchar *buf,
guint count,
guint *bytes_written,
GIOAddress recipient);
void (*io_close) (GIOMessage *message);
guint (*io_add_watch) (GIOMessage *message,
gint priority,
GIOCondition condition,
GIOMFunc func,
gpointer user_data,
GDestroyNotify notify);
void (*io_free) (GIOMessage *message);
};
void g_io_message_init (GIOMessage *message);
void g_io_message_ref (GIOMessage *message);
void g_io_message_unref (GIOMessage *message);
GIOError g_io_message_recv (GIOMessage *message,
gchar *buf,
guint count,
guint *bytes_read,
GIOAddress sender);
GIOError g_io_message_send (GIOMessage *message,
gchar *buf,
guint count,
guint *bytes_written,
GIOAddress recipient);
void g_io_message_close (GIOMessage *message);
guint g_io_madd_watch_full (GIOMessage *message,
gint priority,
GIOCondition condition,
GIOMFunc func,
gpointer user_data,
GDestroyNotify notify);
guint g_io_madd_watch (GIOMessage *message,
GIOCondition condition,
GIOMFunc func,
gpointer user_data);
#include <glib.h>
#include <sys/socket.h>
#include "giomessage.h"
#include "giodgram.h"
#include "errno.h"
static gboolean
g_io_dgram_prepare (gpointer source_data,
GTimeVal *current_time,
gint *timeout,
gpointer user_data);
static gboolean
g_io_dgram_check (gpointer source_data,
GTimeVal *current_time,
gpointer user_data);
static gboolean
g_io_dgram_dispatch (gpointer source_data,
GTimeVal *current_time,
gpointer user_data);
static void
g_io_dgram_destroy (gpointer source_data);
static GIOError
g_io_dgram_recv (GIOMessage *message,
gchar *buf,
guint count,
guint *bytes_read,
GIOAddress address);
static GIOError
g_io_dgram_send(GIOMessage *message,
gchar *buf,
guint count,
guint *bytes_written,
GIOAddress address);
static void
g_io_dgram_close (GIOMessage *message);
static guint
g_io_dgram_add_watch (GIOMessage *message,
gint priority,
GIOCondition condition,
GIOMFunc func,
gpointer user_data,
GDestroyNotify notify);
static void
g_io_dgram_free (GIOMessage *message);
GSourceFuncs dgram_watch_funcs = {
g_io_dgram_prepare,
g_io_dgram_check,
g_io_dgram_dispatch,
g_io_dgram_destroy
};
GIOMFuncs dgram_message_funcs = {
g_io_dgram_recv,
g_io_dgram_send,
g_io_dgram_close,
g_io_dgram_add_watch,
g_io_dgram_free,
};
static gboolean
g_io_dgram_prepare (gpointer source_data,
GTimeVal *current_time,
gint *timeout,
gpointer user_data)
{
*timeout = -1;
return FALSE;
}
static gboolean
g_io_dgram_check (gpointer source_data,
GTimeVal *current_time,
gpointer user_data)
{
GIODgramWatch *data = source_data;
return (data->pollfd.revents & data->condition);
}
static gboolean
g_io_dgram_dispatch (gpointer source_data,
GTimeVal *current_time,
gpointer user_data)
{
GIODgramWatch *data = source_data;
return (*data->callback)(data->message,
data->pollfd.revents & data->condition,
user_data);
}
static void
g_io_dgram_destroy (gpointer source_data)
{
GIODgramWatch *data = source_data;
g_main_remove_poll (&data->pollfd);
g_io_message_unref (data->message);
g_free (data);
}
static GIOError
g_io_dgram_recv (GIOMessage *message,
gchar *buf,
guint count,
guint *bytes_read,
GIOAddress address)
{
GIODgramMessage *dgram_message = (GIODgramMessage *)message;
gint result;
GIODgramAddress *saddr;
saddr = (GIODgramAddress *)address;
result = recvfrom (dgram_message->fd, buf, count, 0, &(saddr->addr),
&(saddr->len));
if (result < 0)
{
*bytes_read = 0;
switch (errno)
{
case EINVAL:
return G_IO_ERROR_INVAL;
case EAGAIN:
return G_IO_ERROR_AGAIN;
default:
return G_IO_ERROR_UNKNOWN;
}
}
else
{
*bytes_read = result;
return G_IO_ERROR_NONE;
}
}
static GIOError
g_io_dgram_send(GIOMessage *message,
gchar *buf,
guint count,
guint *bytes_written,
GIOAddress address)
{
GIODgramMessage *dgram_message = (GIODgramMessage *)message;
gint result;
GIODgramAddress *saddr;
saddr = (GIODgramAddress *)address;
result = sendto (dgram_message->fd, buf, count, 0, &(saddr->addr),
saddr->len);
if (result < 0)
{
*bytes_written = 0;
switch (errno)
{
case EINVAL:
return G_IO_ERROR_INVAL;
case EAGAIN:
return G_IO_ERROR_AGAIN;
default:
return G_IO_ERROR_UNKNOWN;
}
}
else
{
*bytes_written = result;
return G_IO_ERROR_NONE;
}
}
static void
g_io_dgram_close (GIOMessage *message)
{
GIODgramMessage *dgram_message = (GIODgramMessage *)message;
close (dgram_message->fd);
}
static void
g_io_dgram_free (GIOMessage *message)
{
GIODgramMessage *dgram_message = (GIODgramMessage *)message;
g_free (dgram_message);
}
static guint
g_io_dgram_add_watch (GIOMessage *message,
gint priority,
GIOCondition condition,
GIOMFunc func,
gpointer user_data,
GDestroyNotify notify)
{
GIODgramWatch *watch = g_new (GIODgramWatch, 1);
GIODgramMessage *dgram_message = (GIODgramMessage *)message;
watch->message = message;
g_io_message_ref (message);
watch->callback = func;
watch->condition = condition;
watch->pollfd.fd = dgram_message->fd;
watch->pollfd.events = condition;
g_main_add_poll (&watch->pollfd, priority);
return g_source_add (priority, TRUE, &dgram_watch_funcs, watch, user_data, notify);
}
GIOMessage *
g_io_message_dgram_new (gint fd)
{
GIODgramMessage *dgram_message = g_new (GIODgramMessage, 1);
GIOMessage *message = (GIOMessage *)dgram_message;
g_io_message_init (message);
message->funcs = &dgram_message_funcs;
dgram_message->fd = fd;
return message;
}
gint
g_io_message_dgram_get_fd (GIOMessage *message)
{
GIODgramMessage *dgram_message = (GIODgramMessage *)message;
return dgram_message->fd;
}
/*
* Datagram Messages
*/
typedef struct _GIODgramMessage GIODgramMessage;
typedef struct _GIODgramWatch GIODgramWatch;
typedef struct _GIODgramAddress GIODgramAddress;
struct _GIODgramMessage {
GIOMessage message;
gint fd;
};
struct _GIODgramWatch {
GPollFD pollfd;
GIOMessage *message;
GIOCondition condition;
GIOMFunc callback;
};
struct _GIODgramAddress {
socklen_t len;
struct sockaddr addr;
};
GIOMessage * g_io_message_dgram_new (gint fd);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]