/*
 * brocas.h
 * Copyright (C) 1996 by candy
 * $Id: brocas.h,v 3.7 1996/12/12 17:15:12 candy Exp candy $
 */
#ifndef BROCAS_H__
#define BROCAS_H__

#define COUNTOF(v) (sizeof(v)/sizeof((v)[0]))
#define GETUW(p) ((((unsigned char *)(p))[0]<<8)|(((unsigned char *)(p))[1]))
#define GETUL(p) ((((unsigned long)((unsigned char *)(p))[0])<<24)|(((unsigned char *)(p))[1]<<16)|(((unsigned char *)(p))[2]<<8)|(((unsigned char *)(p))[3]))
#define SETUW(p,x) (void)(((char*)(p))[0]=((x)>>8)&0xff,((char*)(p))[1]=(x)&0xff)
#define SETUL(p,x) (void)(((char*)(p))[0]=((x)>>24)&0xff,((char*)(p))[1]=((x)>>16)&0xff,((char*)(p))[2]=((x)>>8)&0xff,((char*)(p))[3]=(x)&0xff)

#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif

extern int debug_flag;

#define USERNAME_MAX 64
#define HOSTNAME_MAX 256
#define MESSAGE_MAX 8192

/*
 * ソケットアドレス
 */
union saddr {
	struct sockaddr sa;
	struct sockaddr_in sin;
};

/*
 * IP Messenger プロトコルアドレス構造体
 */
struct maddr_t {
	int m_so;
	char m_user[USERNAME_MAX];
	union saddr m_saddr;
};

/*
 * 受信パケットをデコードしたもの
 */
struct packet_t {
	unsigned long pk_ver;
	unsigned long pk_no;
	unsigned long pk_cmd;
	char *pk_user;
	char *pk_host;
	char *pk_msg;
	char *pk_icon;
	size_t pk_msgsize;
	struct maddr_t pk_maddr;
};

/*
 * コールバックのイベント
 */
enum bro_event_t {
	BRO_EV_LIST_CHANGED, /* 名前リストが変わった */
	BRO_EV_RECV_MESSAGE, /* メッセージが届いた */
	BRO_EV_RECV_ACK, /* 送ったメッセージが間違いなく届いた */
	BRO_EV_NO_ACK, /* 送ったメッセージが届かなかったかも */
	BRO_EV_START_WORK_PROC, /* work procedure を開始する (^^;; */
	BRO_EV_MAX /* (イベント種類総数) */
};

struct msg_data_t {
	struct maddr_t *md_replyto;
	char *md_msg;
	char *md_from;
	unsigned long md_opt;
	unsigned long md_pkno;
	unsigned char *md_icon;
};

/*
 * パケットフィルタリング用
 */
struct rcv_q_t {
	unsigned long q_id; /* 受信したパケット番号 */
	unsigned long q_keep; /* 保持する時間 */
};

/*
 *
 */
struct rcv_t {
	struct rcv_q_t *rcv_q;
	size_t rcv_size; /* rcv_q のサイズ */
	size_t rcv_used; /* rcv_q の使用中のサイズ */
};

struct ns_t {
	struct maddr_t ns_maddr; /* プロトコルアドレス */
	char ns_host[HOSTNAME_MAX]; /* ホスト名フィールド値 */
	char ns_nick[USERNAME_MAX]; /* ニックネーム */
	struct rcv_t ns_rcv;
};

typedef void (*bro_callback_t)(enum bro_event_t, void *closure, void *call_data);

/*
 * スキャッターバッファ
 */
struct iov_t {
	struct iov_t *iov_next;
	void *iov_base;
	size_t iov_len;
};

#define SET_IOV(v,next,base,len) (void)((v)->iov_next = (next), (v)->iov_base = (base), (v)->iov_len = (len))



/* ----START */
char * str_dup(const char *s);
char * strncpyz(char *dst, const char *src, size_t len);
char * strnchr(const char *s, int ch, size_t n);
int strcmpi(const char *d_, const char *s_);
int strncmpi(const char *d_, const char *s_, size_t n);
int bro_add_callback(enum bro_event_t e, bro_callback_t callback, void *closure);
struct xq_t * xq_enq(struct xq_t *xq);
int bro_send(const char *msg, const unsigned char *icon, const struct maddr_t *ma);
struct ns_t * ns_lookup(const struct maddr_t *ma);
struct ns_t * ns_get(int idx);
void ns_free(const struct maddr_t *ma);
void ns_clear(void);
char ** ns_list(void);
int send_IPMSG_READMSG(struct maddr_t *replyto, unsigned long pkno);
int send_IPMSG_BR_ENTRY(void);
int send_IPMSG_BR_EXIT(void);
int bro_recv_packet(int so);
void bro_job(void);
void bro_work(void);
int bro_set_disable(int disable);
int bro_init(int port, const char *user, const char *host, const char * const *bros);
/* ----END */

#endif
