merge from re/branches/bfcp2
This commit is contained in:
parent
0c4cdc4c3b
commit
5f9f9eac4b
13 changed files with 1256 additions and 1563 deletions
|
@ -5,51 +5,57 @@
|
|||
*/
|
||||
|
||||
|
||||
/** BFCP Version */
|
||||
enum {BFCP_VERSION = 1};
|
||||
|
||||
/** BFCP Primitives */
|
||||
enum bfcp_prim {
|
||||
BFCP_FLOOR_REQUEST = 1,
|
||||
BFCP_FLOOR_RELEASE = 2,
|
||||
BFCP_FLOOR_REQUEST_QUERY = 3,
|
||||
BFCP_FLOOR_REQUEST_STAT = 4,
|
||||
BFCP_USER_QUERY = 5,
|
||||
BFCP_USER_STATUS = 6,
|
||||
BFCP_FLOOR_QUERY = 7,
|
||||
BFCP_FLOOR_STATUS = 8,
|
||||
BFCP_CHAIR_ACTION = 9,
|
||||
BFCP_CHAIR_ACTION_ACK = 10,
|
||||
BFCP_HELLO = 11,
|
||||
BFCP_HELLO_ACK = 12,
|
||||
BFCP_ERROR = 13,
|
||||
BFCP_FLOOR_REQUEST = 1,
|
||||
BFCP_FLOOR_RELEASE = 2,
|
||||
BFCP_FLOOR_REQUEST_QUERY = 3,
|
||||
BFCP_FLOOR_REQUEST_STATUS = 4,
|
||||
BFCP_USER_QUERY = 5,
|
||||
BFCP_USER_STATUS = 6,
|
||||
BFCP_FLOOR_QUERY = 7,
|
||||
BFCP_FLOOR_STATUS = 8,
|
||||
BFCP_CHAIR_ACTION = 9,
|
||||
BFCP_CHAIR_ACTION_ACK = 10,
|
||||
BFCP_HELLO = 11,
|
||||
BFCP_HELLO_ACK = 12,
|
||||
BFCP_ERROR = 13,
|
||||
BFCP_FLOOR_REQ_STATUS_ACK = 14,
|
||||
BFCP_FLOOR_STATUS_ACK = 15,
|
||||
BFCP_GOODBYE = 16,
|
||||
BFCP_GOODBYE_ACK = 17,
|
||||
};
|
||||
|
||||
/** BFCP Attributes */
|
||||
enum bfcp_attrib {
|
||||
BFCP_BENEFICIARY_ID = 1,
|
||||
BFCP_FLOOR_ID = 2,
|
||||
BFCP_FLOOR_REQUEST_ID = 3,
|
||||
BFCP_PRIORITY = 4,
|
||||
BFCP_REQUEST_STATUS = 5,
|
||||
BFCP_ERROR_CODE = 6,
|
||||
BFCP_ERROR_INFO = 7,
|
||||
BFCP_PARTICIPANT_PROV_INFO = 8,
|
||||
BFCP_STATUS_INFO = 9,
|
||||
BFCP_SUPPORTED_ATTRIBUTES = 10,
|
||||
BFCP_SUPPORTED_PRIMITIVES = 11,
|
||||
BFCP_USER_DISPLAY_NAME = 12,
|
||||
BFCP_USER_URI = 13,
|
||||
BFCP_BENEFICIARY_ID = 1,
|
||||
BFCP_FLOOR_ID = 2,
|
||||
BFCP_FLOOR_REQUEST_ID = 3,
|
||||
BFCP_PRIORITY = 4,
|
||||
BFCP_REQUEST_STATUS = 5,
|
||||
BFCP_ERROR_CODE = 6,
|
||||
BFCP_ERROR_INFO = 7,
|
||||
BFCP_PART_PROV_INFO = 8,
|
||||
BFCP_STATUS_INFO = 9,
|
||||
BFCP_SUPPORTED_ATTRS = 10,
|
||||
BFCP_SUPPORTED_PRIMS = 11,
|
||||
BFCP_USER_DISP_NAME = 12,
|
||||
BFCP_USER_URI = 13,
|
||||
/* grouped: */
|
||||
BFCP_BENEFICIARY_INFO = 14,
|
||||
BFCP_FLOOR_REQUEST_INFO = 15,
|
||||
BFCP_REQUESTED_BY_INFO = 16,
|
||||
BFCP_FLOOR_REQUEST_STATUS = 17,
|
||||
BFCP_OVERALL_REQUEST_STATUS = 18,
|
||||
BFCP_BENEFICIARY_INFO = 14,
|
||||
BFCP_FLOOR_REQ_INFO = 15,
|
||||
BFCP_REQUESTED_BY_INFO = 16,
|
||||
BFCP_FLOOR_REQ_STATUS = 17,
|
||||
BFCP_OVERALL_REQ_STATUS = 18,
|
||||
|
||||
/** Mandatory Attribute */
|
||||
BFCP_MANDATORY = 1<<7,
|
||||
/** Encode Handler */
|
||||
BFCP_ENCODE_HANDLER = 1<<8,
|
||||
};
|
||||
|
||||
/** BFCP Request Status */
|
||||
enum bfcp_rstat {
|
||||
enum bfcp_reqstat {
|
||||
BFCP_PENDING = 1,
|
||||
BFCP_ACCEPTED = 2,
|
||||
BFCP_GRANTED = 3,
|
||||
|
@ -61,19 +67,24 @@ enum bfcp_rstat {
|
|||
|
||||
/** BFCP Error Codes */
|
||||
enum bfcp_err {
|
||||
BFCP_ERR_CONF_NOT_EXIST = 1,
|
||||
BFCP_ERR_USER_NOT_EXIST = 2,
|
||||
BFCP_ERR_UNKNOWN_PRIM = 3,
|
||||
BFCP_ERR_UNKNOWN_MAND_ATTR = 4,
|
||||
BFCP_ERR_UNAUTH_OPERATION = 5,
|
||||
BFCP_ERR_INVALID_FLOOR_ID = 6,
|
||||
BFCP_ERR_FLOOR_REQ_ID_NOT_EXIST = 7,
|
||||
BFCP_ERR_MAX_FLOOR_REQ_REACHED = 8,
|
||||
BFCP_ERR_USE_TLS = 9
|
||||
BFCP_CONF_NOT_EXIST = 1,
|
||||
BFCP_USER_NOT_EXIST = 2,
|
||||
BFCP_UNKNOWN_PRIM = 3,
|
||||
BFCP_UNKNOWN_MAND_ATTR = 4,
|
||||
BFCP_UNAUTH_OPERATION = 5,
|
||||
BFCP_INVALID_FLOOR_ID = 6,
|
||||
BFCP_FLOOR_REQ_ID_NOT_EXIST = 7,
|
||||
BFCP_MAX_FLOOR_REQ_REACHED = 8,
|
||||
BFCP_USE_TLS = 9,
|
||||
BFCP_PARSE_ERROR = 10,
|
||||
BFCP_USE_DTLS = 11,
|
||||
BFCP_UNSUPPORTED_VERSION = 12,
|
||||
BFCP_BAD_LENGTH = 13,
|
||||
BFCP_GENERIC_ERROR = 14,
|
||||
};
|
||||
|
||||
/** BFCP Priority */
|
||||
enum bfcp_prio {
|
||||
enum bfcp_priority {
|
||||
BFCP_PRIO_LOWEST = 0,
|
||||
BFCP_PRIO_LOW = 1,
|
||||
BFCP_PRIO_NORMAL = 2,
|
||||
|
@ -81,74 +92,40 @@ enum bfcp_prio {
|
|||
BFCP_PRIO_HIGHEST = 4
|
||||
};
|
||||
|
||||
/** BFCP Request status */
|
||||
struct bfcp_reqstat {
|
||||
enum bfcp_rstat stat;
|
||||
/** BFCP Transport */
|
||||
enum bfcp_transp {
|
||||
BFCP_UDP,
|
||||
};
|
||||
|
||||
/** BFCP Request Status */
|
||||
struct bfcp_reqstatus {
|
||||
enum bfcp_reqstat status;
|
||||
uint8_t qpos;
|
||||
};
|
||||
|
||||
/** BFCP Error code */
|
||||
/** BFCP Error Code */
|
||||
struct bfcp_errcode {
|
||||
enum bfcp_err code;
|
||||
uint8_t *details; /* optional */
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/** BFCP supported attributes */
|
||||
/** BFCP Supported Attributes */
|
||||
struct bfcp_supattr {
|
||||
enum bfcp_attrib *attrv;
|
||||
size_t attrc;
|
||||
};
|
||||
|
||||
/** BFCP supported primitives */
|
||||
/** BFCP Supported Primitives */
|
||||
struct bfcp_supprim {
|
||||
enum bfcp_prim *primv;
|
||||
size_t primc;
|
||||
};
|
||||
|
||||
/** BFCP overall request status */
|
||||
struct bfcp_overall_reqstat {
|
||||
uint16_t freqid;
|
||||
struct bfcp_reqstat reqstat;
|
||||
char *statinfo;
|
||||
};
|
||||
|
||||
/** BFCP beneficiary information */
|
||||
struct bfcp_beneficiary_info {
|
||||
uint16_t bfid;
|
||||
char *dname;
|
||||
char *uri;
|
||||
};
|
||||
|
||||
/** BFCP requested by information */
|
||||
struct bfcp_reqby_info {
|
||||
uint16_t rbid;
|
||||
char *dname;
|
||||
char *uri;
|
||||
};
|
||||
|
||||
/** BFCP floor request status */
|
||||
struct bfcp_floor_reqstat {
|
||||
uint16_t floorid;
|
||||
struct bfcp_reqstat reqstat;
|
||||
char *statinfo;
|
||||
};
|
||||
|
||||
/** BFCP floor request info */
|
||||
struct bfcp_floor_reqinfo {
|
||||
uint16_t freqid;
|
||||
struct bfcp_overall_reqstat ors;
|
||||
struct bfcp_floor_reqstat *frsv;
|
||||
size_t frsc;
|
||||
struct bfcp_beneficiary_info bfi;
|
||||
struct bfcp_reqby_info rbi;
|
||||
enum bfcp_prio prio;
|
||||
char *ppi;
|
||||
};
|
||||
|
||||
/** BFCP Attribute */
|
||||
struct bfcp_attr {
|
||||
struct le le;
|
||||
struct list attrl;
|
||||
enum bfcp_attrib type;
|
||||
bool mand;
|
||||
union bfcp_union {
|
||||
|
@ -157,39 +134,63 @@ struct bfcp_attr {
|
|||
uint16_t u16;
|
||||
|
||||
/* actual attributes */
|
||||
uint16_t bfid;
|
||||
uint16_t beneficiaryid;
|
||||
uint16_t floorid;
|
||||
uint16_t freqid;
|
||||
enum bfcp_prio prio;
|
||||
struct bfcp_reqstat reqstat;
|
||||
uint16_t floorreqid;
|
||||
enum bfcp_priority priority;
|
||||
struct bfcp_reqstatus reqstatus;
|
||||
struct bfcp_errcode errcode;
|
||||
char *errinfo;
|
||||
char *ppi;
|
||||
char *statinfo;
|
||||
char *partprovinfo;
|
||||
char *statusinfo;
|
||||
struct bfcp_supattr supattr;
|
||||
struct bfcp_supprim supprim;
|
||||
char *userdname;
|
||||
char *useruri;
|
||||
|
||||
/* grouped attributes */
|
||||
struct bfcp_beneficiary_info bfi;
|
||||
struct bfcp_floor_reqinfo fri;
|
||||
struct bfcp_reqby_info rbi;
|
||||
struct bfcp_floor_reqstat frs;
|
||||
struct bfcp_overall_reqstat ors;
|
||||
uint16_t reqbyid;
|
||||
} v;
|
||||
};
|
||||
|
||||
/** BFCP Transport */
|
||||
enum bfcp_transp {
|
||||
BFCP_TRANSP_TCP = 0,
|
||||
BFCP_TRANSP_TLS = 1
|
||||
/** BFCP unknown attributes */
|
||||
struct bfcp_unknown_attr {
|
||||
uint8_t typev[16];
|
||||
size_t typec;
|
||||
};
|
||||
|
||||
/** BFCP Message */
|
||||
struct bfcp_msg {
|
||||
struct bfcp_unknown_attr uma;
|
||||
struct sa src;
|
||||
uint8_t ver;
|
||||
unsigned r:1;
|
||||
unsigned f:1;
|
||||
enum bfcp_prim prim;
|
||||
uint16_t len;
|
||||
uint32_t confid;
|
||||
uint16_t tid;
|
||||
uint16_t userid;
|
||||
struct list attrl;
|
||||
};
|
||||
|
||||
/* BFCP Message */
|
||||
struct bfcp_conn;
|
||||
|
||||
|
||||
/**
|
||||
* Defines the BFCP encode handler
|
||||
*
|
||||
* @param mb Mbuf to encode into
|
||||
* @param arg Handler argument
|
||||
*
|
||||
* @return 0 if success, otherwise errorcode
|
||||
*/
|
||||
typedef int (bfcp_encode_h)(struct mbuf *mb, void *arg);
|
||||
|
||||
/** BFCP Encode */
|
||||
struct bfcp_encode {
|
||||
bfcp_encode_h *ench;
|
||||
void *arg;
|
||||
};
|
||||
|
||||
struct bfcp_msg;
|
||||
|
||||
/**
|
||||
* Defines the BFCP attribute handler
|
||||
|
@ -201,52 +202,15 @@ struct bfcp_msg;
|
|||
*/
|
||||
typedef bool (bfcp_attr_h)(const struct bfcp_attr *attr, void *arg);
|
||||
|
||||
int bfcp_msg_vencode(struct mbuf *mb, enum bfcp_prim prim,
|
||||
uint32_t confid, uint16_t tid, uint16_t userid,
|
||||
uint32_t attrc, va_list ap);
|
||||
int bfcp_msg_encode(struct mbuf *mb, enum bfcp_prim prim, uint32_t confid,
|
||||
uint16_t tid, uint16_t userid, uint32_t attrc, ...);
|
||||
int bfcp_msg_decode(struct bfcp_msg **msgp, struct mbuf *mb,
|
||||
const struct sa *src);
|
||||
struct bfcp_attr *bfcp_msg_attr(const struct bfcp_msg *msg,
|
||||
enum bfcp_attrib type);
|
||||
struct bfcp_attr *bfcp_msg_attr_apply(const struct bfcp_msg *msg,
|
||||
bfcp_attr_h *h, void *arg);
|
||||
int bfcp_msg_print(struct re_printf *pf, const struct bfcp_msg *msg);
|
||||
enum bfcp_prim bfcp_msg_prim(const struct bfcp_msg *msg);
|
||||
uint32_t bfcp_msg_confid(const struct bfcp_msg *msg);
|
||||
uint16_t bfcp_msg_tid(const struct bfcp_msg *msg);
|
||||
uint16_t bfcp_msg_userid(const struct bfcp_msg *msg);
|
||||
const struct sa *bfcp_msg_src(const struct bfcp_msg *msg);
|
||||
|
||||
|
||||
/* BFCP supplement */
|
||||
|
||||
const char *bfcp_prim_name(enum bfcp_prim prim);
|
||||
const char *bfcp_attr_name(enum bfcp_attrib attr);
|
||||
const char *bfcp_reqstat_name(enum bfcp_rstat rstat);
|
||||
const char *bfcp_errcode_name(enum bfcp_err code);
|
||||
|
||||
|
||||
/* BFCP Transport */
|
||||
|
||||
bool bfcp_transp_reliable(enum bfcp_transp tp);
|
||||
const char *bfcp_transp_proto(enum bfcp_transp tp);
|
||||
|
||||
|
||||
/* BFCP Socket */
|
||||
|
||||
struct tls;
|
||||
struct bfcp_sock;
|
||||
struct bfcp_ctrans;
|
||||
|
||||
/**
|
||||
* Defines the BFCP message handler
|
||||
* Defines the BFCP receive handler
|
||||
*
|
||||
* @param msg BFCP message
|
||||
* @param arg Handler argument
|
||||
*/
|
||||
typedef void (bfcp_msg_h)(const struct bfcp_msg *msg, void *arg);
|
||||
typedef void (bfcp_recv_h)(const struct bfcp_msg *msg, void *arg);
|
||||
|
||||
|
||||
/**
|
||||
* Defines the BFCP response handler
|
||||
|
@ -258,14 +222,56 @@ typedef void (bfcp_msg_h)(const struct bfcp_msg *msg, void *arg);
|
|||
typedef void (bfcp_resp_h)(int err, const struct bfcp_msg *msg, void *arg);
|
||||
|
||||
|
||||
int bfcp_listen(struct bfcp_sock **sockp, enum bfcp_transp transp,
|
||||
struct tls *tls, const struct sa *laddr,
|
||||
bfcp_msg_h *msgh, void *arg);
|
||||
int bfcp_request(struct bfcp_ctrans **ctp, struct bfcp_sock *sock,
|
||||
const struct sa *dst,
|
||||
/* attr */
|
||||
int bfcp_attrs_vencode(struct mbuf *mb, unsigned attrc, va_list ap);
|
||||
int bfcp_attrs_encode(struct mbuf *mb, unsigned attrc, ...);
|
||||
struct bfcp_attr *bfcp_attr_subattr(const struct bfcp_attr *attr,
|
||||
enum bfcp_attrib type);
|
||||
struct bfcp_attr *bfcp_attr_subattr_apply(const struct bfcp_attr *attr,
|
||||
bfcp_attr_h *h, void *arg);
|
||||
int bfcp_attr_print(struct re_printf *pf, const struct bfcp_attr *attr);
|
||||
const char *bfcp_attr_name(enum bfcp_attrib type);
|
||||
const char *bfcp_reqstatus_name(enum bfcp_reqstat status);
|
||||
const char *bfcp_errcode_name(enum bfcp_err code);
|
||||
|
||||
|
||||
/* msg */
|
||||
int bfcp_msg_vencode(struct mbuf *mb, uint8_t ver, bool r, enum bfcp_prim prim,
|
||||
uint32_t confid, uint16_t tid, uint16_t userid,
|
||||
unsigned attrc, va_list ap);
|
||||
int bfcp_msg_encode(struct mbuf *mb, uint8_t ver, bool r, enum bfcp_prim prim,
|
||||
uint32_t confid, uint16_t tid, uint16_t userid,
|
||||
unsigned attrc, ...);
|
||||
int bfcp_msg_decode(struct bfcp_msg **msgp, struct mbuf *mb);
|
||||
struct bfcp_attr *bfcp_msg_attr(const struct bfcp_msg *msg,
|
||||
enum bfcp_attrib type);
|
||||
struct bfcp_attr *bfcp_msg_attr_apply(const struct bfcp_msg *msg,
|
||||
bfcp_attr_h *h, void *arg);
|
||||
int bfcp_msg_print(struct re_printf *pf, const struct bfcp_msg *msg);
|
||||
const char *bfcp_prim_name(enum bfcp_prim prim);
|
||||
|
||||
|
||||
/* conn */
|
||||
int bfcp_listen(struct bfcp_conn **bcp, enum bfcp_transp tp, struct sa *laddr,
|
||||
bfcp_recv_h *recvh, void *arg);
|
||||
|
||||
|
||||
/* request */
|
||||
int bfcp_request(struct bfcp_conn *bc, const struct sa *dst,
|
||||
enum bfcp_prim prim, uint32_t confid, uint16_t userid,
|
||||
bfcp_resp_h *resph, void *arg, uint32_t attrc, ...);
|
||||
int bfcp_reply(struct bfcp_sock *sock, const struct bfcp_msg *req,
|
||||
|
||||
|
||||
/* notify */
|
||||
int bfcp_notify(struct bfcp_conn *bc, const struct sa *dst,
|
||||
enum bfcp_prim prim, uint32_t confid, uint16_t userid,
|
||||
uint32_t attrc, ...);
|
||||
|
||||
|
||||
/* reply */
|
||||
int bfcp_reply(struct bfcp_conn *bc, const struct bfcp_msg *req,
|
||||
enum bfcp_prim prim, uint32_t attrc, ...);
|
||||
int bfcp_ereply(struct bfcp_sock *sock, const struct bfcp_msg *req,
|
||||
enum bfcp_err code, ...);
|
||||
int bfcp_edreply(struct bfcp_conn *bc, const struct bfcp_msg *req,
|
||||
enum bfcp_err code, const uint8_t *details, size_t len);
|
||||
int bfcp_ereply(struct bfcp_conn *bc, const struct bfcp_msg *req,
|
||||
enum bfcp_err code);
|
||||
|
|
880
src/bfcp/attr.c
880
src/bfcp/attr.c
File diff suppressed because it is too large
Load diff
|
@ -4,57 +4,51 @@
|
|||
* Copyright (C) 2010 Creytiv.com
|
||||
*/
|
||||
|
||||
|
||||
/* header */
|
||||
enum {
|
||||
BFCP_HDR_SIZE = 12,
|
||||
ATTR_HDR_SIZE = 2
|
||||
BFCP_VER1 = 1,
|
||||
BFCP_VER2 = 2,
|
||||
};
|
||||
|
||||
|
||||
struct bfcp_hdr {
|
||||
uint8_t ver;
|
||||
unsigned i:1;
|
||||
struct bfcp_strans {
|
||||
enum bfcp_prim prim;
|
||||
uint16_t len;
|
||||
uint32_t confid;
|
||||
uint16_t tid;
|
||||
uint16_t userid;
|
||||
};
|
||||
|
||||
int bfcp_hdr_encode(struct mbuf *mb, enum bfcp_prim prim, uint16_t len,
|
||||
uint32_t confid, uint16_t tid, uint16_t userid);
|
||||
int bfcp_hdr_decode(struct mbuf *mb, struct bfcp_hdr *hdr);
|
||||
|
||||
|
||||
/* attributes */
|
||||
int bfcp_attr_encode(struct mbuf *mb, bool mand, enum bfcp_attrib type,
|
||||
const void *v);
|
||||
int bfcp_attr_decode(struct bfcp_attr **attrp, struct mbuf *mb);
|
||||
int bfcp_attr_print(struct re_printf *pf, const struct bfcp_attr *a);
|
||||
bool bfcp_attr_isgrouped(enum bfcp_attrib attr);
|
||||
|
||||
|
||||
/* socket */
|
||||
|
||||
struct bfcp_sock {
|
||||
struct list transl;
|
||||
struct list connl;
|
||||
struct tcp_sock *ts;
|
||||
struct tls *tls;
|
||||
enum bfcp_transp transp;
|
||||
uint16_t tidc;
|
||||
bool active;
|
||||
bfcp_msg_h *msgh;
|
||||
struct bfcp_conn {
|
||||
struct bfcp_strans st;
|
||||
struct list ctransl;
|
||||
struct tmr tmr1;
|
||||
struct tmr tmr2;
|
||||
struct udp_sock *us;
|
||||
struct mbuf *mb;
|
||||
bfcp_recv_h *recvh;
|
||||
void *arg;
|
||||
enum bfcp_transp tp;
|
||||
unsigned txc;
|
||||
uint16_t tid;
|
||||
};
|
||||
|
||||
|
||||
int bfcp_send(struct bfcp_sock *sock, const struct sa *dst, struct mbuf *mb);
|
||||
/* attributes */
|
||||
int bfcp_attrs_decode(struct list *attrl, struct mbuf *mb, size_t len,
|
||||
struct bfcp_unknown_attr *uma);
|
||||
struct bfcp_attr *bfcp_attrs_find(const struct list *attrl,
|
||||
enum bfcp_attrib type);
|
||||
struct bfcp_attr *bfcp_attrs_apply(const struct list *attrl,
|
||||
bfcp_attr_h *h, void *arg);
|
||||
int bfcp_attrs_print(struct re_printf *pf, const struct list *attrl,
|
||||
unsigned level);
|
||||
|
||||
|
||||
/* ctrans request */
|
||||
/* connection */
|
||||
int bfcp_send(struct bfcp_conn *bc, const struct sa *dst, struct mbuf *mb);
|
||||
|
||||
void bfcp_ctrans_completed(struct bfcp_ctrans *ct, int err,
|
||||
const struct bfcp_msg *msg);
|
||||
struct bfcp_ctrans *bfcp_ctrans_find(struct bfcp_sock *sock, uint16_t tid);
|
||||
|
||||
/* request */
|
||||
bool bfcp_handle_response(struct bfcp_conn *bc, const struct bfcp_msg *msg);
|
||||
int bfcp_vrequest(struct bfcp_conn *bc, const struct sa *dst,
|
||||
enum bfcp_prim prim, uint32_t confid, uint16_t userid,
|
||||
bfcp_resp_h *resph, void *arg, uint32_t attrc, va_list ap);
|
||||
|
|
148
src/bfcp/conn.c
Normal file
148
src/bfcp/conn.c
Normal file
|
@ -0,0 +1,148 @@
|
|||
/**
|
||||
* @file bfcp/conn.c BFCP Connection
|
||||
*
|
||||
* Copyright (C) 2010 Creytiv.com
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <re_types.h>
|
||||
#include <re_fmt.h>
|
||||
#include <re_mem.h>
|
||||
#include <re_mbuf.h>
|
||||
#include <re_list.h>
|
||||
#include <re_sa.h>
|
||||
#include <re_udp.h>
|
||||
#include <re_tmr.h>
|
||||
#include <re_bfcp.h>
|
||||
#include "bfcp.h"
|
||||
|
||||
|
||||
static void destructor(void *arg)
|
||||
{
|
||||
struct bfcp_conn *bc = arg;
|
||||
|
||||
list_flush(&bc->ctransl);
|
||||
tmr_cancel(&bc->tmr1);
|
||||
tmr_cancel(&bc->tmr2);
|
||||
mem_deref(bc->us);
|
||||
mem_deref(bc->mb);
|
||||
}
|
||||
|
||||
|
||||
static bool strans_cmp(const struct bfcp_strans *st,
|
||||
const struct bfcp_msg *msg)
|
||||
{
|
||||
if (st->tid != msg->tid)
|
||||
return false;
|
||||
|
||||
if (st->prim != msg->prim)
|
||||
return false;
|
||||
|
||||
if (st->confid != msg->confid)
|
||||
return false;
|
||||
|
||||
if (st->userid != msg->userid)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void udp_recv_handler(const struct sa *src, struct mbuf *mb, void *arg)
|
||||
{
|
||||
struct bfcp_conn *bc = arg;
|
||||
struct bfcp_msg *msg;
|
||||
int err;
|
||||
|
||||
err = bfcp_msg_decode(&msg, mb);
|
||||
if (err)
|
||||
return;
|
||||
|
||||
msg->src = *src;
|
||||
|
||||
if (bfcp_handle_response(bc, msg))
|
||||
goto out;
|
||||
|
||||
if (bc->mb && strans_cmp(&bc->st, msg)) {
|
||||
(void)bfcp_send(bc, &msg->src, bc->mb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bc->recvh)
|
||||
bc->recvh(msg, bc->arg);
|
||||
|
||||
out:
|
||||
mem_deref(msg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create BFCP connection
|
||||
*
|
||||
* @param bcp Pointer to BFCP connection
|
||||
* @param tp BFCP Transport type
|
||||
* @param laddr Optional listening address/port
|
||||
* @param recvh Receive handler
|
||||
* @param arg Receive handler argument
|
||||
*
|
||||
* @return 0 if success, otherwise errorcode
|
||||
*/
|
||||
int bfcp_listen(struct bfcp_conn **bcp, enum bfcp_transp tp, struct sa *laddr,
|
||||
bfcp_recv_h *recvh, void *arg)
|
||||
{
|
||||
struct bfcp_conn *bc;
|
||||
int err;
|
||||
|
||||
if (!bcp)
|
||||
return EINVAL;
|
||||
|
||||
bc = mem_zalloc(sizeof(*bc), destructor);
|
||||
if (!bc)
|
||||
return ENOMEM;
|
||||
|
||||
bc->tp = tp;
|
||||
bc->recvh = recvh;
|
||||
bc->arg = arg;
|
||||
|
||||
switch (bc->tp) {
|
||||
|
||||
case BFCP_UDP:
|
||||
err = udp_listen(&bc->us, laddr, udp_recv_handler, bc);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
if (laddr) {
|
||||
err = udp_local_get(bc->us, laddr);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
err = ENOSYS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (err)
|
||||
mem_deref(bc);
|
||||
else
|
||||
*bcp = bc;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int bfcp_send(struct bfcp_conn *bc, const struct sa *dst, struct mbuf *mb)
|
||||
{
|
||||
if (!bc || !dst || !mb)
|
||||
return EINVAL;
|
||||
|
||||
switch (bc->tp) {
|
||||
|
||||
case BFCP_UDP:
|
||||
return udp_send(bc->us, dst, mb);
|
||||
|
||||
default:
|
||||
return ENOSYS;
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
/**
|
||||
* @file bfcp/hdr.c BFCP Message header
|
||||
*
|
||||
* Copyright (C) 2010 Creytiv.com
|
||||
*/
|
||||
#include <re_types.h>
|
||||
#include <re_fmt.h>
|
||||
#include <re_mem.h>
|
||||
#include <re_mbuf.h>
|
||||
#include <re_sa.h>
|
||||
#include <re_list.h>
|
||||
#include <re_bfcp.h>
|
||||
#include "bfcp.h"
|
||||
|
||||
|
||||
int bfcp_hdr_encode(struct mbuf *mb, enum bfcp_prim prim, uint16_t len,
|
||||
uint32_t confid, uint16_t tid, uint16_t userid)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = mbuf_write_u8(mb, BFCP_VERSION << 5);
|
||||
err |= mbuf_write_u8(mb, prim);
|
||||
err |= mbuf_write_u16(mb, htons(len));
|
||||
err |= mbuf_write_u32(mb, htonl(confid));
|
||||
err |= mbuf_write_u16(mb, htons(tid));
|
||||
err |= mbuf_write_u16(mb, htons(userid));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int bfcp_hdr_decode(struct mbuf *mb, struct bfcp_hdr *hdr)
|
||||
{
|
||||
uint8_t b;
|
||||
|
||||
if (mbuf_get_left(mb) < BFCP_HDR_SIZE)
|
||||
return EBADMSG;
|
||||
|
||||
b = mbuf_read_u8(mb);
|
||||
hdr->ver = b >> 5;
|
||||
hdr->i = (b >> 4) & 1;
|
||||
hdr->prim = mbuf_read_u8(mb);
|
||||
hdr->len = ntohs(mbuf_read_u16(mb));
|
||||
hdr->confid = ntohl(mbuf_read_u32(mb));
|
||||
hdr->tid = ntohs(mbuf_read_u16(mb));
|
||||
hdr->userid = ntohs(mbuf_read_u16(mb));
|
||||
|
||||
if (hdr->ver != BFCP_VERSION)
|
||||
return EBADMSG;
|
||||
|
||||
if (mbuf_get_left(mb) < (size_t)(hdr->len*4)) {
|
||||
|
||||
return ENODATA;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -5,9 +5,7 @@
|
|||
#
|
||||
|
||||
SRCS += bfcp/attr.c
|
||||
SRCS += bfcp/hdr.c
|
||||
SRCS += bfcp/conn.c
|
||||
SRCS += bfcp/msg.c
|
||||
SRCS += bfcp/rep.c
|
||||
SRCS += bfcp/req.c
|
||||
SRCS += bfcp/sock.c
|
||||
SRCS += bfcp/transp.c
|
||||
SRCS += bfcp/reply.c
|
||||
SRCS += bfcp/request.c
|
||||
|
|
293
src/bfcp/msg.c
293
src/bfcp/msg.c
|
@ -10,14 +10,13 @@
|
|||
#include <re_mbuf.h>
|
||||
#include <re_list.h>
|
||||
#include <re_sa.h>
|
||||
#include <re_tmr.h>
|
||||
#include <re_bfcp.h>
|
||||
#include "bfcp.h"
|
||||
|
||||
|
||||
struct bfcp_msg {
|
||||
struct sa src;
|
||||
struct bfcp_hdr hdr;
|
||||
struct list attrl;
|
||||
enum {
|
||||
BFCP_HDR_SIZE = 12,
|
||||
};
|
||||
|
||||
|
||||
|
@ -29,10 +28,61 @@ static void destructor(void *arg)
|
|||
}
|
||||
|
||||
|
||||
static int hdr_encode(struct mbuf *mb, uint8_t ver, bool r,
|
||||
enum bfcp_prim prim, uint16_t len, uint32_t confid,
|
||||
uint16_t tid, uint16_t userid)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = mbuf_write_u8(mb, (ver << 5) | ((r ? 1 : 0) << 4));
|
||||
err |= mbuf_write_u8(mb, prim);
|
||||
err |= mbuf_write_u16(mb, htons(len));
|
||||
err |= mbuf_write_u32(mb, htonl(confid));
|
||||
err |= mbuf_write_u16(mb, htons(tid));
|
||||
err |= mbuf_write_u16(mb, htons(userid));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int hdr_decode(struct bfcp_msg *msg, struct mbuf *mb)
|
||||
{
|
||||
uint8_t b;
|
||||
|
||||
if (mbuf_get_left(mb) < BFCP_HDR_SIZE)
|
||||
return ENODATA;
|
||||
|
||||
b = mbuf_read_u8(mb);
|
||||
|
||||
msg->ver = b >> 5;
|
||||
msg->r = (b >> 4) & 1;
|
||||
msg->f = (b >> 3) & 1;
|
||||
msg->prim = mbuf_read_u8(mb);
|
||||
msg->len = ntohs(mbuf_read_u16(mb));
|
||||
msg->confid = ntohl(mbuf_read_u32(mb));
|
||||
msg->tid = ntohs(mbuf_read_u16(mb));
|
||||
msg->userid = ntohs(mbuf_read_u16(mb));
|
||||
|
||||
if (msg->ver != BFCP_VER1 && msg->ver != BFCP_VER2)
|
||||
return EBADMSG;
|
||||
|
||||
/* fragmentation not supported */
|
||||
if (msg->f)
|
||||
return ENOSYS;
|
||||
|
||||
if (mbuf_get_left(mb) < (size_t)(4*msg->len))
|
||||
return ENODATA;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encode a BFCP message with variable arguments
|
||||
*
|
||||
* @param mb Mbuf to encode into
|
||||
* @param ver Protocol version
|
||||
* @param r Transaction responder flag
|
||||
* @param prim BFCP Primitive
|
||||
* @param confid Conference ID
|
||||
* @param tid Transaction ID
|
||||
|
@ -42,14 +92,12 @@ static void destructor(void *arg)
|
|||
*
|
||||
* @return 0 if success, otherwise errorcode
|
||||
*/
|
||||
int bfcp_msg_vencode(struct mbuf *mb, enum bfcp_prim prim,
|
||||
int bfcp_msg_vencode(struct mbuf *mb, uint8_t ver, bool r, enum bfcp_prim prim,
|
||||
uint32_t confid, uint16_t tid, uint16_t userid,
|
||||
uint32_t attrc, va_list ap)
|
||||
unsigned attrc, va_list ap)
|
||||
{
|
||||
size_t start;
|
||||
uint32_t i;
|
||||
uint16_t len;
|
||||
int err = 0;
|
||||
size_t start, len;
|
||||
int err;
|
||||
|
||||
if (!mb)
|
||||
return EINVAL;
|
||||
|
@ -57,26 +105,16 @@ int bfcp_msg_vencode(struct mbuf *mb, enum bfcp_prim prim,
|
|||
start = mb->pos;
|
||||
mb->pos += BFCP_HDR_SIZE;
|
||||
|
||||
for (i=0; i<attrc; i++) {
|
||||
|
||||
uint16_t type = va_arg(ap, int);
|
||||
const void *v = va_arg(ap, const void *);
|
||||
bool mand = false;
|
||||
|
||||
if (!v)
|
||||
continue;
|
||||
|
||||
err = bfcp_attr_encode(mb, mand, type, v);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
err = bfcp_attrs_vencode(mb, attrc, ap);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* header */
|
||||
len = (mb->pos - start - BFCP_HDR_SIZE) / 4;
|
||||
len = mb->pos - start - BFCP_HDR_SIZE;
|
||||
mb->pos = start;
|
||||
err = bfcp_hdr_encode(mb, prim, len, confid, tid, userid);
|
||||
|
||||
mb->pos = mb->end;
|
||||
err = hdr_encode(mb, ver, r, prim, (uint16_t)(len/4), confid, tid,
|
||||
userid);
|
||||
mb->pos += len;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -86,6 +124,8 @@ int bfcp_msg_vencode(struct mbuf *mb, enum bfcp_prim prim,
|
|||
* Encode a BFCP message
|
||||
*
|
||||
* @param mb Mbuf to encode into
|
||||
* @param ver Protocol version
|
||||
* @param r Transaction responder flag
|
||||
* @param prim BFCP Primitive
|
||||
* @param confid Conference ID
|
||||
* @param tid Transaction ID
|
||||
|
@ -94,14 +134,16 @@ int bfcp_msg_vencode(struct mbuf *mb, enum bfcp_prim prim,
|
|||
*
|
||||
* @return 0 if success, otherwise errorcode
|
||||
*/
|
||||
int bfcp_msg_encode(struct mbuf *mb, enum bfcp_prim prim, uint32_t confid,
|
||||
uint16_t tid, uint16_t userid, uint32_t attrc, ...)
|
||||
int bfcp_msg_encode(struct mbuf *mb, uint8_t ver, bool r, enum bfcp_prim prim,
|
||||
uint32_t confid, uint16_t tid, uint16_t userid,
|
||||
unsigned attrc, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int err;
|
||||
|
||||
va_start(ap, attrc);
|
||||
err = bfcp_msg_vencode(mb, prim, confid, tid, userid, attrc, ap);
|
||||
err = bfcp_msg_vencode(mb, ver, r, prim, confid, tid, userid,
|
||||
attrc, ap);
|
||||
va_end(ap);
|
||||
|
||||
return err;
|
||||
|
@ -113,47 +155,33 @@ int bfcp_msg_encode(struct mbuf *mb, enum bfcp_prim prim, uint32_t confid,
|
|||
*
|
||||
* @param msgp Pointer to allocated and decoded BFCP message
|
||||
* @param mb Mbuf to decode from
|
||||
* @param src Source network address (optional)
|
||||
*
|
||||
* @return 0 if success, otherwise errorcode
|
||||
*/
|
||||
int bfcp_msg_decode(struct bfcp_msg **msgp, struct mbuf *mb,
|
||||
const struct sa *src)
|
||||
int bfcp_msg_decode(struct bfcp_msg **msgp, struct mbuf *mb)
|
||||
{
|
||||
struct bfcp_msg *msg;
|
||||
size_t start, extra;
|
||||
size_t start;
|
||||
int err;
|
||||
|
||||
if (!msgp || !mb)
|
||||
return EINVAL;
|
||||
|
||||
start = mb->pos;
|
||||
|
||||
msg = mem_zalloc(sizeof(*msg), destructor);
|
||||
if (!msg)
|
||||
return ENOMEM;
|
||||
|
||||
err = bfcp_hdr_decode(mb, &msg->hdr);
|
||||
start = mb->pos;
|
||||
|
||||
err = hdr_decode(msg, mb);
|
||||
if (err) {
|
||||
mb->pos = start;
|
||||
goto out;
|
||||
}
|
||||
|
||||
extra = mbuf_get_left(mb) - 4*msg->hdr.len;
|
||||
|
||||
while (mbuf_get_left(mb) - extra >= ATTR_HDR_SIZE) {
|
||||
|
||||
struct bfcp_attr *attr;
|
||||
|
||||
err = bfcp_attr_decode(&attr, mb);
|
||||
if (err)
|
||||
break;
|
||||
|
||||
list_append(&msg->attrl, &attr->le, attr);
|
||||
}
|
||||
|
||||
if (src)
|
||||
msg->src = *src;
|
||||
err = bfcp_attrs_decode(&msg->attrl, mb, 4*msg->len, &msg->uma);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
if (err)
|
||||
|
@ -165,12 +193,6 @@ int bfcp_msg_decode(struct bfcp_msg **msgp, struct mbuf *mb,
|
|||
}
|
||||
|
||||
|
||||
static bool attr_match(const struct bfcp_attr *attr, void *arg)
|
||||
{
|
||||
return attr->type == *(enum bfcp_attrib *)arg;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a BFCP attribute from a BFCP message
|
||||
*
|
||||
|
@ -182,7 +204,10 @@ static bool attr_match(const struct bfcp_attr *attr, void *arg)
|
|||
struct bfcp_attr *bfcp_msg_attr(const struct bfcp_msg *msg,
|
||||
enum bfcp_attrib type)
|
||||
{
|
||||
return bfcp_msg_attr_apply(msg, attr_match, &type);
|
||||
if (!msg)
|
||||
return NULL;
|
||||
|
||||
return bfcp_attrs_find(&msg->attrl, type);
|
||||
}
|
||||
|
||||
|
||||
|
@ -198,26 +223,10 @@ struct bfcp_attr *bfcp_msg_attr(const struct bfcp_msg *msg,
|
|||
struct bfcp_attr *bfcp_msg_attr_apply(const struct bfcp_msg *msg,
|
||||
bfcp_attr_h *h, void *arg)
|
||||
{
|
||||
struct le *le = msg ? list_head(&msg->attrl) : NULL;
|
||||
if (!msg)
|
||||
return NULL;
|
||||
|
||||
while (le) {
|
||||
struct bfcp_attr *attr = le->data;
|
||||
|
||||
le = le->next;
|
||||
|
||||
if (h && h(attr, arg))
|
||||
return attr;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static bool attr_print(const struct bfcp_attr *attr, void *arg)
|
||||
{
|
||||
struct re_printf *pf = arg;
|
||||
|
||||
return 0 != bfcp_attr_print(pf, attr);
|
||||
return bfcp_attrs_apply(&msg->attrl, h, arg);
|
||||
}
|
||||
|
||||
|
||||
|
@ -236,91 +245,16 @@ int bfcp_msg_print(struct re_printf *pf, const struct bfcp_msg *msg)
|
|||
if (!msg)
|
||||
return 0;
|
||||
|
||||
err = re_hprintf(pf, "%s (len=%u confid=%u tid=%u userid=%u)\n",
|
||||
bfcp_prim_name(msg->hdr.prim), msg->hdr.len,
|
||||
msg->hdr.confid, msg->hdr.tid, msg->hdr.userid);
|
||||
err = re_hprintf(pf, "%s (confid=%u tid=%u userid=%u)\n",
|
||||
bfcp_prim_name(msg->prim), msg->confid,
|
||||
msg->tid, msg->userid);
|
||||
|
||||
bfcp_msg_attr_apply(msg, attr_print, pf);
|
||||
err |= bfcp_attrs_print(pf, &msg->attrl, 0);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the BFCP primitive of a BFCP message
|
||||
*
|
||||
* @param msg BFCP message
|
||||
*
|
||||
* @return The BFCP primitive
|
||||
*/
|
||||
enum bfcp_prim bfcp_msg_prim(const struct bfcp_msg *msg)
|
||||
{
|
||||
return msg ? msg->hdr.prim : 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the Conference ID of a BFCP message
|
||||
*
|
||||
* @param msg BFCP message
|
||||
*
|
||||
* @return The Conference ID
|
||||
*/
|
||||
uint32_t bfcp_msg_confid(const struct bfcp_msg *msg)
|
||||
{
|
||||
return msg ? msg->hdr.confid : 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the Transaction ID of a BFCP message
|
||||
*
|
||||
* @param msg BFCP message
|
||||
*
|
||||
* @return The Transaction ID
|
||||
*/
|
||||
uint16_t bfcp_msg_tid(const struct bfcp_msg *msg)
|
||||
{
|
||||
return msg ? msg->hdr.tid : 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the User ID of a BFCP message
|
||||
*
|
||||
* @param msg BFCP message
|
||||
*
|
||||
* @return The User ID
|
||||
*/
|
||||
uint16_t bfcp_msg_userid(const struct bfcp_msg *msg)
|
||||
{
|
||||
return msg ? msg->hdr.userid : 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the BFCP Request status name
|
||||
*
|
||||
* @param rstat Request status
|
||||
*
|
||||
* @return String with BFCP Request status name
|
||||
*/
|
||||
const char *bfcp_reqstat_name(enum bfcp_rstat rstat)
|
||||
{
|
||||
switch (rstat) {
|
||||
|
||||
case BFCP_PENDING: return "Pending";
|
||||
case BFCP_ACCEPTED: return "Accepted";
|
||||
case BFCP_GRANTED: return "Granted";
|
||||
case BFCP_DENIED: return "Denied";
|
||||
case BFCP_CANCELLED: return "Cancelled";
|
||||
case BFCP_RELEASED: return "Released";
|
||||
case BFCP_REVOKED: return "Revoked";
|
||||
default: return "???";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the BFCP primitive name
|
||||
*
|
||||
|
@ -332,32 +266,23 @@ const char *bfcp_prim_name(enum bfcp_prim prim)
|
|||
{
|
||||
switch (prim) {
|
||||
|
||||
case BFCP_FLOOR_REQUEST: return "FloorRequest";
|
||||
case BFCP_FLOOR_RELEASE: return "FloorRelease";
|
||||
case BFCP_FLOOR_REQUEST_QUERY: return "FloorRequestQuery";
|
||||
case BFCP_FLOOR_REQUEST_STAT: return "FloorRequestStatus";
|
||||
case BFCP_USER_QUERY: return "UserQuery";
|
||||
case BFCP_USER_STATUS: return "UserStatus";
|
||||
case BFCP_FLOOR_QUERY: return "FloorQuery";
|
||||
case BFCP_FLOOR_STATUS: return "FloorStatus";
|
||||
case BFCP_CHAIR_ACTION: return "ChairAction";
|
||||
case BFCP_CHAIR_ACTION_ACK: return "ChairActionAck";
|
||||
case BFCP_HELLO: return "Hello";
|
||||
case BFCP_HELLO_ACK: return "HelloAck";
|
||||
case BFCP_ERROR: return "Error";
|
||||
default: return "???";
|
||||
case BFCP_FLOOR_REQUEST: return "FloorRequest";
|
||||
case BFCP_FLOOR_RELEASE: return "FloorRelease";
|
||||
case BFCP_FLOOR_REQUEST_QUERY: return "FloorRequestQuery";
|
||||
case BFCP_FLOOR_REQUEST_STATUS: return "FloorRequestStatus";
|
||||
case BFCP_USER_QUERY: return "UserQuery";
|
||||
case BFCP_USER_STATUS: return "UserStatus";
|
||||
case BFCP_FLOOR_QUERY: return "FloorQuery";
|
||||
case BFCP_FLOOR_STATUS: return "FloorStatus";
|
||||
case BFCP_CHAIR_ACTION: return "ChairAction";
|
||||
case BFCP_CHAIR_ACTION_ACK: return "ChairActionAck";
|
||||
case BFCP_HELLO: return "Hello";
|
||||
case BFCP_HELLO_ACK: return "HelloAck";
|
||||
case BFCP_ERROR: return "Error";
|
||||
case BFCP_FLOOR_REQ_STATUS_ACK: return "FloorRequestStatusAck";
|
||||
case BFCP_FLOOR_STATUS_ACK: return "FloorStatusAck";
|
||||
case BFCP_GOODBYE: return "Goodbye";
|
||||
case BFCP_GOODBYE_ACK: return "GoodbyeAck";
|
||||
default: return "???";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the source network address of a BFCP message
|
||||
*
|
||||
* @param msg BFCP message
|
||||
*
|
||||
* @return Source network address
|
||||
*/
|
||||
const struct sa *bfcp_msg_src(const struct bfcp_msg *msg)
|
||||
{
|
||||
return msg ? &msg->src : NULL;
|
||||
}
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
/**
|
||||
* @file bfcp/rep.c BFCP Reply
|
||||
*
|
||||
* Copyright (C) 2010 Creytiv.com
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <re_types.h>
|
||||
#include <re_fmt.h>
|
||||
#include <re_mem.h>
|
||||
#include <re_mbuf.h>
|
||||
#include <re_list.h>
|
||||
#include <re_sa.h>
|
||||
#include <re_bfcp.h>
|
||||
#include "bfcp.h"
|
||||
|
||||
|
||||
/**
|
||||
* Send BFCP reply
|
||||
*
|
||||
* @param sock BFCP socket
|
||||
* @param req BFCP request to reply to
|
||||
* @param prim BFCP primitive
|
||||
* @param attrc Number of attributes
|
||||
*
|
||||
* @return 0 if success, otherwise errorcode
|
||||
*/
|
||||
int bfcp_reply(struct bfcp_sock *sock, const struct bfcp_msg *req,
|
||||
enum bfcp_prim prim, uint32_t attrc, ...)
|
||||
{
|
||||
struct mbuf *mb;
|
||||
va_list ap;
|
||||
int err;
|
||||
|
||||
if (!sock || !req)
|
||||
return EINVAL;
|
||||
|
||||
mb = mbuf_alloc(64);
|
||||
if (!mb)
|
||||
return ENOMEM;
|
||||
|
||||
va_start(ap, attrc);
|
||||
err = bfcp_msg_vencode(mb, prim, bfcp_msg_confid(req),
|
||||
bfcp_msg_tid(req), bfcp_msg_userid(req),
|
||||
attrc, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
mb->pos = 0;
|
||||
|
||||
err = bfcp_send(sock, bfcp_msg_src(req), mb);
|
||||
|
||||
out:
|
||||
mem_deref(mb);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send BFCP error reply
|
||||
*
|
||||
* @param sock BFCP socket
|
||||
* @param req BFCP request to reply to
|
||||
* @param code BFCP Error code
|
||||
*
|
||||
* @return 0 if success, otherwise errorcode
|
||||
*/
|
||||
int bfcp_ereply(struct bfcp_sock *sock, const struct bfcp_msg *req,
|
||||
enum bfcp_err code, ...)
|
||||
{
|
||||
struct bfcp_errcode ec;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, code);
|
||||
|
||||
memset(&ec, 0, sizeof(ec));
|
||||
ec.code = code;
|
||||
|
||||
if (code == BFCP_ERR_UNKNOWN_MAND_ATTR) {
|
||||
ec.details = va_arg(ap, uint8_t *);
|
||||
ec.len = va_arg(ap, size_t);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
return bfcp_reply(sock, req, BFCP_ERROR, 1, BFCP_ERROR_CODE, &ec);
|
||||
}
|
124
src/bfcp/reply.c
Normal file
124
src/bfcp/reply.c
Normal file
|
@ -0,0 +1,124 @@
|
|||
/**
|
||||
* @file bfcp/reply.c BFCP Reply
|
||||
*
|
||||
* Copyright (C) 2010 Creytiv.com
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <re_types.h>
|
||||
#include <re_fmt.h>
|
||||
#include <re_mem.h>
|
||||
#include <re_mbuf.h>
|
||||
#include <re_list.h>
|
||||
#include <re_sa.h>
|
||||
#include <re_tmr.h>
|
||||
#include <re_bfcp.h>
|
||||
#include "bfcp.h"
|
||||
|
||||
|
||||
enum {
|
||||
BFCP_T2 = 10000,
|
||||
};
|
||||
|
||||
|
||||
static void tmr_handler(void *arg)
|
||||
{
|
||||
struct bfcp_conn *bc = arg;
|
||||
|
||||
bc->mb = mem_deref(bc->mb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send a BFCP response
|
||||
*
|
||||
* @param bc BFCP connection
|
||||
* @param req BFCP request message
|
||||
* @param prim BFCP Primitive
|
||||
* @param attrc Number of attributes
|
||||
*
|
||||
* @return 0 if success, otherwise errorcode
|
||||
*/
|
||||
int bfcp_reply(struct bfcp_conn *bc, const struct bfcp_msg *req,
|
||||
enum bfcp_prim prim, uint32_t attrc, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int err;
|
||||
|
||||
if (!bc || !req)
|
||||
return EINVAL;
|
||||
|
||||
bc->mb = mem_deref(bc->mb);
|
||||
tmr_cancel(&bc->tmr2);
|
||||
|
||||
bc->mb = mbuf_alloc(64);
|
||||
if (!bc->mb)
|
||||
return ENOMEM;
|
||||
|
||||
va_start(ap, attrc);
|
||||
err = bfcp_msg_vencode(bc->mb, BFCP_VER2, true, prim, req->confid,
|
||||
req->tid, req->userid, attrc, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
bc->mb->pos = 0;
|
||||
|
||||
err = bfcp_send(bc, &req->src, bc->mb);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
bc->st.prim = req->prim;
|
||||
bc->st.confid = req->confid;
|
||||
bc->st.tid = req->tid;
|
||||
bc->st.userid = req->userid;
|
||||
|
||||
tmr_start(&bc->tmr2, BFCP_T2, tmr_handler, bc);
|
||||
|
||||
out:
|
||||
if (err)
|
||||
bc->mb = mem_deref(bc->mb);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send a BFCP error response with details
|
||||
*
|
||||
* @param bc BFCP connection
|
||||
* @param req BFCP request message
|
||||
* @param code Error code
|
||||
* @param details Error details
|
||||
* @param len Details length
|
||||
*
|
||||
* @return 0 if success, otherwise errorcode
|
||||
*/
|
||||
int bfcp_edreply(struct bfcp_conn *bc, const struct bfcp_msg *req,
|
||||
enum bfcp_err code, const uint8_t *details, size_t len)
|
||||
{
|
||||
struct bfcp_errcode errcode;
|
||||
|
||||
errcode.code = code;
|
||||
errcode.details = (uint8_t *)details;
|
||||
errcode.len = len;
|
||||
|
||||
return bfcp_reply(bc, req, BFCP_ERROR, 1,
|
||||
BFCP_ERROR_CODE, 0, &errcode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send a BFCP error response
|
||||
*
|
||||
* @param bc BFCP connection
|
||||
* @param req BFCP request message
|
||||
* @param code Error code
|
||||
*
|
||||
* @return 0 if success, otherwise errorcode
|
||||
*/
|
||||
int bfcp_ereply(struct bfcp_conn *bc, const struct bfcp_msg *req,
|
||||
enum bfcp_err code)
|
||||
{
|
||||
return bfcp_edreply(bc, req, code, NULL, 0);
|
||||
}
|
171
src/bfcp/req.c
171
src/bfcp/req.c
|
@ -1,171 +0,0 @@
|
|||
/**
|
||||
* @file bfcp/req.c BFCP Client request
|
||||
*
|
||||
* Copyright (C) 2010 Creytiv.com
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <re_types.h>
|
||||
#include <re_fmt.h>
|
||||
#include <re_mem.h>
|
||||
#include <re_mbuf.h>
|
||||
#include <re_list.h>
|
||||
#include <re_tmr.h>
|
||||
#include <re_sa.h>
|
||||
#include <re_bfcp.h>
|
||||
#include "bfcp.h"
|
||||
|
||||
|
||||
struct bfcp_ctrans {
|
||||
struct le le;
|
||||
struct tmr tmr;
|
||||
struct bfcp_ctrans **ctp;
|
||||
uint16_t tid;
|
||||
bfcp_resp_h *resph;
|
||||
void *arg;
|
||||
};
|
||||
|
||||
|
||||
static void destructor(void *arg)
|
||||
{
|
||||
struct bfcp_ctrans *ct = arg;
|
||||
|
||||
list_unlink(&ct->le);
|
||||
tmr_cancel(&ct->tmr);
|
||||
}
|
||||
|
||||
|
||||
static void timeout(void *arg)
|
||||
{
|
||||
struct bfcp_ctrans *ct = arg;
|
||||
|
||||
bfcp_ctrans_completed(ct, ETIMEDOUT, NULL);
|
||||
}
|
||||
|
||||
|
||||
static struct bfcp_ctrans *ctrans_new(struct bfcp_sock *sock,
|
||||
bfcp_resp_h *resph, void *arg)
|
||||
{
|
||||
struct bfcp_ctrans *ct;
|
||||
|
||||
ct = mem_zalloc(sizeof(*ct), destructor);
|
||||
if (!ct)
|
||||
return NULL;
|
||||
|
||||
list_append(&sock->transl, &ct->le, ct);
|
||||
|
||||
sock->tidc++;
|
||||
|
||||
if (sock->tidc == 0)
|
||||
sock->tidc++;
|
||||
|
||||
ct->tid = sock->tidc;
|
||||
ct->resph = resph;
|
||||
ct->arg = arg;
|
||||
|
||||
tmr_start(&ct->tmr, 10000, timeout, ct);
|
||||
|
||||
return ct;
|
||||
}
|
||||
|
||||
|
||||
void bfcp_ctrans_completed(struct bfcp_ctrans *ct, int err,
|
||||
const struct bfcp_msg *msg)
|
||||
{
|
||||
bfcp_resp_h *resph = ct->resph;
|
||||
void *arg = ct->arg;
|
||||
|
||||
list_unlink(&ct->le);
|
||||
tmr_cancel(&ct->tmr);
|
||||
|
||||
if (ct->ctp) {
|
||||
*ct->ctp = NULL;
|
||||
ct->ctp = NULL;
|
||||
}
|
||||
|
||||
ct->resph = NULL;
|
||||
|
||||
mem_deref(ct);
|
||||
|
||||
if (resph)
|
||||
resph(err, msg, arg);
|
||||
}
|
||||
|
||||
|
||||
struct bfcp_ctrans *bfcp_ctrans_find(struct bfcp_sock *sock, uint16_t tid)
|
||||
{
|
||||
struct le *le;
|
||||
|
||||
for (le = sock->transl.head; le; le = le->next) {
|
||||
|
||||
struct bfcp_ctrans *ct = le->data;
|
||||
|
||||
if (ct->tid == tid)
|
||||
return ct;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send a BFCP request with variable number of attributes
|
||||
*
|
||||
* @param ctp Pointer to allocated transaction (optional)
|
||||
* @param sock BFCP socket
|
||||
* @param dst Destination network address
|
||||
* @param prim BFCP primitive
|
||||
* @param confid Conference ID
|
||||
* @param userid User ID
|
||||
* @param resph Response handler (optional)
|
||||
* @param arg Handler argument
|
||||
* @param attrc Number of BFCP attributes
|
||||
*
|
||||
* @return 0 if success, otherwise errorcode
|
||||
*/
|
||||
int bfcp_request(struct bfcp_ctrans **ctp, struct bfcp_sock *sock,
|
||||
const struct sa *dst,
|
||||
enum bfcp_prim prim, uint32_t confid, uint16_t userid,
|
||||
bfcp_resp_h *resph, void *arg, uint32_t attrc, ...)
|
||||
{
|
||||
struct bfcp_ctrans *ct;
|
||||
struct mbuf *mb;
|
||||
va_list ap;
|
||||
int err;
|
||||
|
||||
if (!sock || !dst || !confid || !userid)
|
||||
return EINVAL;
|
||||
|
||||
ct = ctrans_new(sock, resph, arg);
|
||||
if (!ct)
|
||||
return ENOMEM;
|
||||
|
||||
mb = mbuf_alloc(512);
|
||||
if (!mb) {
|
||||
err = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
va_start(ap, attrc);
|
||||
err = bfcp_msg_vencode(mb, prim, confid, ct->tid, userid,
|
||||
attrc, ap);
|
||||
va_end(ap);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
mb->pos = 0;
|
||||
|
||||
err = bfcp_send(sock, dst, mb);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
if (err)
|
||||
mem_deref(ct);
|
||||
else if (ctp) {
|
||||
ct->ctp = ctp;
|
||||
*ctp = ct;
|
||||
}
|
||||
|
||||
mem_deref(mb);
|
||||
return err;
|
||||
}
|
255
src/bfcp/request.c
Normal file
255
src/bfcp/request.c
Normal file
|
@ -0,0 +1,255 @@
|
|||
/**
|
||||
* @file bfcp/request.c BFCP Request
|
||||
*
|
||||
* Copyright (C) 2010 Creytiv.com
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <re_types.h>
|
||||
#include <re_fmt.h>
|
||||
#include <re_mem.h>
|
||||
#include <re_mbuf.h>
|
||||
#include <re_list.h>
|
||||
#include <re_sa.h>
|
||||
#include <re_tmr.h>
|
||||
#include <re_bfcp.h>
|
||||
#include "bfcp.h"
|
||||
|
||||
|
||||
enum {
|
||||
BFCP_T1 = 500,
|
||||
BFCP_TXC = 4,
|
||||
};
|
||||
|
||||
|
||||
struct bfcp_ctrans {
|
||||
struct le le;
|
||||
struct sa dst;
|
||||
struct mbuf *mb;
|
||||
bfcp_resp_h *resph;
|
||||
void *arg;
|
||||
uint32_t confid;
|
||||
uint16_t userid;
|
||||
uint16_t tid;
|
||||
};
|
||||
|
||||
|
||||
static void tmr_handler(void *arg);
|
||||
|
||||
|
||||
static void dummy_resp_handler(int err, const struct bfcp_msg *msg, void *arg)
|
||||
{
|
||||
(void)err;
|
||||
(void)msg;
|
||||
(void)arg;
|
||||
}
|
||||
|
||||
|
||||
static void destructor(void *arg)
|
||||
{
|
||||
struct bfcp_ctrans *ct = arg;
|
||||
|
||||
list_unlink(&ct->le);
|
||||
mem_deref(ct->mb);
|
||||
}
|
||||
|
||||
|
||||
static void dispatch(struct bfcp_conn *bc)
|
||||
{
|
||||
struct le *le = bc->ctransl.head;
|
||||
|
||||
while (le) {
|
||||
struct bfcp_ctrans *ct = le->data;
|
||||
int err;
|
||||
|
||||
le = le->next;
|
||||
|
||||
err = bfcp_send(bc, &ct->dst, ct->mb);
|
||||
if (err) {
|
||||
ct->resph(err, NULL, ct->arg);
|
||||
mem_deref(ct);
|
||||
continue;
|
||||
}
|
||||
|
||||
tmr_start(&bc->tmr1, BFCP_T1, tmr_handler, bc);
|
||||
bc->txc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void tmr_handler(void *arg)
|
||||
{
|
||||
struct bfcp_conn *bc = arg;
|
||||
struct bfcp_ctrans *ct;
|
||||
uint32_t timeout;
|
||||
int err;
|
||||
|
||||
ct = list_ledata(bc->ctransl.head);
|
||||
if (!ct)
|
||||
return;
|
||||
|
||||
timeout = BFCP_T1<<bc->txc;
|
||||
|
||||
if (++bc->txc > BFCP_TXC) {
|
||||
err = ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = bfcp_send(bc, &ct->dst, ct->mb);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
tmr_start(&bc->tmr1, timeout, tmr_handler, bc);
|
||||
return;
|
||||
|
||||
out:
|
||||
ct->resph(err, NULL, ct->arg);
|
||||
mem_deref(ct);
|
||||
dispatch(bc);
|
||||
}
|
||||
|
||||
|
||||
bool bfcp_handle_response(struct bfcp_conn *bc, const struct bfcp_msg *msg)
|
||||
{
|
||||
struct bfcp_ctrans *ct;
|
||||
|
||||
if (!bc || !msg)
|
||||
return false;
|
||||
|
||||
ct = list_ledata(bc->ctransl.head);
|
||||
if (!ct)
|
||||
return false;
|
||||
|
||||
if (msg->tid != ct->tid)
|
||||
return false;
|
||||
|
||||
if (msg->confid != ct->confid)
|
||||
return false;
|
||||
|
||||
if (msg->userid != ct->userid)
|
||||
return false;
|
||||
|
||||
tmr_cancel(&bc->tmr1);
|
||||
|
||||
ct->resph(0, msg, ct->arg);
|
||||
mem_deref(ct);
|
||||
|
||||
dispatch(bc);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int bfcp_vrequest(struct bfcp_conn *bc, const struct sa *dst,
|
||||
enum bfcp_prim prim, uint32_t confid, uint16_t userid,
|
||||
bfcp_resp_h *resph, void *arg, uint32_t attrc, va_list ap)
|
||||
{
|
||||
struct bfcp_ctrans *ct;
|
||||
int err;
|
||||
|
||||
if (!bc || !dst)
|
||||
return EINVAL;
|
||||
|
||||
ct = mem_zalloc(sizeof(*ct), destructor);
|
||||
if (!ct)
|
||||
return ENOMEM;
|
||||
|
||||
if (bc->tid == 0)
|
||||
bc->tid = 1;
|
||||
|
||||
ct->dst = *dst;
|
||||
ct->confid = confid;
|
||||
ct->userid = userid;
|
||||
ct->tid = bc->tid++;
|
||||
ct->resph = resph ? resph : dummy_resp_handler;
|
||||
ct->arg = arg;
|
||||
|
||||
ct->mb = mbuf_alloc(128);
|
||||
if (!ct->mb) {
|
||||
err = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = bfcp_msg_vencode(ct->mb, BFCP_VER2, false, prim, confid, ct->tid,
|
||||
userid, attrc, ap);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
ct->mb->pos = 0;
|
||||
|
||||
if (!bc->ctransl.head) {
|
||||
|
||||
err = bfcp_send(bc, &ct->dst, ct->mb);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
tmr_start(&bc->tmr1, BFCP_T1, tmr_handler, bc);
|
||||
bc->txc = 1;
|
||||
}
|
||||
|
||||
list_append(&bc->ctransl, &ct->le, ct);
|
||||
|
||||
out:
|
||||
if (err)
|
||||
mem_deref(ct);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send a BFCP request
|
||||
*
|
||||
* @param bc BFCP connection
|
||||
* @param dst Destination address
|
||||
* @param prim BFCP Primitive
|
||||
* @param confid Conference ID
|
||||
* @param userid User ID
|
||||
* @param resph Response handler
|
||||
* @param arg Response handler argument
|
||||
* @param attrc Number of attributes
|
||||
*
|
||||
* @return 0 if success, otherwise errorcode
|
||||
*/
|
||||
int bfcp_request(struct bfcp_conn *bc, const struct sa *dst,
|
||||
enum bfcp_prim prim, uint32_t confid, uint16_t userid,
|
||||
bfcp_resp_h *resph, void *arg, uint32_t attrc, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int err;
|
||||
|
||||
va_start(ap, attrc);
|
||||
err = bfcp_vrequest(bc, dst, prim, confid, userid, resph, arg,
|
||||
attrc, ap);
|
||||
va_end(ap);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send a BFCP notification/subsequent response
|
||||
*
|
||||
* @param bc BFCP connection
|
||||
* @param dst Destination address
|
||||
* @param prim BFCP Primitive
|
||||
* @param confid Conference ID
|
||||
* @param userid User ID
|
||||
* @param attrc Number of attributes
|
||||
*
|
||||
* @return 0 if success, otherwise errorcode
|
||||
*/
|
||||
int bfcp_notify(struct bfcp_conn *bc, const struct sa *dst,
|
||||
enum bfcp_prim prim, uint32_t confid, uint16_t userid,
|
||||
uint32_t attrc, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int err;
|
||||
|
||||
va_start(ap, attrc);
|
||||
err = bfcp_vrequest(bc, dst, prim, confid, userid, NULL, NULL,
|
||||
attrc, ap);
|
||||
va_end(ap);
|
||||
|
||||
return err;
|
||||
}
|
352
src/bfcp/sock.c
352
src/bfcp/sock.c
|
@ -1,352 +0,0 @@
|
|||
/**
|
||||
* @file bfcp/sock.c BFCP Socket
|
||||
*
|
||||
* Copyright (C) 2010 Creytiv.com
|
||||
*/
|
||||
#include <re_types.h>
|
||||
#include <re_fmt.h>
|
||||
#include <re_mem.h>
|
||||
#include <re_mbuf.h>
|
||||
#include <re_list.h>
|
||||
#include <re_tmr.h>
|
||||
#include <re_sa.h>
|
||||
#include <re_tcp.h>
|
||||
#include <re_tls.h>
|
||||
#include <re_bfcp.h>
|
||||
#include "bfcp.h"
|
||||
|
||||
|
||||
struct bfcp_conn {
|
||||
struct le le;
|
||||
struct sa paddr;
|
||||
struct mbuf *mbtx;
|
||||
struct mbuf *mbrx;
|
||||
struct tcp_conn *tc;
|
||||
struct tls_conn *sc;
|
||||
struct bfcp_sock *bs;
|
||||
bool established;
|
||||
};
|
||||
|
||||
|
||||
static void destructor(void *arg)
|
||||
{
|
||||
struct bfcp_sock *sock = arg;
|
||||
|
||||
list_flush(&sock->transl);
|
||||
list_flush(&sock->connl);
|
||||
mem_deref(sock->tls);
|
||||
mem_deref(sock->ts);
|
||||
}
|
||||
|
||||
|
||||
static void conn_destructor(void *arg)
|
||||
{
|
||||
struct bfcp_conn *conn = arg;
|
||||
|
||||
list_unlink(&conn->le);
|
||||
mem_deref(conn->mbtx);
|
||||
mem_deref(conn->mbrx);
|
||||
mem_deref(conn->sc);
|
||||
mem_deref(conn->tc);
|
||||
}
|
||||
|
||||
|
||||
static struct bfcp_conn *conn_add(struct bfcp_sock *bs,
|
||||
const struct sa *paddr)
|
||||
{
|
||||
struct bfcp_conn *bc = mem_zalloc(sizeof(*bc), conn_destructor);
|
||||
if (!bc)
|
||||
return NULL;
|
||||
|
||||
list_append(&bs->connl, &bc->le, bc);
|
||||
|
||||
bc->bs = bs;
|
||||
bc->paddr = *paddr;
|
||||
|
||||
return bc;
|
||||
}
|
||||
|
||||
|
||||
static void tcp_estab_handler(void *arg)
|
||||
{
|
||||
struct bfcp_conn *conn = arg;
|
||||
|
||||
#ifdef USE_TLS
|
||||
if (conn->sc) {
|
||||
char cn[256];
|
||||
int err;
|
||||
|
||||
err = tls_verify_cert(conn->sc, cn, sizeof(cn));
|
||||
|
||||
(void)re_printf("CN: '%s' (%sverified)\n",
|
||||
cn, err ? "not " : "");
|
||||
}
|
||||
#endif
|
||||
|
||||
conn->established = true;
|
||||
|
||||
/* flush transmit buffer */
|
||||
if (conn->mbtx) {
|
||||
|
||||
conn->mbtx->pos = 0;
|
||||
if (tcp_send(conn->tc, conn->mbtx))
|
||||
return;
|
||||
|
||||
conn->mbtx = mem_deref(conn->mbtx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void tcp_recv_handler(struct mbuf *mb, void *arg)
|
||||
{
|
||||
struct bfcp_conn *conn = arg;
|
||||
size_t pos;
|
||||
int err = 0;
|
||||
|
||||
if (conn->mbrx) {
|
||||
pos = conn->mbrx->pos;
|
||||
|
||||
conn->mbrx->pos = conn->mbrx->end;
|
||||
|
||||
err = mbuf_write_mem(conn->mbrx,
|
||||
mbuf_buf(mb), mbuf_get_left(mb));
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
conn->mbrx->pos = pos;
|
||||
}
|
||||
else {
|
||||
conn->mbrx = mem_ref(mb);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
struct bfcp_msg *msg;
|
||||
struct bfcp_ctrans *ct;
|
||||
|
||||
pos = conn->mbrx->pos;
|
||||
|
||||
err = bfcp_msg_decode(&msg, conn->mbrx, &conn->paddr);
|
||||
if (err) {
|
||||
if (err == ENODATA) {
|
||||
conn->mbrx->pos = pos;
|
||||
err = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ct = bfcp_ctrans_find(conn->bs, bfcp_msg_tid(msg));
|
||||
if (ct) {
|
||||
bfcp_ctrans_completed(ct, 0, msg);
|
||||
}
|
||||
else {
|
||||
if (conn->bs->msgh)
|
||||
conn->bs->msgh(msg, conn->bs->arg);
|
||||
}
|
||||
|
||||
mem_deref(msg);
|
||||
|
||||
if (0 == mbuf_get_left(conn->mbrx)) {
|
||||
conn->mbrx = mem_deref(conn->mbrx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (err)
|
||||
mem_deref(conn);
|
||||
}
|
||||
|
||||
|
||||
static void tcp_close_handler(int err, void *arg)
|
||||
{
|
||||
struct bfcp_conn *conn = arg;
|
||||
|
||||
(void)re_printf("BFCP connection closed: %m\n", err);
|
||||
|
||||
mem_deref(conn);
|
||||
}
|
||||
|
||||
|
||||
static void tcp_conn_handler(const struct sa *addr, void *arg)
|
||||
{
|
||||
struct bfcp_sock *bs = arg;
|
||||
struct bfcp_conn *conn;
|
||||
|
||||
(void)re_printf("bfcpd: Connection from %J via %s\n", addr,
|
||||
bs->transp == BFCP_TRANSP_TLS ? "TLS" : "TCP");
|
||||
|
||||
conn = conn_add(bs, addr);
|
||||
if (conn) {
|
||||
if (tcp_accept(&conn->tc, bs->ts, tcp_estab_handler,
|
||||
tcp_recv_handler, tcp_close_handler, conn))
|
||||
goto error;
|
||||
|
||||
#ifdef USE_TLS
|
||||
if (bs->transp == BFCP_TRANSP_TLS) {
|
||||
if (tls_start_tcp(&conn->sc, bs->tls, conn->tc, 0))
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
error:
|
||||
tcp_reject(bs->ts);
|
||||
mem_deref(conn);
|
||||
}
|
||||
|
||||
|
||||
static struct bfcp_conn *findconn(const struct bfcp_sock *bs,
|
||||
const struct sa *peer)
|
||||
{
|
||||
struct le *le;
|
||||
|
||||
for (le = bs->connl.head; le; le = le->next) {
|
||||
|
||||
struct bfcp_conn *bc = le->data;
|
||||
|
||||
if (sa_cmp(&bc->paddr, peer, SA_ALL))
|
||||
return bc;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Listen on a BFCP socket
|
||||
*
|
||||
* @param sockp Pointer to allocated BFCP socket object
|
||||
* @param transp BFCP transport
|
||||
* @param tls TLS context, used for secure transport (optional)
|
||||
* @param laddr Local network address (optional)
|
||||
* @param msgh BFCP message handler (optional)
|
||||
* @param arg Handler argument
|
||||
*
|
||||
* @return 0 if success, otherwise errorcode
|
||||
*/
|
||||
int bfcp_listen(struct bfcp_sock **sockp, enum bfcp_transp transp,
|
||||
struct tls *tls, const struct sa *laddr,
|
||||
bfcp_msg_h *msgh, void *arg)
|
||||
{
|
||||
struct bfcp_sock *sock;
|
||||
int err = 0;
|
||||
|
||||
if (!sockp)
|
||||
return EINVAL;
|
||||
|
||||
sock = mem_zalloc(sizeof(*sock), destructor);
|
||||
if (!sock)
|
||||
return ENOMEM;
|
||||
|
||||
sock->transp = transp;
|
||||
sock->tls = mem_ref(tls);
|
||||
sock->msgh = msgh;
|
||||
sock->arg = arg;
|
||||
|
||||
/* Server */
|
||||
if (laddr) {
|
||||
switch (transp) {
|
||||
|
||||
case BFCP_TRANSP_TLS:
|
||||
if (!tls) {
|
||||
err = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
/*@fallthrough@*/
|
||||
|
||||
case BFCP_TRANSP_TCP:
|
||||
sock->active = false;
|
||||
err = tcp_listen(&sock->ts, laddr, tcp_conn_handler,
|
||||
sock);
|
||||
break;
|
||||
|
||||
default:
|
||||
err = EPROTONOSUPPORT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sock->active = true;
|
||||
}
|
||||
|
||||
out:
|
||||
if (err)
|
||||
mem_deref(sock);
|
||||
else if (sockp)
|
||||
*sockp = sock;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int bfcp_send(struct bfcp_sock *sock, const struct sa *dst, struct mbuf *mb)
|
||||
{
|
||||
struct bfcp_conn *conn = NULL;
|
||||
int err = 0;
|
||||
|
||||
if (!sock || !dst || !mb)
|
||||
return EINVAL;
|
||||
|
||||
switch (sock->transp) {
|
||||
|
||||
case BFCP_TRANSP_TCP:
|
||||
case BFCP_TRANSP_TLS:
|
||||
|
||||
conn = findconn(sock, dst);
|
||||
|
||||
if (!conn) {
|
||||
|
||||
if (!sock->active)
|
||||
return ENOTCONN;
|
||||
|
||||
conn = conn_add(sock, dst);
|
||||
if (!conn) {
|
||||
err = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = tcp_connect(&conn->tc, dst, tcp_estab_handler,
|
||||
tcp_recv_handler,
|
||||
tcp_close_handler, conn);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
#ifdef USE_TLS
|
||||
if (sock->transp == BFCP_TRANSP_TLS) {
|
||||
|
||||
err = tls_start_tcp(&conn->sc, sock->tls,
|
||||
conn->tc, 0);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (conn->established) {
|
||||
err = tcp_send(conn->tc, mb);
|
||||
}
|
||||
else {
|
||||
if (!conn->mbtx) {
|
||||
conn->mbtx = mem_ref(mb);
|
||||
}
|
||||
else {
|
||||
conn->mbtx->pos = conn->mbtx->end;
|
||||
err = mbuf_write_mem(conn->mbtx, mbuf_buf(mb),
|
||||
mbuf_get_left(mb));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
err = EPROTONOSUPPORT;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
if (err)
|
||||
mem_deref(conn);
|
||||
|
||||
return err;
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/**
|
||||
* @file bfcp/transp.c BFCP Transport
|
||||
*
|
||||
* Copyright (C) 2010 Creytiv.com
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <re_types.h>
|
||||
#include <re_fmt.h>
|
||||
#include <re_mem.h>
|
||||
#include <re_mbuf.h>
|
||||
#include <re_list.h>
|
||||
#include <re_tmr.h>
|
||||
#include <re_sa.h>
|
||||
#include <re_tcp.h>
|
||||
#include <re_bfcp.h>
|
||||
#include "bfcp.h"
|
||||
|
||||
|
||||
/**
|
||||
* Check if BFCP transport is reliable
|
||||
*
|
||||
* @param tp BFCP transport
|
||||
*
|
||||
* @return True if reliable, false if un-reliable
|
||||
*/
|
||||
bool bfcp_transp_reliable(enum bfcp_transp tp)
|
||||
{
|
||||
switch (tp) {
|
||||
|
||||
case BFCP_TRANSP_TCP: return true;
|
||||
case BFCP_TRANSP_TLS: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the BFCP Transport protocol, suitable for SDP
|
||||
*
|
||||
* @param tp BFCP transport
|
||||
*
|
||||
* @return String with BFCP transport protocol
|
||||
*/
|
||||
const char *bfcp_transp_proto(enum bfcp_transp tp)
|
||||
{
|
||||
switch (tp) {
|
||||
|
||||
case BFCP_TRANSP_TCP: return "TCP/BFCP";
|
||||
case BFCP_TRANSP_TLS: return "TCP/TLS/BFCP";
|
||||
default: return "???";
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue