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