FreeCalypso > hg > themwi-system-sw
view rtp-mgr/ctrl_prot.c @ 217:9f6a148ceb25
tcpserv-dump: brown paper bag
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 24 Jul 2023 22:33:01 -0800 |
parents | 3962d9345a09 |
children |
line wrap: on
line source
/* * In this module we implement our control socket protocol. */ #include <sys/types.h> #include <sys/socket.h> #include <sys/uio.h> #include <netinet/in.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include <syslog.h> #include <unistd.h> #include "../include/tmgw_const.h" #include "../include/rtp_alloc.h" #include "struct.h" #include "select.h" extern struct bind_range_cfg bind_range_gsm, bind_range_pstn; static void free_rtp_end(roe) struct rtp_one_end *roe; { close(roe->rtp_fd); close(roe->rtcp_fd); } static void close_fds(fd_list, num_fd) int *fd_list, num_fd; { int i; for (i = 0; i < num_fd; i++) close(fd_list[i]); } void ctrl_message_handler(fd) { struct rtp_alloc_req req; struct rtp_alloc_resp resp; struct rtp_one_end rtp_gsm, rtp_pstn; struct iovec iov; struct msghdr msg; int fd_out[4], num_fd, *fd_bufptr; union { char buf[CMSG_SPACE(sizeof fd_out)]; struct cmsghdr align; } cmsgu; struct cmsghdr *cmsg; int rc; /* receive request */ rc = recv(fd, &req, sizeof req, 0); if (rc < sizeof req) { syslog(LOG_DEBUG, "ctrl connection closing"); close(fd); FD_CLR(fd, &select_for_read); return; } /* start preparing response */ bzero(&resp, sizeof resp); resp.transact_ref = req.transact_ref; switch (req.ep_type) { case TMGW_EP_TYPE_GSM_ONLY: case TMGW_EP_TYPE_PSTN_ONLY: case TMGW_EP_TYPE_GATEWAY: break; default: resp.res = RTP_ALLOC_ERR_PARAM; error_resp: send(fd, &resp, sizeof resp, 0); return; } /* allocate resources */ if (req.ep_type & TMGW_EP_HAS_GSM_SOCK) { rc = get_rtp_port_pair(&rtp_gsm, &bind_range_gsm); if (rc < 0) { syslog(LOG_ERR, "unable to get local port pair on GSM side"); resp.res = RTP_ALLOC_ERR_RSRC; goto error_resp; } } if (req.ep_type & TMGW_EP_HAS_PSTN_SOCK) { rc = get_rtp_port_pair(&rtp_pstn, &bind_range_pstn); if (rc < 0) { syslog(LOG_ERR, "unable to get local port pair on PSTN side"); if (req.ep_type & TMGW_EP_HAS_GSM_SOCK) free_rtp_end(&rtp_gsm); resp.res = RTP_ALLOC_ERR_RSRC; goto error_resp; } } /* finish ordinary body of response */ resp.res = RTP_ALLOC_OK; if (req.ep_type & TMGW_EP_HAS_GSM_SOCK) bcopy(&rtp_gsm.bound_addr, &resp.gsm_addr, sizeof(struct sockaddr_in)); if (req.ep_type & TMGW_EP_HAS_PSTN_SOCK) bcopy(&rtp_pstn.bound_addr, &resp.pstn_addr, sizeof(struct sockaddr_in)); iov.iov_base = &resp; iov.iov_len = sizeof resp; /* file descriptor passing voodoo */ switch (req.ep_type) { case TMGW_EP_TYPE_GSM_ONLY: num_fd = 2; fd_out[0] = rtp_gsm.rtp_fd; fd_out[1] = rtp_gsm.rtcp_fd; break; case TMGW_EP_TYPE_PSTN_ONLY: num_fd = 2; fd_out[0] = rtp_pstn.rtp_fd; fd_out[1] = rtp_pstn.rtcp_fd; break; case TMGW_EP_TYPE_GATEWAY: num_fd = 4; fd_out[0] = rtp_gsm.rtp_fd; fd_out[1] = rtp_gsm.rtcp_fd; fd_out[2] = rtp_pstn.rtp_fd; fd_out[3] = rtp_pstn.rtcp_fd; } bzero(&msg, sizeof msg); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = cmsgu.buf; msg.msg_controllen = CMSG_SPACE(sizeof(int) * num_fd); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fd); fd_bufptr = (int *) CMSG_DATA(cmsg); bcopy(fd_out, fd_bufptr, sizeof(int) * num_fd); sendmsg(fd, &msg, 0); close_fds(fd_out, num_fd); }