From 6973a241a89ce28d635a5102246453490a6e6722 Mon Sep 17 00:00:00 2001 From: Max Date: Sat, 30 Jul 2022 17:11:25 +0700 Subject: [PATCH] libosmonetify SMPP Use libosmo-netif instead of socket interface. Note: osmo_stream_srv_recv() is not used for now to keep as much of existing code as possible and make troubleshooting easier. Related: OS#5568 Change-Id: Idc2e60af1010783e555e61b114ae61f55a89d890 Signed-off-by: Max --- include/osmocom/msc/smpp.h | 5 +- src/libmsc/Makefile.am | 1 + src/libmsc/smpp_smsc.c | 102 ++++++++++++++----------------------- src/libmsc/smpp_smsc.h | 2 +- src/libmsc/smpp_utils.c | 20 ++------ src/libmsc/smpp_vty.c | 8 +-- src/utils/Makefile.am | 1 + src/utils/smpp_mirror.c | 2 +- tests/smpp/Makefile.am | 1 + 9 files changed, 57 insertions(+), 85 deletions(-) diff --git a/include/osmocom/msc/smpp.h b/include/osmocom/msc/smpp.h index c30812f82..f3eaa6599 100644 --- a/include/osmocom/msc/smpp.h +++ b/include/osmocom/msc/smpp.h @@ -1,5 +1,7 @@ #pragma once +#define SMPP_DEFAULT_PORT 2775 + /* Length limits according to SMPP 3.4 spec including NUL-byte: */ #define SMPP_SYS_ID_LEN 15 #define SMPP_PASSWD_LEN 8 @@ -15,6 +17,8 @@ enum esme_read_state { struct esme { uint32_t own_seq_nr; + /* represents the TCP connection we accept()ed for this ESME */ + struct osmo_stream_srv *srv; struct osmo_wqueue wqueue; enum esme_read_state read_state; uint32_t read_len; @@ -67,7 +71,6 @@ struct esme { uint32_t smpp_msgb_cmdid(struct msgb *msg); uint32_t esme_inc_seq_nr(struct esme *esme); void esme_read_state_reset(struct esme *esme); -void esme_queue_reset(struct esme *esme); int esme_write_callback(struct esme *esme, int fd, struct msgb *msg); int esme_read_callback(struct esme *esme, int fd); int pack_and_send(struct esme *esme, uint32_t type, void *ptr); diff --git a/src/libmsc/Makefile.am b/src/libmsc/Makefile.am index fe59cf594..d3c3b1efc 100644 --- a/src/libmsc/Makefile.am +++ b/src/libmsc/Makefile.am @@ -109,6 +109,7 @@ libsmpputil_a_SOURCES = \ libsmpputil_a_CFLAGS = \ $(LIBSMPP34_CFLAGS) \ $(LIBOSMOCORE_CFLAGS) \ + $(LIBOSMONETIF_CFLAGS) \ $(NULL) libsmpputil_a_LIBADD = \ diff --git a/src/libmsc/smpp_smsc.c b/src/libmsc/smpp_smsc.c index 604156bd7..6309909b4 100644 --- a/src/libmsc/smpp_smsc.c +++ b/src/libmsc/smpp_smsc.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include "smpp_smsc.h" @@ -160,8 +161,6 @@ void smpp_acl_delete(struct osmo_smpp_acl *acl) /* kill any active ESMEs */ if (acl->esme) { - struct esme *esme = acl->esme->esme; - esme_queue_reset(esme); acl->esme = NULL; smpp_esme_put(acl->esme); } @@ -237,14 +236,14 @@ void smpp_esme_get(struct osmo_esme *esme) static void esme_destroy(struct osmo_esme *esme) { - osmo_wqueue_clear(&esme->esme->wqueue); - if (esme->esme->wqueue.bfd.fd >= 0) { - esme_queue_reset(esme->esme); - } + if (esme->use < 0) + return; + smpp_cmd_flush_pending(esme); llist_del(&esme->list); if (esme->acl) esme->acl->esme = NULL; + osmo_stream_srv_destroy(esme->esme->srv); talloc_free(esme); } @@ -720,9 +719,10 @@ static int smpp_pdu_rx(struct osmo_esme *esme, struct msgb *msg __uses) } /* !\brief call-back when per-ESME TCP socket has some data to be read */ -static int esme_link_read_cb(struct osmo_fd *ofd) +static int esme_link_read_cb(struct osmo_stream_srv *conn) { - struct osmo_esme *e = ofd->data; + struct osmo_esme *e = osmo_stream_srv_get_data(conn); + struct osmo_fd *ofd = osmo_stream_srv_get_ofd(conn); struct esme *esme = e->esme; int rc = esme_read_callback(esme, ofd->fd); @@ -743,27 +743,25 @@ static int esme_link_read_cb(struct osmo_fd *ofd) return 0; } -/* call-back of write queue once it wishes to write a message to the socket */ -static int esme_link_write_cb(struct osmo_fd *ofd, struct msgb *msg) +/* call-back when new connection is closed on ESME */ +static int esme_link_close_cb(struct osmo_stream_srv *conn) { - struct osmo_esme *esme = ofd->data; - int rc = esme_write_callback(esme->esme, ofd->fd, msg); + struct osmo_esme *esme = osmo_stream_srv_get_data(conn); - if (rc == 0) { - if (esme->acl) - esme->acl->esme = NULL; - smpp_esme_put(esme); - } else if (rc == -1) { - return -1; - } + LOGPESME(esme->esme, LOGL_NOTICE, "Connection lost\n"); + + if (esme->acl) + esme->acl->esme = NULL; + + smpp_esme_put(esme); return 0; } /* callback for already-accepted new TCP socket */ -static int link_accept_cb(struct smsc *smsc, int fd, - struct sockaddr_storage *s, socklen_t s_len) +static int link_accept_cb(struct osmo_stream_srv_link *link, int fd) { + struct smsc *smsc = osmo_stream_srv_link_get_data(link); struct osmo_esme *esme = talloc_zero(smsc, struct osmo_esme); if (!esme) { close(fd); @@ -780,39 +778,17 @@ static int link_accept_cb(struct smsc *smsc, int fd, esme->esme->own_seq_nr = rand(); esme_inc_seq_nr(esme->esme); esme->smsc = smsc; - osmo_wqueue_init(&esme->esme->wqueue, 10); - osmo_fd_setup(&esme->esme->wqueue.bfd, fd, OSMO_FD_READ, osmo_wqueue_bfd_cb, esme, 0); - - if (osmo_fd_register(&esme->esme->wqueue.bfd) != 0) { - close(fd); + esme->esme->srv = osmo_stream_srv_create(esme, link, fd, esme_link_read_cb, esme_link_close_cb, esme); + if (!esme->esme->srv) { talloc_free(esme); - return -EIO; + return -EINVAL; } - esme->esme->wqueue.read_cb = esme_link_read_cb; - esme->esme->wqueue.write_cb = esme_link_write_cb; - llist_add_tail(&esme->list, &smsc->esme_list); return 0; } -/* callback of listening TCP socket */ -static int smsc_fd_cb(struct osmo_fd *ofd, unsigned int what) -{ - int rc; - struct sockaddr_storage sa; - socklen_t sa_len = sizeof(sa); - - rc = accept(ofd->fd, (struct sockaddr *)&sa, &sa_len); - if (rc < 0) { - LOGP(DSMPP, LOGL_ERROR, "Accept returns %d (%s)\n", - rc, strerror(errno)); - return rc; - } - return link_accept_cb(ofd->data, rc, &sa, sa_len); -} - /*! \brief allocate and initialize an smsc struct from talloc context ctx. */ struct smsc *smpp_smsc_alloc_init(void *ctx) { @@ -822,8 +798,14 @@ struct smsc *smpp_smsc_alloc_init(void *ctx) INIT_LLIST_HEAD(&smsc->acl_list); INIT_LLIST_HEAD(&smsc->route_list); - smsc->listen_ofd.data = smsc; - smsc->listen_ofd.cb = smsc_fd_cb; + smsc->link = osmo_stream_srv_link_create(smsc); + if (!smsc->link) + return NULL; + + osmo_stream_srv_link_set_data(smsc->link, smsc); + osmo_stream_srv_link_set_accept_cb(smsc->link, link_accept_cb); + osmo_stream_srv_link_set_proto(smsc->link, IPPROTO_TCP); + osmo_stream_srv_link_set_nodelay(smsc->link, true); return smsc; } @@ -849,18 +831,16 @@ int smpp_smsc_start(struct smsc *smsc, const char *bind_addr, uint16_t port) { int rc; - /* default port for SMPP */ - if (!port) - port = 2775; + osmo_stream_srv_link_set_addr(smsc->link, bind_addr ? bind_addr : "0.0.0.0"); + osmo_stream_srv_link_set_port(smsc->link, port ? port : SMPP_DEFAULT_PORT); - LOGP(DSMPP, LOGL_NOTICE, "SMPP at %s %d\n", - bind_addr? bind_addr : "0.0.0.0", port); - - rc = osmo_sock_init_ofd(&smsc->listen_ofd, AF_UNSPEC, SOCK_STREAM, - IPPROTO_TCP, bind_addr, port, - OSMO_SOCK_F_BIND); - if (rc < 0) + rc = osmo_stream_srv_link_open(smsc->link); + if (rc < 0) { + LOGP(DSMPP, LOGL_ERROR, "SMPP socket cannot be opened: %s\n", strerror(-rc)); return rc; + } + + LOGP(DSMPP, LOGL_NOTICE, "SMPP at %s\n", osmo_stream_srv_link_get_sockname(smsc->link)); /* store new address and port */ rc = smpp_smsc_conf(smsc, bind_addr, port); @@ -887,9 +867,5 @@ int smpp_smsc_restart(struct smsc *smsc, const char *bind_addr, uint16_t port) /*! /brief Close SMPP connection. */ void smpp_smsc_stop(struct smsc *smsc) { - if (smsc->listen_ofd.fd > 0) { - close(smsc->listen_ofd.fd); - smsc->listen_ofd.fd = 0; - osmo_fd_unregister(&smsc->listen_ofd); - } + osmo_stream_srv_link_close(smsc->link); } diff --git a/src/libmsc/smpp_smsc.h b/src/libmsc/smpp_smsc.h index 9752eba2b..54a0a92ee 100644 --- a/src/libmsc/smpp_smsc.h +++ b/src/libmsc/smpp_smsc.h @@ -85,7 +85,7 @@ void smpp_cmd_err(struct osmo_smpp_cmd *cmd, uint32_t status); void smpp_cmd_flush_pending(struct osmo_esme *esme); struct smsc { - struct osmo_fd listen_ofd; + struct osmo_stream_srv_link *link; struct llist_head esme_list; struct llist_head acl_list; struct llist_head route_list; diff --git a/src/libmsc/smpp_utils.c b/src/libmsc/smpp_utils.c index adf1206c6..37e1417e2 100644 --- a/src/libmsc/smpp_utils.c +++ b/src/libmsc/smpp_utils.c @@ -28,6 +28,8 @@ #include #include #include +#include + #include #include @@ -62,13 +64,6 @@ void esme_read_state_reset(struct esme *esme) esme->read_state = READ_ST_IN_LEN; } -void esme_queue_reset(struct esme *esme) -{ - osmo_fd_unregister(&esme->wqueue.bfd); - close(esme->wqueue.bfd.fd); - esme->wqueue.bfd.fd = -1; -} - /* !\brief call-back when per-ESME TCP socket has some data to be read */ int esme_read_callback(struct esme *esme, int fd) { @@ -123,7 +118,6 @@ int esme_read_callback(struct esme *esme, int fd) return 0; dead_socket: - esme_queue_reset(esme); esme_read_state_reset(esme); return -EBADF; } @@ -132,7 +126,6 @@ int esme_write_callback(struct esme *esme, int fd, struct msgb *msg) { int rc = write(fd, msgb_data(msg), msgb_length(msg)); if (rc == 0) { - esme_queue_reset(esme); return 0; } else if (rc < msgb_length(msg)) { LOGPESME(esme, LOGL_ERROR, "Short write\n"); @@ -150,7 +143,7 @@ int pack_and_send(struct esme *esme, uint32_t type, void *ptr) /* the socket was closed. Avoid allocating + enqueueing msgb, see * https://osmocom.org/issues/3278 */ - if (esme->wqueue.bfd.fd == -1) + if (!esme->srv) return -EIO; msg = msgb_alloc(4096, "SMPP_Tx"); @@ -165,11 +158,8 @@ int pack_and_send(struct esme *esme, uint32_t type, void *ptr) } msgb_put(msg, rlen); - if (osmo_wqueue_enqueue(&esme->wqueue, msg) != 0) { - LOGPESME(esme, LOGL_ERROR, "Write queue full. Dropping message\n"); - msgb_free(msg); - return -EAGAIN; - } + osmo_stream_srv_send(esme->srv, msg); + return 0; } diff --git a/src/libmsc/smpp_vty.c b/src/libmsc/smpp_vty.c index e8842d2e9..a8abfb5e9 100644 --- a/src/libmsc/smpp_vty.c +++ b/src/libmsc/smpp_vty.c @@ -27,7 +27,7 @@ #include #include #include - +#include #include #include #include @@ -81,7 +81,7 @@ static int smpp_local_tcp(struct vty *vty, const char *bind_addr, uint16_t port) { struct smsc *smsc = smsc_from_vty(vty); - int is_running = smsc->listen_ofd.fd > 0; + bool is_running = smsc->link; int same_bind_addr; int rc; @@ -188,7 +188,7 @@ static int config_write_smpp(struct vty *vty) vty_out(vty, " local-tcp-ip %s %u%s", smsc->bind_addr, smsc->listen_port, VTY_NEWLINE); else - vty_out(vty, " local-tcp-port %u%s", smsc->listen_port, + vty_out(vty, " local-tcp-port %u%s", smsc->listen_port ? smsc->listen_port : SMPP_DEFAULT_PORT, VTY_NEWLINE); if (strlen(smsc->system_id) > 0) vty_out(vty, " system-id %s%s", smsc->system_id, VTY_NEWLINE); @@ -528,7 +528,7 @@ static void dump_one_esme(struct vty *vty, struct osmo_esme *esme) vty_out(vty, "ESME System ID: %s, Password: %s, SMPP Version %02x%s", esme->esme->system_id, esme->acl ? esme->acl->passwd : "", esme->smpp_version, VTY_NEWLINE); - vty_out(vty, " Connection %s%s", osmo_sock_get_name(tall_vty_ctx, esme->esme->wqueue.bfd.fd), VTY_NEWLINE); + vty_out(vty, " Connection %s%s", osmo_stream_srv_link_get_sockname(esme->smsc->link), VTY_NEWLINE); if (esme->smsc->def_route == esme->acl) vty_out(vty, " Is current default route%s", VTY_NEWLINE); } diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am index 3019f1e8b..7f75c251f 100644 --- a/src/utils/Makefile.am +++ b/src/utils/Makefile.am @@ -48,5 +48,6 @@ smpp_mirror_LDADD = \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(LIBSMPP34_LIBS) \ + $(LIBOSMONETIF_LIBS) \ $(NULL) endif diff --git a/src/utils/smpp_mirror.c b/src/utils/smpp_mirror.c index 9dc6dd689..81465f22d 100644 --- a/src/utils/smpp_mirror.c +++ b/src/utils/smpp_mirror.c @@ -176,7 +176,7 @@ static int smpp_esme_init(struct esme *esme, const char *host, uint16_t port) int rc; if (port == 0) - port = 2775; + port = SMPP_DEFAULT_PORT; esme->own_seq_nr = rand(); esme_inc_seq_nr(esme); diff --git a/tests/smpp/Makefile.am b/tests/smpp/Makefile.am index 402f6ad79..81c412e6c 100644 --- a/tests/smpp/Makefile.am +++ b/tests/smpp/Makefile.am @@ -39,4 +39,5 @@ smpp_test_LDADD = \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(LIBSMPP34_LIBS) \ + $(LIBOSMONETIF_LIBS) \ $(NULL)