blob: cfe066eae4ee726444aea389db2aabef157ef7b0 [file] [log] [blame]
James Kuszmaul82f6c042021-01-17 11:30:16 -08001/**
2 * @file bfcp/request.c BFCP Request
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
18enum {
19 BFCP_T1 = 500,
20 BFCP_TXC = 4,
21};
22
23
24struct bfcp_ctrans {
25 struct le le;
26 struct sa dst;
27 struct mbuf *mb;
28 bfcp_resp_h *resph;
29 void *arg;
30 uint32_t confid;
31 uint16_t userid;
32 uint16_t tid;
33};
34
35
36static void tmr_handler(void *arg);
37
38
39static void dummy_resp_handler(int err, const struct bfcp_msg *msg, void *arg)
40{
41 (void)err;
42 (void)msg;
43 (void)arg;
44}
45
46
47static void destructor(void *arg)
48{
49 struct bfcp_ctrans *ct = arg;
50
51 list_unlink(&ct->le);
52 mem_deref(ct->mb);
53}
54
55
56static void dispatch(struct bfcp_conn *bc)
57{
58 struct le *le = bc->ctransl.head;
59
60 while (le) {
61 struct bfcp_ctrans *ct = le->data;
62 int err;
63
64 le = le->next;
65
66 err = bfcp_send(bc, &ct->dst, ct->mb);
67 if (err) {
68 ct->resph(err, NULL, ct->arg);
69 mem_deref(ct);
70 continue;
71 }
72
73 tmr_start(&bc->tmr1, BFCP_T1, tmr_handler, bc);
74 bc->txc = 1;
75 break;
76 }
77}
78
79
80static void tmr_handler(void *arg)
81{
82 struct bfcp_conn *bc = arg;
83 struct bfcp_ctrans *ct;
84 uint32_t timeout;
85 int err;
86
87 ct = list_ledata(bc->ctransl.head);
88 if (!ct)
89 return;
90
91 timeout = BFCP_T1<<bc->txc;
92
93 if (++bc->txc > BFCP_TXC) {
94 err = ETIMEDOUT;
95 goto out;
96 }
97
98 err = bfcp_send(bc, &ct->dst, ct->mb);
99 if (err)
100 goto out;
101
102 tmr_start(&bc->tmr1, timeout, tmr_handler, bc);
103 return;
104
105 out:
106 ct->resph(err, NULL, ct->arg);
107 mem_deref(ct);
108 dispatch(bc);
109}
110
111
112bool bfcp_handle_response(struct bfcp_conn *bc, const struct bfcp_msg *msg)
113{
114 struct bfcp_ctrans *ct;
115
116 if (!bc || !msg)
117 return false;
118
119 ct = list_ledata(bc->ctransl.head);
120 if (!ct)
121 return false;
122
123 if (msg->tid != ct->tid)
124 return false;
125
126 if (msg->confid != ct->confid)
127 return false;
128
129 if (msg->userid != ct->userid)
130 return false;
131
132 tmr_cancel(&bc->tmr1);
133
134 ct->resph(0, msg, ct->arg);
135 mem_deref(ct);
136
137 dispatch(bc);
138
139 return true;
140}
141
142
143int bfcp_vrequest(struct bfcp_conn *bc, const struct sa *dst, uint8_t ver,
144 enum bfcp_prim prim, uint32_t confid, uint16_t userid,
145 bfcp_resp_h *resph, void *arg, unsigned attrc, va_list *ap)
146{
147 struct bfcp_ctrans *ct;
148 int err;
149
150 if (!bc || !dst)
151 return EINVAL;
152
153 ct = mem_zalloc(sizeof(*ct), destructor);
154 if (!ct)
155 return ENOMEM;
156
157 if (bc->tid == 0)
158 bc->tid = 1;
159
160 ct->dst = *dst;
161 ct->confid = confid;
162 ct->userid = userid;
163 ct->tid = bc->tid++;
164 ct->resph = resph ? resph : dummy_resp_handler;
165 ct->arg = arg;
166
167 ct->mb = mbuf_alloc(128);
168 if (!ct->mb) {
169 err = ENOMEM;
170 goto out;
171 }
172
173 err = bfcp_msg_vencode(ct->mb, ver, false, prim, confid, ct->tid,
174 userid, attrc, ap);
175 if (err)
176 goto out;
177
178 ct->mb->pos = 0;
179
180 if (!bc->ctransl.head) {
181
182 err = bfcp_send(bc, &ct->dst, ct->mb);
183 if (err)
184 goto out;
185
186 tmr_start(&bc->tmr1, BFCP_T1, tmr_handler, bc);
187 bc->txc = 1;
188 }
189
190 list_append(&bc->ctransl, &ct->le, ct);
191
192 out:
193 if (err)
194 mem_deref(ct);
195
196 return err;
197}
198
199
200/**
201 * Send a BFCP request
202 *
203 * @param bc BFCP connection
204 * @param dst Destination address
205 * @param ver BFCP Version
206 * @param prim BFCP Primitive
207 * @param confid Conference ID
208 * @param userid User ID
209 * @param resph Response handler
210 * @param arg Response handler argument
211 * @param attrc Number of attributes
212 *
213 * @return 0 if success, otherwise errorcode
214 */
215int bfcp_request(struct bfcp_conn *bc, const struct sa *dst, uint8_t ver,
216 enum bfcp_prim prim, uint32_t confid, uint16_t userid,
217 bfcp_resp_h *resph, void *arg, unsigned attrc, ...)
218{
219 va_list ap;
220 int err;
221
222 va_start(ap, attrc);
223 err = bfcp_vrequest(bc, dst, ver, prim, confid, userid, resph, arg,
224 attrc, &ap);
225 va_end(ap);
226
227 return err;
228}
229
230
231/**
232 * Send a BFCP notification/subsequent response
233 *
234 * @param bc BFCP connection
235 * @param dst Destination address
236 * @param ver BFCP Version
237 * @param prim BFCP Primitive
238 * @param confid Conference ID
239 * @param userid User ID
240 * @param attrc Number of attributes
241 *
242 * @return 0 if success, otherwise errorcode
243 */
244int bfcp_notify(struct bfcp_conn *bc, const struct sa *dst, uint8_t ver,
245 enum bfcp_prim prim, uint32_t confid, uint16_t userid,
246 unsigned attrc, ...)
247{
248 va_list ap;
249 int err;
250
251 va_start(ap, attrc);
252 err = bfcp_vrequest(bc, dst, ver, prim, confid, userid, NULL, NULL,
253 attrc, &ap);
254 va_end(ap);
255
256 return err;
257}