1 /**
2  * @file bfcp/reply.c BFCP Reply
3  *
4  * Copyright (C) 2010 Creytiv.com
5  */
6 #include <string.h>
7 #include <re_types.h>
8 #include <re_fmt.h>
9 #include <re_mem.h>
10 #include <re_mbuf.h>
11 #include <re_list.h>
12 #include <re_sa.h>
13 #include <re_tmr.h>
14 #include <re_bfcp.h>
15 #include "bfcp.h"
16 
17 
18 enum {
19 	BFCP_T2  = 10000,
20 };
21 
22 
tmr_handler(void * arg)23 static void tmr_handler(void *arg)
24 {
25 	struct bfcp_conn *bc = arg;
26 
27 	bc->mb = mem_deref(bc->mb);
28 }
29 
30 
31 /**
32  * Send a BFCP response
33  *
34  * @param bc      BFCP connection
35  * @param req     BFCP request message
36  * @param prim    BFCP Primitive
37  * @param attrc   Number of attributes
38  *
39  * @return 0 if success, otherwise errorcode
40  */
bfcp_reply(struct bfcp_conn * bc,const struct bfcp_msg * req,enum bfcp_prim prim,unsigned attrc,...)41 int bfcp_reply(struct bfcp_conn *bc, const struct bfcp_msg *req,
42 	       enum bfcp_prim prim, unsigned attrc, ...)
43 {
44 	va_list ap;
45 	int err;
46 
47 	if (!bc || !req)
48 		return EINVAL;
49 
50 	bc->mb = mem_deref(bc->mb);
51 	tmr_cancel(&bc->tmr2);
52 
53 	bc->mb = mbuf_alloc(64);
54 	if (!bc->mb)
55 		return ENOMEM;
56 
57 	va_start(ap, attrc);
58 	err = bfcp_msg_vencode(bc->mb, req->ver, true, prim, req->confid,
59 			       req->tid, req->userid, attrc, &ap);
60 	va_end(ap);
61 
62 	if (err)
63 		goto out;
64 
65 	bc->mb->pos = 0;
66 
67 	err = bfcp_send(bc, &req->src, bc->mb);
68 	if (err)
69 		goto out;
70 
71 	bc->st.prim   = req->prim;
72 	bc->st.confid = req->confid;
73 	bc->st.tid    = req->tid;
74 	bc->st.userid = req->userid;
75 
76 	tmr_start(&bc->tmr2, BFCP_T2, tmr_handler, bc);
77 
78  out:
79 	if (err)
80 		bc->mb = mem_deref(bc->mb);
81 
82 	return err;
83 }
84 
85 
86 /**
87  * Send a BFCP error response with details
88  *
89  * @param bc      BFCP connection
90  * @param req     BFCP request message
91  * @param code    Error code
92  * @param details Error details
93  * @param len     Details length
94  *
95  * @return 0 if success, otherwise errorcode
96  */
bfcp_edreply(struct bfcp_conn * bc,const struct bfcp_msg * req,enum bfcp_err code,const uint8_t * details,size_t len)97 int bfcp_edreply(struct bfcp_conn *bc, const struct bfcp_msg *req,
98 		 enum bfcp_err code, const uint8_t *details, size_t len)
99 {
100 	struct bfcp_errcode errcode;
101 
102 	errcode.code    = code;
103 	errcode.details = (uint8_t *)details;
104 	errcode.len     = len;
105 
106 	return bfcp_reply(bc, req, BFCP_ERROR, 1,
107 			  BFCP_ERROR_CODE, 0, &errcode);
108 }
109 
110 
111 /**
112  * Send a BFCP error response
113  *
114  * @param bc      BFCP connection
115  * @param req     BFCP request message
116  * @param code    Error code
117  *
118  * @return 0 if success, otherwise errorcode
119  */
bfcp_ereply(struct bfcp_conn * bc,const struct bfcp_msg * req,enum bfcp_err code)120 int bfcp_ereply(struct bfcp_conn *bc, const struct bfcp_msg *req,
121 		enum bfcp_err code)
122 {
123 	return bfcp_edreply(bc, req, code, NULL, 0);
124 }
125