merge from re/branches/bfcp2

This commit is contained in:
Alfred E. Heggestad 2013-02-22 22:07:12 +00:00
parent 0c4cdc4c3b
commit 5f9f9eac4b
13 changed files with 1256 additions and 1563 deletions

View file

@ -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);

File diff suppressed because it is too large Load diff

View file

@ -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
View 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;
}
}

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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
View 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);
}

View file

@ -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
View 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;
}

View file

@ -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;
}

View file

@ -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 "???";
}
}