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
This commit is contained in:
parent
43a6a9a208
commit
1c82ae53cb
|
@ -3,6 +3,8 @@
|
|||
#include <inttypes.h>
|
||||
#include <osmocom/msc/gsm_data.h>
|
||||
|
||||
#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
|
||||
|
@ -16,6 +18,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;
|
||||
|
@ -50,7 +54,6 @@ struct esme {
|
|||
|
||||
struct esme *esme_alloc(void *ctx);
|
||||
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);
|
||||
uint32_t smpp_msgb_cmdid(struct msgb *msg);
|
||||
|
|
|
@ -87,7 +87,7 @@ void smpp_cmd_err(struct osmo_smpp_cmd *cmd, uint32_t status);
|
|||
void smpp_cmd_flush_pending(struct smpp_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;
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <osmocom/core/logging.h>
|
||||
#include <osmocom/core/write_queue.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/netif/stream.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_11.h>
|
||||
|
||||
#include <osmocom/msc/debug.h>
|
||||
|
@ -159,8 +160,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);
|
||||
smpp_esme_put(acl->esme);
|
||||
acl->esme = NULL;
|
||||
}
|
||||
|
@ -236,14 +235,14 @@ void smpp_esme_get(struct smpp_esme *esme)
|
|||
|
||||
static void esme_destroy(struct smpp_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);
|
||||
}
|
||||
|
||||
|
@ -759,9 +758,10 @@ static int smpp_pdu_rx(struct smpp_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 smpp_esme *e = ofd->data;
|
||||
struct smpp_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);
|
||||
|
||||
|
@ -782,19 +782,17 @@ 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 smpp_esme *esme = ofd->data;
|
||||
int rc = esme_write_callback(esme->esme, ofd->fd, msg);
|
||||
struct smpp_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;
|
||||
}
|
||||
|
@ -807,15 +805,14 @@ struct esme *esme_alloc(void *ctx)
|
|||
|
||||
e->own_seq_nr = rand();
|
||||
esme_inc_seq_nr(e);
|
||||
osmo_wqueue_init(&e->wqueue, 10);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
/* 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 smpp_esme *esme = talloc_zero(smsc, struct smpp_esme);
|
||||
if (!esme) {
|
||||
close(fd);
|
||||
|
@ -831,38 +828,18 @@ static int link_accept_cb(struct smsc *smsc, int fd,
|
|||
INIT_LLIST_HEAD(&esme->smpp_cmd_list);
|
||||
smpp_esme_get(esme);
|
||||
esme->smsc = smsc;
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -872,8 +849,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;
|
||||
}
|
||||
|
@ -899,18 +882,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);
|
||||
|
@ -937,9 +918,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);
|
||||
}
|
||||
|
|
|
@ -48,13 +48,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;
|
||||
}
|
||||
|
||||
/* This macro should be called after a call to read() in the read_cb of an
|
||||
* osmo_fd to properly check for errors.
|
||||
* rc is the return value of read, err_label is the label to jump to in case of
|
||||
|
@ -126,7 +119,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;
|
||||
}
|
||||
|
@ -135,7 +127,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");
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include <osmocom/vty/command.h>
|
||||
#include <osmocom/vty/buffer.h>
|
||||
#include <osmocom/vty/vty.h>
|
||||
|
||||
#include <osmocom/netif/stream.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/core/socket.h>
|
||||
|
@ -80,7 +80,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;
|
||||
|
||||
|
@ -187,7 +187,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);
|
||||
|
@ -527,7 +527,7 @@ static void dump_one_esme(struct vty *vty, struct smpp_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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue