1 /**
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
destructor(void * arg)19 static 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
strans_cmp(const struct bfcp_strans * st,const struct bfcp_msg * msg)31 static 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
udp_recv_handler(const struct sa * src,struct mbuf * mb,void * arg)50 static 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
73 out:
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 */
bfcp_listen(struct bfcp_conn ** bcp,enum bfcp_transp tp,struct sa * laddr,struct tls * tls,bfcp_recv_h * recvh,void * arg)90 int 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
bfcp_send(struct bfcp_conn * bc,const struct sa * dst,struct mbuf * mb)137 int 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
bfcp_sock(const struct bfcp_conn * bc)153 void *bfcp_sock(const struct bfcp_conn *bc)
154 {
155 return bc ? bc->us : NULL;
156 }
157