/*
    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_STREAM_SOCKET_H_
#define __GSK_STREAM_SOCKET_H_


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

/* --- typedefs --- */
typedef struct _GskStreamSocket GskStreamSocket;
typedef struct _GskStreamSocketClass GskStreamSocketClass;

#include "gskgtk.h"
#include "gsksocketaddress.h"

/* --- type macros --- */
GtkType gsk_stream_socket_get_type();
#define GSK_TYPE_STREAM_SOCKET			(gsk_stream_socket_get_type ())
#define GSK_STREAM_SOCKET(obj)              (GTK_CHECK_CAST ((obj), GSK_TYPE_STREAM_SOCKET, GskStreamSocket))
#define GSK_STREAM_SOCKET_CLASS(klass)      (GTK_CHECK_CLASS_CAST ((klass), GSK_TYPE_STREAM_SOCKET, GskStreamSocketClass))
#define GSK_STREAM_SOCKET_GET_CLASS(obj)    (GSK_STREAM_SOCKET_CLASS(GTK_OBJECT(obj)->klass))
#define GSK_IS_STREAM_SOCKET(obj)           (GTK_CHECK_TYPE ((obj), GSK_TYPE_STREAM_SOCKET))
#define GSK_IS_STREAM_SOCKET_CLASS(klass)   (GTK_CHECK_CLASS_TYPE ((klass), GSK_TYPE_STREAM_SOCKET))

typedef struct iovec GskIOVec;

/* --- structures --- */
struct _GskStreamSocketClass 
{
  GtkObjectClass    object_class;

  /* As long as `connection_events_pending' is nonzero,
   * you must try and call connect ().
   * if connect () returns FALSE, there was an error and you should
   * destroy this socket. */
  gboolean        (*connect) (GskStreamSocket  *socket,
			      GIOCondition      events);
  int             (*read)    (GskStreamSocket  *socket,
			      void             *buf,
			      int               n);

  int             (*write)   (GskStreamSocket  *socket,
			      const void       *buf,
			      int               n);
  int             (*writev)  (GskStreamSocket  *socket,
			      const GskIOVec   *iobufs,
			      int               n);
  gboolean        (*shutdown)(GskStreamSocket  *socket,
			      int               how);
  void            (*close)   (GskStreamSocket  *socket);

};
struct _GskStreamSocket 
{
  GtkObject		  object;
  int                     read_fd;
  int                     write_fd;
  /* Whether the socket is readable/writable from the `shutdown'
   * perspective. */
  unsigned                is_readable : 1,
			  is_writable : 1,
			  got_eof : 1;

  int                     last_error;
  /* For sockets that are still connecting: */
  GIOCondition            connection_events_pending;
};

/* --- prototypes --- */
/* pass in the events to wait for to connect */
GskStreamSocket *gsk_stream_socket_new_raw (int                 fd,
					    GIOCondition        conn_events);
GskStreamSocket *gsk_stream_socket_new_from_pair
     					   (int                 in_fd,
                                            int                 out_fd);

int              gsk_stream_socket_read    (GskStreamSocket    *socket,
                                            void               *buffer,
                                            int                 buffer_length);
int              gsk_stream_socket_write   (GskStreamSocket    *socket,
                                            const void         *buffer,
                                            int                 buffer_length);
int              gsk_stream_socket_writev  (GskStreamSocket    *socket,
                                            GskIOVec           *bufs,
                                            int                 n);
gboolean         gsk_stream_socket_shutdown(GskStreamSocket    *socket,
                                            int                 how);
void             gsk_stream_socket_close   (GskStreamSocket    *stream_socket);
gboolean         gsk_stream_socket_finish_connecting
				           (GskStreamSocket    *socket,
                                            int                 events_got);

int              gsk_stream_socket_errno   (GskStreamSocket    *socket);
const char*      gsk_stream_socket_strerror(GskStreamSocket    *socket);

/* --- create newly connecting sockets ---  */
GskStreamSocket *gsk_stream_socket_new_connecting_tcp(const GskSocketAddress *);
GskStreamSocket *gsk_stream_socket_new_connecting_unix(const char *socket_path);


#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif
