/* BTP library - Banana Tree Protocol
 * Copyright (C) 1999-2001  The Regents of the University of Michigan
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library 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.
 */

#ifndef _B_CONN_H
#define _B_CONN_H

#include <stdio.h>
#include <gnet/gnet.h>


/**

   BConn represents a connection.

   Most BConn functions are in the file, but see also b_conn_connect
   and b_conn_accept.  (b_conn_ping and b_conn_io are internal).

 */


/* Maximum total size of MCAST packets in packet_queue. */
#define B_CONN_MAX_MCAST_SIZE	16384

/* Size of read buffer */
#define BCONN_BUF_SIZE	4096

typedef struct _BConn BConn;
#define BPacket struct _BPacket
#define BPeer   struct _BPeer
#define BGroup  struct _BGroup


typedef enum _BConnStatus
{
  B_CONN_STATUS_UNCONNECTED,		/* Not connected (default)	*/
  B_CONN_STATUS_CONNECTING,		/* In process of connecting	*/
  B_CONN_STATUS_ACCEPTED,		/* Accepted, but not connected	*/
  B_CONN_STATUS_CONNECTED,		/* Connected			*/
  B_CONN_STATUS_CLOSING			/* In process of closing	*/

  /* UNCONNECTED -> [CONNECTING|ACCEPTED] -> CONNECTED -> CLOSING -> UNCONNECTED */

} BConnStatus;


typedef void	 (*BConnConnectFunc)   (BConn* conn, gpointer user_data);
typedef void	 (*BConnPingFunc)      (BConn* conn, gpointer user_data);
typedef void	 (*BConnWriteableFunc) (BConn* conn, gpointer user_data);
typedef void 	 (*BConnFailFunc)      (BConn* conn, gpointer user_data);
typedef void 	 (*BConnCloseFunc)     (BConn* conn, gpointer user_data);


typedef struct _BConnFuncs
{
  BConnConnectFunc	connect;	/* HELLO-OK exchanged	*/
  BConnPingFunc		ping;		/* Ping received	*/
  BConnWriteableFunc	writeable;	/* Conn is writeable	*/
  BConnCloseFunc	close;		/* Conn has closed	*/
  BConnFailFunc		fail;		/* Conn has failed	*/

} BConnFuncs;

/* Conn is reset before close or fail is called; status is
   UNCONNECTED. */


struct _BConn
{
  GConn*	conn;
  BConnStatus	status;
  BGroup*	group;
  		
  BConnFuncs*	funcs;
  gpointer	user_data;
		

  /* ******************** */

  /* Connection ID (b_conn_connect/b_peer) */
  guint32 	in_conn_id;	/* ID expected for incoming packets (set by us)	*/
  guint32 	out_conn_id;	/* ID used for outgoing packets (set by them)	*/

  /* Packet queue (b_conn) */
  GSList* 	pkt_queue;	/* Sorted list of packets		*/
  guint		pkt_queue_size;	/* Size of list in bytes		*/
		
  /* Packet handlers (b_conn_handler) */
  GSList*	handlers;

  /* Pinging / keep alive (b_conn_ping) */
  gboolean	is_pinging;	/* Are we sending pings			*/
  guint 	send_ping_timer;/* Timer for next ping			*/
  guint		conn_timeout_timer; /* Timer for connection timeout	*/
  guint		bye_to_timer; 	/* Timeout for sending BYE		*/
  guint		distance;	/* RTT in milliseconds			*/
									
  /* Packet reading (b_packet) */					
  BPacket*      cur_pkt; 	/* Long packets being parsed		*/
  guint16 	cur_read;	/* Bytes of current_packet read		*/
									
  /* IO management (b_conn_io) */					
  guint		watch;		/* IOChannel watch ID 			*/
  guint		watch_flags;	/* Flags of events watched		*/
  guint		watch_changed;	/* Watch was changed while in upcall	*/
  guint		in_upcall:1;	/* In upcall from IO function 		*/
  guint		should_destroy:1; /* Delete after upcall?		*/
									
  guint 	buffer_offset;	/* Offset for writing in the buffer	*/
  gchar 	buffer[BCONN_BUF_SIZE];

};


/* ******************** */


BConn*   b_conn_new (gchar* hostname, gint port, BGroup* group,
		     BConnFuncs* funcs, gpointer user_data);
BConn*	 b_conn_new_accepted (GConn* conn);
void     b_conn_delete (BConn* conn);

void	 b_conn_print (FILE* file, BConn* conn);

void	 b_conn_func_connect   (BConn* conn);
void	 b_conn_func_ping      (BConn* conn);
void	 b_conn_func_writeable (BConn* conn);
void	 b_conn_func_fail      (BConn* conn);
void	 b_conn_func_close     (BConn* conn);


gboolean b_conn_has_packet (BConn* conn, guint8 type);
gboolean b_conn_has_packet_by_subtype (BConn* conn, guint8 type, guint8 subtype);

void 	 b_conn_send_packet (BConn* conn, BPacket* packet);
void	 b_conn_prepend_packet (BConn* conn, BPacket* packet);
void	 b_conn_append_packet (BConn* conn, BPacket* packet);

BPacket* b_conn_pop_packet (BConn* conn);
void	 b_conn_remove_packets (BConn* conn, guint8 type);
void	 b_conn_remove_packets_by_subtype (BConn* conn, guint8 type, guint8 subtype);


#define  b_conn_is_unconnected(CONN)	((CONN)->status == B_CONN_STATUS_UNCONNECTED)
#define  b_conn_is_closing(CONN)	((CONN)->status == B_CONN_STATUS_CLOSING)
#define  b_conn_is_connected(CONN)	((CONN)->status == B_CONN_STATUS_CONNECTED)
#define  b_conn_is_connecting(CONN)	((CONN)->status == B_CONN_STATUS_CONNECTING)
#define  b_conn_is_accepted(CONN)	((CONN)->status == B_CONN_STATUS_ACCEPTED)

#undef BPacket
#undef BPeer
#undef BGroup

/* Other b_conn files */
#include "b_conn_io.h"
#include "b_conn_handler.h"
#include "b_conn_connect.h"
#include "b_conn_ping.h"
#include "b_group.h"

/* For garbage collection/proper disconnection purposes while exiting */
extern guint b_conn_num_conns;
extern void (*b_conn_num_conns_zero)(void);

#endif /* _B_CONN_H */


syntax highlighted by Code2HTML, v. 0.9.1