aboutsummaryrefslogtreecommitdiffstats
path: root/src/stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/stream.c')
-rw-r--r--src/stream.c156
1 files changed, 136 insertions, 20 deletions
diff --git a/src/stream.c b/src/stream.c
index 3d0b665..744a904 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -84,7 +84,6 @@ static int sctp_sock_activate_events(int fd)
event.sctp_data_io_event = 1;
event.sctp_association_event = 1;
event.sctp_address_event = 1;
- event.sctp_address_event = 1;
event.sctp_send_failure_event = 1;
event.sctp_peer_error_event = 1;
event.sctp_shutdown_event = 1;
@@ -149,9 +148,11 @@ struct osmo_stream_cli {
struct llist_head tx_queue;
struct osmo_timer_list timer;
enum osmo_stream_cli_state state;
- char *addr;
+ char *addr[OSMO_SOCK_MAX_ADDRS];
+ uint8_t addrcnt;
uint16_t port;
- char *local_addr;
+ char *local_addr[OSMO_SOCK_MAX_ADDRS];
+ uint8_t local_addrcnt;
uint16_t local_port;
uint16_t proto;
int (*connect_cb)(struct osmo_stream_cli *srv);
@@ -184,6 +185,14 @@ void osmo_stream_cli_reconnect(struct osmo_stream_cli *cli)
cli->state = STREAM_CLI_STATE_CONNECTING;
}
+/*! \brief Check if Osmocom Stream Client is in connected state
+ * \param[in] cli Osmocom Stream Client
+ */
+bool osmo_stream_cli_is_connected(struct osmo_stream_cli *cli)
+{
+ return cli->state == STREAM_CLI_STATE_CONNECTED;
+}
+
/*! \brief Close an Osmocom Stream Client
* \param[in] cli Osmocom Stream Client to be closed
* We unregister the socket fd from the osmocom select() loop
@@ -275,7 +284,12 @@ static int osmo_stream_cli_fd_cb(struct osmo_fd *ofd, unsigned int what)
osmo_stream_cli_reconnect(cli);
return 0;
}
- ofd->when &= ~BSC_FD_WRITE;
+
+ /* If messages got enqueued while 'connecting', keep WRITE flag
+ up to dispatch them upon next main loop step */
+ if (llist_empty(&cli->tx_queue))
+ cli->ofd.when &= ~BSC_FD_WRITE;
+
LOGSCLI(cli, LOGL_DEBUG, "connection done.\n");
cli->state = STREAM_CLI_STATE_CONNECTED;
if (cli->proto == IPPROTO_SCTP) {
@@ -342,8 +356,32 @@ struct osmo_stream_cli *osmo_stream_cli_create(void *ctx)
void
osmo_stream_cli_set_addr(struct osmo_stream_cli *cli, const char *addr)
{
- osmo_talloc_replace_string(cli, &cli->addr, addr);
+ osmo_stream_cli_set_addrs(cli, &addr, 1);
+}
+
+/*! \brief Set the remote address set to which we connect.
+ * Useful for protocols allowing connecting to more than one address (such as SCTP)
+ * \param[in] cli Stream Client to modify
+ * \param[in] addr Remote IP address set
+ * \return negative on error, 0 on success
+ */
+int osmo_stream_cli_set_addrs(struct osmo_stream_cli *cli, const char **addr, size_t addrcnt)
+{
+ int i = 0;
+
+ if (addrcnt > OSMO_SOCK_MAX_ADDRS)
+ return -EINVAL;
+
+ for (; i < addrcnt; i++)
+ osmo_talloc_replace_string(cli, &cli->addr[i], addr[i]);
+ for (; i < cli->addrcnt; i++) {
+ talloc_free(cli->addr[i]);
+ cli->addr[i] = NULL;
+ }
+
+ cli->addrcnt = addrcnt;
cli->flags |= OSMO_STREAM_CLI_F_RECONF;
+ return 0;
}
/*! \brief Set the remote port number to which we connect
@@ -375,8 +413,32 @@ osmo_stream_cli_set_local_port(struct osmo_stream_cli *cli, uint16_t port)
void
osmo_stream_cli_set_local_addr(struct osmo_stream_cli *cli, const char *addr)
{
- osmo_talloc_replace_string(cli, &cli->local_addr, addr);
+ osmo_stream_cli_set_local_addrs(cli, &addr, 1);
+}
+
+/*! \brief Set the local address set to which we connect.
+ * Useful for protocols allowing bind to more than one address (such as SCTP)
+ * \param[in] cli Stream Client to modify
+ * \param[in] addr Local IP address set
+ * \return negative on error, 0 on success
+ */
+int osmo_stream_cli_set_local_addrs(struct osmo_stream_cli *cli, const char **addr, size_t addrcnt)
+{
+ int i = 0;
+
+ if (addrcnt > OSMO_SOCK_MAX_ADDRS)
+ return -EINVAL;
+
+ for (; i < addrcnt; i++)
+ osmo_talloc_replace_string(cli, &cli->local_addr[i], addr[i]);
+ for (; i < cli->local_addrcnt; i++) {
+ talloc_free(cli->local_addr[i]);
+ cli->local_addr[i] = NULL;
+ }
+
+ cli->local_addrcnt = addrcnt;
cli->flags |= OSMO_STREAM_CLI_F_RECONF;
+ return 0;
}
/*! \brief Set the protocol for the stream client socket
@@ -491,10 +553,20 @@ int osmo_stream_cli_open2(struct osmo_stream_cli *cli, int reconnect)
cli->flags &= ~OSMO_STREAM_CLI_F_RECONF;
- ret = osmo_sock_init2(AF_INET, SOCK_STREAM, cli->proto,
- cli->local_addr, cli->local_port,
- cli->addr, cli->port,
- OSMO_SOCK_F_CONNECT|OSMO_SOCK_F_BIND|OSMO_SOCK_F_NONBLOCK);
+ switch (cli->proto) {
+ case IPPROTO_SCTP:
+ ret = osmo_sock_init2_multiaddr(AF_INET, SOCK_STREAM, cli->proto,
+ (const char **)cli->local_addr, cli->local_addrcnt, cli->local_port,
+ (const char **)cli->addr, cli->addrcnt, cli->port,
+ OSMO_SOCK_F_CONNECT|OSMO_SOCK_F_BIND|OSMO_SOCK_F_NONBLOCK);
+ break;
+ default:
+ ret = osmo_sock_init2(AF_INET, SOCK_STREAM, cli->proto,
+ cli->local_addr[0], cli->local_port,
+ cli->addr[0], cli->port,
+ OSMO_SOCK_F_CONNECT|OSMO_SOCK_F_BIND|OSMO_SOCK_F_NONBLOCK);
+ }
+
if (ret < 0) {
if (reconnect)
osmo_stream_cli_reconnect(cli);
@@ -514,7 +586,7 @@ int osmo_stream_cli_open2(struct osmo_stream_cli *cli, int reconnect)
return 0;
error_close_socket:
- close(ret);
+ close(cli->ofd.fd);
cli->ofd.fd = -1;
return -EIO;
}
@@ -549,10 +621,21 @@ int osmo_stream_cli_open(struct osmo_stream_cli *cli)
cli->flags &= ~OSMO_STREAM_CLI_F_RECONF;
- ret = osmo_sock_init2(AF_INET, SOCK_STREAM, cli->proto,
- cli->local_addr, cli->local_port,
- cli->addr, cli->port,
- OSMO_SOCK_F_CONNECT|OSMO_SOCK_F_BIND|OSMO_SOCK_F_NONBLOCK);
+
+ switch (cli->proto) {
+ case IPPROTO_SCTP:
+ ret = osmo_sock_init2_multiaddr(AF_INET, SOCK_STREAM, cli->proto,
+ (const char **)cli->local_addr, cli->local_addrcnt, cli->local_port,
+ (const char **)cli->addr, cli->addrcnt, cli->port,
+ OSMO_SOCK_F_CONNECT|OSMO_SOCK_F_BIND|OSMO_SOCK_F_NONBLOCK);
+ break;
+ default:
+ ret = osmo_sock_init2(AF_INET, SOCK_STREAM, cli->proto,
+ cli->local_addr[0], cli->local_port,
+ cli->addr[0], cli->port,
+ OSMO_SOCK_F_CONNECT|OSMO_SOCK_F_BIND|OSMO_SOCK_F_NONBLOCK);
+ }
+
if (ret < 0) {
osmo_stream_cli_reconnect(cli);
return ret;
@@ -571,7 +654,7 @@ int osmo_stream_cli_open(struct osmo_stream_cli *cli)
return 0;
error_close_socket:
- close(ret);
+ close(cli->ofd.fd);
cli->ofd.fd = -1;
return -EIO;
}
@@ -635,7 +718,8 @@ int osmo_stream_cli_recv(struct osmo_stream_cli *cli, struct msgb *msg)
struct osmo_stream_srv_link {
struct osmo_fd ofd;
- char *addr;
+ char *addr[OSMO_SOCK_MAX_ADDRS];
+ uint8_t addrcnt;
uint16_t port;
uint16_t proto;
int (*accept_cb)(struct osmo_stream_srv_link *srv, int fd);
@@ -733,8 +817,32 @@ void osmo_stream_srv_link_set_nodelay(struct osmo_stream_srv_link *link, bool no
void osmo_stream_srv_link_set_addr(struct osmo_stream_srv_link *link,
const char *addr)
{
- osmo_talloc_replace_string(link, &link->addr, addr);
+ osmo_stream_srv_link_set_addrs(link, &addr, 1);
+}
+
+/*! \brief Set the local address set to which we bind.
+ * Useful for protocols allowing bind on more than one address (such as SCTP)
+ * \param[in] link Stream Server Link to modify
+ * \param[in] addr Local IP address
+ * \return negative on error, 0 on success
+ */
+int osmo_stream_srv_link_set_addrs(struct osmo_stream_srv_link *link, const char **addr, size_t addrcnt)
+{
+ int i = 0;
+
+ if (addrcnt > OSMO_SOCK_MAX_ADDRS)
+ return -EINVAL;
+
+ for (; i < addrcnt; i++)
+ osmo_talloc_replace_string(link, &link->addr[i], addr[i]);
+ for (; i < link->addrcnt; i++) {
+ talloc_free(link->addr[i]);
+ link->addr[i] = NULL;
+ }
+
+ link->addrcnt = addrcnt;
link->flags |= OSMO_STREAM_SRV_F_RECONF;
+ return 0;
}
/*! \brief Set the local port number to which we bind
@@ -841,8 +949,16 @@ int osmo_stream_srv_link_open(struct osmo_stream_srv_link *link)
link->flags &= ~OSMO_STREAM_SRV_F_RECONF;
- ret = osmo_sock_init(AF_INET, SOCK_STREAM, link->proto,
- link->addr, link->port, OSMO_SOCK_F_BIND);
+ switch (link->proto) {
+ case IPPROTO_SCTP:
+ ret = osmo_sock_init2_multiaddr(AF_INET, SOCK_STREAM, link->proto,
+ (const char **)link->addr, link->addrcnt, link->port,
+ NULL, 0, 0, OSMO_SOCK_F_BIND);
+ break;
+ default:
+ ret = osmo_sock_init(AF_INET, SOCK_STREAM, link->proto,
+ link->addr[0], link->port, OSMO_SOCK_F_BIND);
+ }
if (ret < 0)
return ret;