/*
    GSK - a library to write servers
    Copyright (C) 1999-2000 Dave Benson

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA

    Contact:
        daveb@ffem.org <Dave Benson>
*/

#ifndef __GSK_DATAGRAM_SOCKET_H_
#define __GSK_DATAGRAM_SOCKET_H_


#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/* --- typedefs --- */
typedef struct _GskDatagramSocket GskDatagramSocket;
typedef struct _GskDatagramSocketClass GskDatagramSocketClass;

#include "gskconfig.h"
#include "gskbasic.h"
#include "gsksocketaddress.h"
#include "gskgtk.h"

/* --- type macros --- */
GtkType gsk_datagram_socket_get_type();
#define GSK_TYPE_DATAGRAM_SOCKET			(gsk_datagram_socket_get_type ())
#define GSK_DATAGRAM_SOCKET(obj)              (GTK_CHECK_CAST ((obj), GSK_TYPE_DATAGRAM_SOCKET, GskDatagramSocket))
#define GSK_DATAGRAM_SOCKET_CLASS(klass)      (GTK_CHECK_CLASS_CAST ((klass), GSK_TYPE_DATAGRAM_SOCKET, GskDatagramSocketClass))
#define GSK_DATAGRAM_SOCKET_GET_CLASS(obj)    (GSK_DATAGRAM_SOCKET_CLASS(GTK_OBJECT(obj)->klass))
#define GSK_IS_DATAGRAM_SOCKET(obj)           (GTK_CHECK_TYPE ((obj), GSK_TYPE_DATAGRAM_SOCKET))
#define GSK_IS_DATAGRAM_SOCKET_CLASS(klass)   (GTK_CHECK_CLASS_TYPE ((klass), GSK_TYPE_DATAGRAM_SOCKET))

/* --- structures --- */
struct _GskDatagramSocketClass 
{
  GtkObjectClass		object_class;
  GIOError		(*recv_from) (GskDatagramSocket   *datagram_socket,
				      GskSocketAddress    *to_fill,
				      gpointer            *buf_out,
				      int                 *buf_len_out);
  GIOError		(*send_to)   (GskDatagramSocket   *datagram_socket,
				      const GskSocketAddress *destination,
				      gconstpointer        buf,
				      int                  buf_len);
  void  		(*close)     (GskDatagramSocket   *datagram_socket);
};
struct _GskDatagramSocket 
{
  GtkObject		object;
  int			fd;
  unsigned		is_readable : 1;
  unsigned		is_writable : 1;
  int			last_error;
};

/* --- constructors --- */
GskDatagramSocket *gsk_datagram_socket_new(int fd);
GskDatagramSocket *gsk_datagram_socket_new_bound_udp(int port_no);
GskDatagramSocket *gsk_datagram_socket_new_from_spec(const char *spec);
GskDatagramSocket *gsk_datagram_socket_new_client ();

/* --- methods --- */
GIOError        gsk_datagram_socket_recvfrom(GskDatagramSocket *socket,
                                             GskSocketAddress  *address,
                                             gpointer          *buffer,
                                             int               *buffer_length);
GIOError        gsk_datagram_socket_sendto  (GskDatagramSocket *socket,
                                             const GskSocketAddress *address,
                                             gconstpointer      buffer,
                                             int                buffer_length);
int             gsk_datagram_socket_errno   (GskDatagramSocket *socket);
const char     *gsk_datagram_socket_strerror(GskDatagramSocket *socket);
void            gsk_datagram_socket_close   (GskDatagramSocket *socket);
#define gsk_datagram_socket_get_fd(socket)   (GSK_DATAGRAM_SOCKET (socket)->fd)

/* make a system call to get the latest error on this socket,
 * useful after getting a miscellaneous error condition after polling.
 */
void            gsk_datagram_socket_check_err(GskDatagramSocket *socket);

/* multicasting */
typedef enum
{
  GSK_DATAGRAM_TTL_HOST		= 0,
  GSK_DATAGRAM_TTL_SUBNET	= 1,
  GSK_DATAGRAM_TTL_SITE		= 32,
  GSK_DATAGRAM_TTL_REGION	= 64,
  GSK_DATAGRAM_TTL_CONTINENT	= 128,
  GSK_DATAGRAM_TTL_UNRESTRICTED = 255
} GskDatagramTtl;

void            gsk_datagram_socket_set_multicast_ttl
				            (GskDatagramSocket *socket,
					     GskDatagramTtl     ttl);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif
