fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmocom-bb/+/35583?usp=email )
Change subject: [WIP] mobile: implement sending CSD data over UNIX socket ...................................................................... [WIP] mobile: implement sending CSD data over UNIX socket Change-Id: Id054af7b3d9d0a41715f7981deb420f6e09bf30c Related: OS#4396 --- M src/host/layer23/include/osmocom/bb/mobile/tch.h M src/host/layer23/src/mobile/Makefile.am M src/host/layer23/src/mobile/tch_data.c A src/host/layer23/src/mobile/tch_data_sock.c 4 files changed, 284 insertions(+), 11 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/83/35583/1 diff --git a/src/host/layer23/include/osmocom/bb/mobile/tch.h b/src/host/layer23/include/osmocom/bb/mobile/tch.h index a31655a..c3c957a 100644 --- a/src/host/layer23/include/osmocom/bb/mobile/tch.h +++ b/src/host/layer23/include/osmocom/bb/mobile/tch.h @@ -13,6 +13,7 @@ } voice; struct tch_data_state { enum tch_data_io_handler handler; + struct tch_csd_sock_state *sock; struct osmo_v110_ta *v110_ta; struct osmo_soft_uart *suart; } data; diff --git a/src/host/layer23/src/mobile/Makefile.am b/src/host/layer23/src/mobile/Makefile.am index b4e45e2..d00e45e 100644 --- a/src/host/layer23/src/mobile/Makefile.am +++ b/src/host/layer23/src/mobile/Makefile.am @@ -33,6 +33,7 @@ primitives.c \ tch.c \ tch_data.c \ + tch_data_sock.c \ tch_voice.c \ transaction.c \ vty_interface.c \ diff --git a/src/host/layer23/src/mobile/tch_data.c b/src/host/layer23/src/mobile/tch_data.c index 082c397..21ed1c2 100644 --- a/src/host/layer23/src/mobile/tch_data.c +++ b/src/host/layer23/src/mobile/tch_data.c @@ -72,21 +72,31 @@ }, }; +struct tch_csd_sock_state *tch_csd_sock_init(void *ctx, const char *sock_path); +int tch_csd_sock_recv(struct tch_csd_sock_state *state, struct msgb *msg); +int tch_csd_sock_send(struct tch_csd_sock_state *state, struct msgb *msg); +void tch_csd_sock_exit(struct tch_csd_sock_state *state); + static void tch_soft_uart_rx_cb(void *priv, struct msgb *msg, unsigned int flags) { - LOGP(DL1C, LOGL_FATAL, "%s(): [flags=0x%08x] %s\n", + struct tch_data_state *state = (struct tch_data_state *)priv; + + LOGP(DL1C, LOGL_DEBUG, "%s(): [flags=0x%08x] %s\n", __func__, flags, msgb_hexdump(msg)); - msgb_free(msg); + + if (state->sock != NULL && msgb_length(msg) > 0) + tch_csd_sock_send(state->sock, msg); + else + msgb_free(msg); } static void tch_soft_uart_tx_cb(void *priv, struct msgb *msg) { - const char *data = "TEST\r\n"; - size_t n_bytes; + struct tch_data_state *state = (struct tch_data_state *)priv; + int n_bytes = tch_csd_sock_recv(state->sock, msg); - n_bytes = OSMO_MIN(msg->data_len, strlen(data)); - if (n_bytes > 0) - memcpy(msgb_put(msg, n_bytes), (void *)data, n_bytes); + LOGP(DL1C, LOGL_DEBUG, "%s(): [n_bytes=%u/%u] %s\n", + __func__, n_bytes, msg->data_len, msgb_hexdump(msg)); } struct osmo_soft_uart *tch_soft_uart_alloc(struct osmocom_ms *ms) @@ -169,7 +179,7 @@ int tch_csd_rx_from_l1(struct osmocom_ms *ms, struct msgb *msg) { - struct tch_data_state *state = &ms->tch_state->data; + const struct tch_data_state *state = &ms->tch_state->data; const struct gsm48_rr_cd *cd = &ms->rrlayer.cd_now; const struct csd_v110_frame_desc *desc; ubit_t data[4 * 60]; @@ -217,7 +227,7 @@ int tch_csd_tx_to_l1(struct osmocom_ms *ms) { - struct tch_data_state *state = &ms->tch_state->data; + const struct tch_data_state *state = &ms->tch_state->data; const struct gsm48_rr_cd *cd = &ms->rrlayer.cd_now; const struct csd_v110_frame_desc *desc; ubit_t data[60 * 4]; @@ -299,10 +309,13 @@ struct tch_data_state *state) { struct osmocom_ms *ms = trans->ms; + const struct gsm_settings *set = &ms->settings; switch (state->handler) { case TCH_DATA_IOH_UNIX_SOCK: - /* TODO: open listening socket */ + state->sock = tch_csd_sock_init(ms, set->tch_data.unix_socket_path); + if (state->sock == NULL) + return -ENOMEM; break; case TCH_DATA_IOH_LOOPBACK: case TCH_DATA_IOH_NONE: @@ -325,6 +338,8 @@ return 0; exit_free: + if (state->sock != NULL) + tch_csd_sock_exit(state->sock); if (state->suart != NULL) osmo_soft_uart_free(state->suart); if (state->v110_ta != NULL) @@ -341,7 +356,8 @@ switch (state->handler) { case TCH_DATA_IOH_UNIX_SOCK: - /* TODO: close listening socket */ + if (state->sock != NULL) + tch_csd_sock_exit(state->sock); break; default: break; diff --git a/src/host/layer23/src/mobile/tch_data_sock.c b/src/host/layer23/src/mobile/tch_data_sock.c new file mode 100644 index 0000000..c5cde6c --- /dev/null +++ b/src/host/layer23/src/mobile/tch_data_sock.c @@ -0,0 +1,245 @@ +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH <i...@sysmocom.de> + * Author: Vadim Yanitskiy <vyanits...@sysmocom.de> + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <assert.h> +#include <stdint.h> +#include <sys/socket.h> +#include <sys/un.h> + +#include <osmocom/core/talloc.h> +#include <osmocom/core/select.h> +#include <osmocom/core/timer.h> +#include <osmocom/core/msgb.h> +#include <osmocom/core/socket.h> + +#include <osmocom/bb/common/logging.h> +#include <osmocom/bb/common/osmocom_data.h> +#include <osmocom/bb/common/ms.h> +#include <osmocom/bb/mobile/tch.h> + +struct tch_csd_sock_state { + struct osmo_fd listen_bfd; /* fd for listen socket */ + struct osmo_fd conn_bfd; /* fd for a client connection */ + struct llist_head rxqueue; + struct llist_head txqueue; +}; + +static void tch_csd_sock_close(struct tch_csd_sock_state *state) +{ + struct osmo_fd *bfd = &state->conn_bfd; + + LOGP(DMOB, LOGL_NOTICE, "TCH CSD sock has closed connection\n"); + + osmo_fd_unregister(bfd); + close(bfd->fd); + bfd->fd = -1; + + /* re-enable the generation of ACCEPT for new connections */ + osmo_fd_read_enable(&state->listen_bfd); + + /* flush the queues */ + while (!llist_empty(&state->rxqueue)) + msgb_free(msgb_dequeue(&state->rxqueue)); + while (!llist_empty(&state->txqueue)) + msgb_free(msgb_dequeue(&state->txqueue)); +} + +static int tch_csd_sock_read(struct osmo_fd *bfd) +{ + struct tch_csd_sock_state *state = (struct tch_csd_sock_state *)bfd->data; + struct msgb *msg; + int rc; + + msg = msgb_alloc(256, "tch_csd_sock_rx"); + if (!msg) + return -ENOMEM; + + rc = recv(bfd->fd, msg->tail, msgb_tailroom(msg), 0); + if (rc == 0) + goto close; + if (rc < 0) { + if (errno == EAGAIN) + return 0; + goto close; + } + + msgb_put(msg, rc); + msgb_enqueue(&state->rxqueue, msg); + return rc; + +close: + msgb_free(msg); + tch_csd_sock_close(state); + return -1; +} + +static int tch_csd_sock_write(struct osmo_fd *bfd) +{ + struct tch_csd_sock_state *state = bfd->data; + + while (!llist_empty(&state->txqueue)) { + struct msgb *msg; + int rc; + + /* dequeue a msgb */ + msg = msgb_dequeue(&state->txqueue); + osmo_fd_write_disable(bfd); + + /* try to send it over the socket */ + rc = write(bfd->fd, msgb_data(msg), msgb_length(msg)); + if (rc == 0) { + llist_add(&msg->list, &state->txqueue); + goto close; + } else if (rc < 0) { + if (errno == EAGAIN) { + osmo_fd_write_enable(bfd); + break; + } + llist_add(&msg->list, &state->txqueue); + goto close; + } + } + + return 0; + +close: + tch_csd_sock_close(state); + return -1; +} + +static int tch_csd_sock_cb(struct osmo_fd *bfd, unsigned int flags) +{ + int rc = 0; + + if (flags & OSMO_FD_READ) { + rc = tch_csd_sock_read(bfd); + if (rc < 0) + return rc; + } + + if (flags & OSMO_FD_WRITE) + rc = tch_csd_sock_write(bfd); + + return rc; +} + +static int tch_csd_sock_accept(struct osmo_fd *bfd, unsigned int flags) +{ + struct tch_csd_sock_state *state = (struct tch_csd_sock_state *)bfd->data; + struct osmo_fd *conn_bfd = &state->conn_bfd; + struct sockaddr_un un_addr; + socklen_t len; + int rc; + + len = sizeof(un_addr); + rc = accept(bfd->fd, (struct sockaddr *)&un_addr, &len); + if (rc < 0) { + LOGP(DMOB, LOGL_ERROR, "Failed to accept() a new connection\n"); + return -1; + } + + if (conn_bfd->fd >= 0) { + LOGP(DMOB, LOGL_NOTICE, "TCH CSD sock already has an active connection\n"); + osmo_fd_read_disable(&state->listen_bfd); + close(rc); + return 0; + } + + osmo_fd_setup(conn_bfd, rc, OSMO_FD_READ, &tch_csd_sock_cb, state, 0); + if (osmo_fd_register(conn_bfd) != 0) { + LOGP(DMOB, LOGL_ERROR, "osmo_fd_register() failed\n"); + close(conn_bfd->fd); + conn_bfd->fd = -1; + return -1; + } + + LOGP(DMOB, LOGL_NOTICE, "TCH CSD sock got a connection\n"); + + return 0; +} + +struct tch_csd_sock_state *tch_csd_sock_init(void *ctx, const char *sock_path) +{ + struct tch_csd_sock_state *state; + struct osmo_fd *bfd; + int rc; + + state = talloc_zero(ctx, struct tch_csd_sock_state); + if (state == NULL) + return NULL; + + INIT_LLIST_HEAD(&state->rxqueue); + INIT_LLIST_HEAD(&state->txqueue); + state->conn_bfd.fd = -1; + + bfd = &state->listen_bfd; + + rc = osmo_sock_unix_init_ofd(bfd, SOCK_SEQPACKET, 0, sock_path, OSMO_SOCK_F_BIND); + if (rc < 0) { + LOGP(DMOB, LOGL_ERROR, "Could not create unix socket: %s\n", strerror(errno)); + talloc_free(state); + return NULL; + } + + bfd->cb = &tch_csd_sock_accept; + bfd->data = state; + + return state; +} + +void tch_csd_sock_exit(struct tch_csd_sock_state *state) +{ + if (state->conn_bfd.fd > -1) + tch_csd_sock_close(state); + osmo_fd_unregister(&state->listen_bfd); + close(state->listen_bfd.fd); + talloc_free(state); +} + +int tch_csd_sock_recv(struct tch_csd_sock_state *state, struct msgb *msg) +{ + unsigned int n_bytes = 0; + + while (msgb_tailroom(msg) > 0) { + struct msgb *rmsg = msgb_dequeue(&state->rxqueue); + if (rmsg == NULL) + break; + size_t len = OSMO_MIN(msgb_tailroom(msg), msgb_length(rmsg)); + memcpy(msgb_put(msg, len), msgb_data(rmsg), len); + msgb_pull(rmsg, len); + if (msgb_length(rmsg) > 0) + llist_add(&rmsg->list, &state->rxqueue); + else + msgb_free(rmsg); + n_bytes += len; + } + + return n_bytes; +} + +int tch_csd_sock_send(struct tch_csd_sock_state *state, struct msgb *msg) +{ + msgb_enqueue(&state->txqueue, msg); + osmo_fd_write_enable(&state->conn_bfd); + return 0; +} -- To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/35583?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: Id054af7b3d9d0a41715f7981deb420f6e09bf30c Gerrit-Change-Number: 35583 Gerrit-PatchSet: 1 Gerrit-Owner: fixeria <vyanits...@sysmocom.de> Gerrit-MessageType: newchange