comparison mgw/crcx.c @ 32:b3f74df7b808

beginning of themwi-mgw
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 09 Jul 2022 22:51:44 -0800
parents
children 7dae2bae56a1
comparison
equal deleted inserted replaced
31:08d7794cdd0a 32:b3f74df7b808
1 /*
2 * In this module we implement our CRCX operation.
3 */
4
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <netinet/in.h>
8 #include <arpa/inet.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <strings.h>
13 #include <syslog.h>
14 #include <unistd.h>
15 #include "../include/tmgw_ctrl.h"
16 #include "../include/tmgw_const.h"
17 #include "struct.h"
18 #include "select.h"
19
20 extern struct endpoint *find_ep_by_id();
21 extern void udp_sink_rcvr();
22
23 extern struct bind_range_cfg bind_range_gsm, bind_range_pstn;
24
25 static unsigned
26 get_new_ep_id(conn)
27 struct ctrl_conn *conn;
28 {
29 unsigned id;
30
31 for (;;) {
32 id = conn->next_ep_id++;
33 if (!find_ep_by_id(conn, id))
34 return id;
35 }
36 }
37
38 static int
39 get_local_port_pair(ep, roe, brc)
40 struct endpoint *ep;
41 struct rtp_one_end *roe;
42 struct bind_range_cfg *brc;
43 {
44 struct sockaddr_in sin;
45 unsigned tries, rtp_port;
46 int rc;
47
48 sin.sin_family = AF_INET;
49 sin.sin_addr = brc->bind_ip;
50 for (tries = brc->port_tries; tries; tries--) {
51 rtp_port = brc->port_next;
52 brc->port_next += 2;
53 if (brc->port_next >= brc->port_range_end)
54 brc->port_next = brc->port_range_start;
55 sin.sin_port = htons(rtp_port);
56 roe->rtp_fd = socket(AF_INET, SOCK_DGRAM, 0);
57 if (roe->rtp_fd < 0) {
58 syslog(LOG_CRIT, "socket(AF_INET, SOCK_DGRAM, 0): %m");
59 return(-1);
60 }
61 rc = bind(roe->rtp_fd, (struct sockaddr *) &sin, sizeof sin);
62 if (rc < 0) {
63 close(roe->rtp_fd);
64 continue;
65 }
66 bcopy(&sin, &roe->bound_addr, sizeof(struct sockaddr_in));
67 sin.sin_port = htons(rtp_port+1);
68 roe->rtcp_fd = socket(AF_INET, SOCK_DGRAM, 0);
69 if (roe->rtcp_fd < 0) {
70 syslog(LOG_CRIT, "socket(AF_INET, SOCK_DGRAM, 0): %m");
71 close(roe->rtp_fd);
72 return(-1);
73 }
74 rc = bind(roe->rtcp_fd, (struct sockaddr *) &sin, sizeof sin);
75 if (rc < 0) {
76 close(roe->rtp_fd);
77 close(roe->rtcp_fd);
78 continue;
79 }
80 /* all good - make the file descriptors live for select */
81 update_max_fd(roe->rtp_fd);
82 FD_SET(roe->rtp_fd, &select_for_read);
83 select_handlers[roe->rtp_fd] = udp_sink_rcvr;
84 select_data[roe->rtp_fd] = (void *) ep;
85 update_max_fd(roe->rtcp_fd);
86 FD_SET(roe->rtcp_fd, &select_for_read);
87 select_handlers[roe->rtcp_fd] = udp_sink_rcvr;
88 select_data[roe->rtcp_fd] = (void *) ep;
89 return(0);
90 }
91 /* couldn't find a free port pair */
92 return(-1);
93 }
94
95 void
96 process_crcx(conn, req, resp)
97 struct ctrl_conn *conn;
98 struct tmgw_ctrl_req *req;
99 struct tmgw_ctrl_resp *resp;
100 {
101 struct endpoint *ep;
102 int rc;
103
104 /* ep_id in request encodes ep_type */
105 switch (req->ep_id) {
106 case TMGW_EP_TYPE_DUMMY_GSM:
107 case TMGW_EP_TYPE_DUMMY_PSTN:
108 case TMGW_EP_TYPE_GATEWAY:
109 break;
110 default:
111 resp->res = TMGW_RESP_ERR_PROT;
112 return;
113 }
114 ep = malloc(sizeof(struct endpoint));
115 if (!ep) {
116 syslog(LOG_CRIT, "malloc for endpoint: %m");
117 resp->res = TMGW_RESP_ERR_RSRC;
118 return;
119 }
120 bzero(ep, sizeof(struct endpoint));
121 ep->ep_type = req->ep_id;
122 ep->ep_id = get_new_ep_id(conn);
123 if (ep->ep_type & TMGW_EP_HAS_GSM_SOCK) {
124 rc = get_local_port_pair(ep, &ep->rtp_gsm, &bind_range_gsm);
125 if (rc < 0) {
126 syslog(LOG_ERR,
127 "unable to get local port pair on GSM side");
128 free(ep);
129 resp->res = TMGW_RESP_ERR_RSRC;
130 return;
131 }
132 }
133 if (ep->ep_type & TMGW_EP_HAS_PSTN_SOCK) {
134 rc = get_local_port_pair(ep, &ep->rtp_pstn, &bind_range_pstn);
135 if (rc < 0) {
136 syslog(LOG_ERR,
137 "unable to get local port pair on PSTN side");
138 if (ep->ep_type & TMGW_EP_HAS_GSM_SOCK)
139 free_rtp_end(&ep->rtp_gsm);
140 free(ep);
141 resp->res = TMGW_RESP_ERR_RSRC;
142 return;
143 }
144 }
145 rc = mdcx_operation(ep, req, resp);
146 if (rc < 0) {
147 if (ep->ep_type & TMGW_EP_HAS_GSM_SOCK)
148 free_rtp_end(&ep->rtp_gsm);
149 if (ep->ep_type & TMGW_EP_HAS_PSTN_SOCK)
150 free_rtp_end(&ep->rtp_pstn);
151 free(ep);
152 return;
153 }
154 /* all good - accept the new endpoint and return OK */
155 ep->next = conn->endp_list;
156 conn->endp_list = ep;
157 resp->res = TMGW_RESP_OK;
158 resp->ep_id = ep->ep_id;
159 bcopy(&ep->rtp_gsm.bound_addr, &resp->gsm_addr,
160 sizeof(struct sockaddr_in));
161 bcopy(&ep->rtp_pstn.bound_addr, &resp->pstn_addr,
162 sizeof(struct sockaddr_in));
163 syslog(LOG_INFO, "CRCX endpoint type %u id %u", ep->ep_type, ep->ep_id);
164 }