FreeCalypso > hg > themwi-rtp-mgr
diff librtpalloc/simple_client.c @ 6:191d58f5c24f
librtpalloc: port the simple client
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 27 May 2024 21:10:01 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/librtpalloc/simple_client.c Mon May 27 21:10:01 2024 +0000 @@ -0,0 +1,148 @@ +/* + * The library function implemented in this C module provides a + * simple interface for obtaining a single RTP endpoint from + * themwi-rtp-mgr. This "simple client" option is suitable only + * for command line utilities, not for daemon processes! + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> + +#include <themwi/rtp/rtp_alloc_if.h> +#include <themwi/rtp/rtp_alloc_resp.h> +#include <themwi/rtp/rtp_alloc_simple.h> + +static const char ctrl_socket_pathname[] = "/var/gsm/rtp_alloc_socket"; + +static void +fill_sockaddr_un(pathname, sunp, lenp) + char *pathname; + struct sockaddr_un *sunp; + unsigned *lenp; +{ + /* local socket binding voodoo copied from osmocon */ + sunp->sun_family = AF_UNIX; + strncpy(sunp->sun_path, pathname, sizeof(sunp->sun_path)); + sunp->sun_path[sizeof(sunp->sun_path) - 1] = '\0'; + /* we use the same magic that X11 uses in Xtranssock.c for + * calculating the proper length of the sockaddr */ +#if defined(BSD44SOCKETS) || defined(__UNIXWARE__) + sunp->sun_len = strlen(sunp->sun_path); +#endif +#if defined(BSD44SOCKETS) || defined(SUN_LEN) + *lenp = SUN_LEN(sunp); +#else + *lenp = strlen(sunp->sun_path) + + offsetof(struct sockaddr_un, sun_path) + 1; +#endif +} + +static void +close_fds(resp) + struct rtp_alloc_resp_wrap *resp; +{ + unsigned n; + + for (n = 0; n < resp->num_fd; n++) + close(resp->fd_buf[n]); +} + +int rtp_alloc_simple(int ep_type, struct rtp_alloc_simple *out) +{ + struct sockaddr_un sa; + unsigned sa_len; + int ctrl_fd, rc; + struct rtp_alloc_req req; + struct rtp_alloc_resp_wrap resp; + unsigned expect_num_fd; + + switch (ep_type) { + case RTP_ALLOC_TYPE_GSM: + case RTP_ALLOC_TYPE_PSTN: + expect_num_fd = 2; + break; + case RTP_ALLOC_TYPE_GSM2PSTN: + case RTP_ALLOC_TYPE_GSM2GSM: + expect_num_fd = 4; + break; + default: + fprintf(stderr, + "rtp_alloc_simple() error: unknown EP type %d\n", + ep_type); + return(-1); + } + ctrl_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (ctrl_fd < 0) { + perror("socket(AF_UNIX, SOCK_SEQPACKET, 0)"); + return(-1); + } + fill_sockaddr_un(ctrl_socket_pathname, &sa, &sa_len); + rc = connect(ctrl_fd, (struct sockaddr *) &sa, sa_len); + if (rc < 0) { + perror(ctrl_socket_pathname); + close(ctrl_fd); + return(-1); + } + bzero(&req, sizeof req); + req.ep_type = ep_type; + rc = send(ctrl_fd, &req, sizeof req, 0); + if (rc < 0) { + perror("send to RTP allocator socket"); + close(ctrl_fd); + return(-1); + } + rc = collect_rtpmgr_resp(ctrl_fd, 0, &resp); + if (rc < 0) { + perror("recvmsg from RTP allocator socket"); + close(ctrl_fd); + return(-1); + } + close(ctrl_fd); + if (resp.resp_len != sizeof(struct rtp_alloc_resp)) { + fprintf(stderr, +"error: response packet from themwi-rtp-mgr has wrong length (%u bytes)\n", + resp.resp_len); + close_fds(&resp); + return(-1); + } + if (resp.resp.res != RTP_ALLOC_OK) { + fprintf(stderr, "themwi-rtp-mgr returned error %u\n", + resp.resp.res); + close_fds(&resp); + return(-1); + } + if (resp.num_fd != expect_num_fd) { + fprintf(stderr, +"error: themwi-rtp-mgr returned %u descriptors instead of expected %u\n", + resp.num_fd, expect_num_fd); + close_fds(&resp); + return(-1); + } + switch (ep_type) { + case RTP_ALLOC_TYPE_GSM: + out->gsm_rtp_fd = resp.fd_buf[0]; + out->gsm_rtcp_fd = resp.fd_buf[1]; + break; + case RTP_ALLOC_TYPE_PSTN: + out->pstn_rtp_fd = resp.fd_buf[0]; + out->pstn_rtcp_fd = resp.fd_buf[1]; + break; + case RTP_ALLOC_TYPE_GSM2PSTN: + case RTP_ALLOC_TYPE_GSM2GSM: + out->gsm_rtp_fd = resp.fd_buf[0]; + out->gsm_rtcp_fd = resp.fd_buf[1]; + out->pstn_rtp_fd = resp.fd_buf[2]; + out->pstn_rtcp_fd = resp.fd_buf[3]; + } + bcopy(&resp.resp.gsm_addr, &out->gsm_addr, + sizeof(struct sockaddr_storage)); + bcopy(&resp.resp.pstn_addr, &out->pstn_addr, + sizeof(struct sockaddr_storage)); + return(0); +}