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 <info(a)sysmocom.de>
+ * Author: Vadim Yanitskiy <vyanitskiy(a)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 <vyanitskiy(a)sysmocom.de>
Gerrit-MessageType: newchange