FreeCalypso > hg > themwi-system-sw
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 } |
