blob: 6e4051d1f9f551f4bea167579e500b61d607bfc2 [file] [log] [blame]
James Kuszmaul82f6c042021-01-17 11:30:16 -08001/**
2 * @file bfcp/conn.c BFCP Connection
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_udp.h>
14#include <re_tmr.h>
15#include <re_bfcp.h>
16#include "bfcp.h"
17
18
19static void destructor(void *arg)
20{
21 struct bfcp_conn *bc = arg;
22
23 list_flush(&bc->ctransl);
24 tmr_cancel(&bc->tmr1);
25 tmr_cancel(&bc->tmr2);
26 mem_deref(bc->us);
27 mem_deref(bc->mb);
28}
29
30
31static bool strans_cmp(const struct bfcp_strans *st,
32 const struct bfcp_msg *msg)
33{
34 if (st->tid != msg->tid)
35 return false;
36
37 if (st->prim != msg->prim)
38 return false;
39
40 if (st->confid != msg->confid)
41 return false;
42
43 if (st->userid != msg->userid)
44 return false;
45
46 return true;
47}
48
49
50static void udp_recv_handler(const struct sa *src, struct mbuf *mb, void *arg)
51{
52 struct bfcp_conn *bc = arg;
53 struct bfcp_msg *msg;
54 int err;
55
56 err = bfcp_msg_decode(&msg, mb);
57 if (err)
58 return;
59
60 msg->src = *src;
61
62 if (bfcp_handle_response(bc, msg))
63 goto out;
64
65 if (bc->mb && strans_cmp(&bc->st, msg)) {
66 (void)bfcp_send(bc, &msg->src, bc->mb);
67 goto out;
68 }
69
70 if (bc->recvh)
71 bc->recvh(msg, bc->arg);
72
73out:
74 mem_deref(msg);
75}
76
77
78/**
79 * Create BFCP connection
80 *
81 * @param bcp Pointer to BFCP connection
82 * @param tp BFCP Transport type
83 * @param laddr Optional listening address/port
84 * @param tls TLS Context (optional)
85 * @param recvh Receive handler
86 * @param arg Receive handler argument
87 *
88 * @return 0 if success, otherwise errorcode
89 */
90int bfcp_listen(struct bfcp_conn **bcp, enum bfcp_transp tp, struct sa *laddr,
91 struct tls *tls, bfcp_recv_h *recvh, void *arg)
92{
93 struct bfcp_conn *bc;
94 int err;
95 (void)tls;
96
97 if (!bcp)
98 return EINVAL;
99
100 bc = mem_zalloc(sizeof(*bc), destructor);
101 if (!bc)
102 return ENOMEM;
103
104 bc->tp = tp;
105 bc->recvh = recvh;
106 bc->arg = arg;
107
108 switch (bc->tp) {
109
110 case BFCP_UDP:
111 err = udp_listen(&bc->us, laddr, udp_recv_handler, bc);
112 if (err)
113 goto out;
114
115 if (laddr) {
116 err = udp_local_get(bc->us, laddr);
117 if (err)
118 goto out;
119 }
120 break;
121
122 default:
123 err = ENOSYS;
124 goto out;
125 }
126
127 out:
128 if (err)
129 mem_deref(bc);
130 else
131 *bcp = bc;
132
133 return err;
134}
135
136
137int bfcp_send(struct bfcp_conn *bc, const struct sa *dst, struct mbuf *mb)
138{
139 if (!bc || !dst || !mb)
140 return EINVAL;
141
142 switch (bc->tp) {
143
144 case BFCP_UDP:
145 return udp_send(bc->us, dst, mb);
146
147 default:
148 return ENOSYS;
149 }
150}
151
152
153void *bfcp_sock(const struct bfcp_conn *bc)
154{
155 return bc ? bc->us : NULL;
156}