pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmo-netif/+/39316?usp=email )
Change subject: stream: Introduce osmo_stream_{cli,srv}_set_segmentation_cb2 ......................................................................
stream: Introduce osmo_stream_{cli,srv}_set_segmentation_cb2
Change-Id: I6e8dd6ece13397074075f05a1a0a8dbdd80d8848 --- M TODO-RELEASE M include/osmocom/netif/stream.h M src/stream_cli.c M src/stream_srv.c 4 files changed, 105 insertions(+), 23 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-netif refs/changes/16/39316/1
diff --git a/TODO-RELEASE b/TODO-RELEASE index 5092ee7..e66b421 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -9,4 +9,5 @@ #library what description / commit summary line libosmo-netif add API osmo_stream_cli_set_{ip_dscp,priority}(), osmo_stream_srv_link_set_{ip_dscp,priority}() libosmo-netif add API osmo-stream_cli_set_tx_queue_max_length(), osmo_stream_srv_link_set_tx_queue_max_length() -libosmo-netif add API struct osmo_ipa_ka_fsm_inst \ No newline at end of file +libosmo-netif add API struct osmo_ipa_ka_fsm_inst +libosmo-netif add API osmo_stream_{cli,srv}_set_segmentation_cb2() diff --git a/include/osmocom/netif/stream.h b/include/osmocom/netif/stream.h index a132a27..2866ea3 100644 --- a/include/osmocom/netif/stream.h +++ b/include/osmocom/netif/stream.h @@ -114,6 +114,7 @@ typedef int (*osmo_stream_srv_read_cb2_t)(struct osmo_stream_srv *conn, int res, struct msgb *msg);
typedef int (*osmo_stream_srv_segmentation_cb_t)(struct msgb *msg); +typedef int (*osmo_stream_srv_segmentation_cb2_t)(struct osmo_stream_srv *conn, struct msgb *msg);
struct osmo_stream_srv *osmo_stream_srv_create(void *ctx, struct osmo_stream_srv_link *link, int fd, osmo_stream_srv_read_cb_t read_cb, @@ -135,7 +136,8 @@ void osmo_stream_srv_set_flush_and_destroy(struct osmo_stream_srv *conn); void osmo_stream_srv_set_data(struct osmo_stream_srv *conn, void *data);
-void osmo_stream_srv_set_segmentation_cb(struct osmo_stream_srv *conn, osmo_stream_srv_segmentation_cb_t segmentation_cb); +void osmo_stream_srv_set_segmentation_cb(struct osmo_stream_srv *conn, osmo_stream_srv_segmentation_cb_t segmentation_cb) OSMO_DEPRECATED("Use osmo_stream_srv_set_segmentation_cb2() instead"); +void osmo_stream_srv_set_segmentation_cb2(struct osmo_stream_srv *conn, osmo_stream_srv_segmentation_cb2_t segmentation_cb2);
void osmo_stream_srv_send(struct osmo_stream_srv *conn, struct msgb *msg); int osmo_stream_srv_recv(struct osmo_stream_srv *conn, struct msgb *msg); @@ -191,6 +193,7 @@ typedef int (*osmo_stream_cli_read_cb2_t)(struct osmo_stream_cli *cli, int res, struct msgb *msg);
typedef int (*osmo_stream_cli_segmentation_cb_t)(struct msgb *msg); +typedef int (*osmo_stream_cli_segmentation_cb2_t)(struct osmo_stream_cli *cli, struct msgb *msg);
void osmo_stream_cli_set_name(struct osmo_stream_cli *cli, const char *name); const char *osmo_stream_cli_get_name(const struct osmo_stream_cli *cli); @@ -218,7 +221,8 @@ void osmo_stream_cli_set_disconnect_cb(struct osmo_stream_cli *cli, osmo_stream_cli_disconnect_cb_t disconnect_cb); void osmo_stream_cli_set_read_cb(struct osmo_stream_cli *cli, osmo_stream_cli_read_cb_t read_cb); void osmo_stream_cli_set_read_cb2(struct osmo_stream_cli *cli, osmo_stream_cli_read_cb2_t read_cb); -void osmo_stream_cli_set_segmentation_cb(struct osmo_stream_cli *cli, osmo_stream_cli_segmentation_cb_t segmentation_cb); +void osmo_stream_cli_set_segmentation_cb(struct osmo_stream_cli *cli, osmo_stream_cli_segmentation_cb_t segmentation_cb) OSMO_DEPRECATED("Use osmo_stream_cli_set_segmentation_cb2() instead"); +void osmo_stream_cli_set_segmentation_cb2(struct osmo_stream_cli *cli, osmo_stream_cli_segmentation_cb2_t segmentation_cb2); void osmo_stream_cli_reconnect(struct osmo_stream_cli *cli); bool osmo_stream_cli_is_connected(struct osmo_stream_cli *cli);
diff --git a/src/stream_cli.c b/src/stream_cli.c index 48a8858..586b1b0 100644 --- a/src/stream_cli.c +++ b/src/stream_cli.c @@ -117,6 +117,7 @@ osmo_stream_cli_read_cb_t read_cb; osmo_stream_cli_read_cb2_t iofd_read_cb; osmo_stream_cli_segmentation_cb_t segmentation_cb; + osmo_stream_cli_segmentation_cb2_t segmentation_cb2; void *data; int flags; int reconnect_timeout; @@ -511,7 +512,6 @@ cli->state = STREAM_CLI_STATE_CLOSED; osmo_timer_setup(&cli->timer, cli_timer_cb, cli); cli->reconnect_timeout = 5; /* default is 5 seconds. */ - cli->segmentation_cb = NULL; INIT_LLIST_HEAD(&cli->tx_queue); cli->tx_queue_max_length = 1024; /* Default tx queue size, msgbs. */
@@ -598,8 +598,6 @@ static const struct osmo_io_ops osmo_stream_cli_ioops = { .read_cb = stream_cli_iofd_read_cb, .write_cb = stream_cli_iofd_write_cb, - - .segmentation_cb = NULL, };
#ifdef HAVE_LIBSCTP @@ -659,8 +657,6 @@ static const struct osmo_io_ops osmo_stream_cli_ioops_sctp = { .recvmsg_cb = stream_cli_iofd_recvmsg_cb, .sendmsg_cb = stream_cli_iofd_write_cb, - - .segmentation_cb = NULL, }; #endif
@@ -795,28 +791,58 @@ cli->flags |= OSMO_STREAM_CLI_F_RECONF; }
+/* Callback from iofd, forward to stream_cli user: */ +static int stream_cli_iofd_segmentation_cb2(struct osmo_io_fd *iofd, struct msgb *msg) +{ + struct osmo_stream_cli *cli = osmo_iofd_get_data(iofd); + if (cli->segmentation_cb2) + return cli->segmentation_cb2(cli, msg); + if (cli->segmentation_cb) + return cli->segmentation_cb(msg); + OSMO_ASSERT(0); + return 0; +} + /* Configure client side segmentation for the iofd */ -static void configure_cli_segmentation_cb(struct osmo_stream_cli *cli, - osmo_stream_cli_segmentation_cb_t segmentation_cb) +static void configure_cli_segmentation_cb(struct osmo_stream_cli *cli) { /* Copy default settings */ struct osmo_io_ops client_ops; osmo_iofd_get_ioops(cli->iofd, &client_ops); /* Set segmentation cb for this client */ - client_ops.segmentation_cb = segmentation_cb; + if (cli->segmentation_cb || cli->segmentation_cb2) + client_ops.segmentation_cb2 = stream_cli_iofd_segmentation_cb2; + else + client_ops.segmentation_cb2 = NULL; osmo_iofd_set_ioops(cli->iofd, &client_ops); }
/*! Set the segmentation callback for the client. * \param[in,out] cli Stream Client to modify * \param[in] segmentation_cb Target segmentation callback + * + * DEPRECATED: Use osmo_cli_set_segmentation_cb2() instead. */ void osmo_stream_cli_set_segmentation_cb(struct osmo_stream_cli *cli, osmo_stream_cli_segmentation_cb_t segmentation_cb) { cli->segmentation_cb = segmentation_cb; + cli->segmentation_cb2 = NULL; if (cli->iofd) /* Otherwise, this will be done in osmo_stream_cli_open() */ - configure_cli_segmentation_cb(cli, segmentation_cb); + configure_cli_segmentation_cb(cli); +} + +/*! Set the segmentation callback for the client. + * \param[in,out] cli Stream Client to modify + * \param[in] segmentation_cb2 Target segmentation callback + */ +void osmo_stream_cli_set_segmentation_cb2(struct osmo_stream_cli *cli, + osmo_stream_cli_segmentation_cb2_t segmentation_cb2) +{ + cli->segmentation_cb = NULL; + cli->segmentation_cb2 = segmentation_cb2; + if (cli->iofd) /* Otherwise, this will be done in osmo_stream_cli_open() */ + configure_cli_segmentation_cb(cli); }
/*! Set the socket type for the stream server link. @@ -1257,7 +1283,7 @@
osmo_iofd_set_txqueue_max_length(cli->iofd, cli->tx_queue_max_length); osmo_iofd_notify_connected(cli->iofd); - configure_cli_segmentation_cb(cli, cli->segmentation_cb); + configure_cli_segmentation_cb(cli);
if (osmo_iofd_register(cli->iofd, fd) < 0) goto error_close_socket; diff --git a/src/stream_srv.c b/src/stream_srv.c index c74f7b0..c2b187a 100644 --- a/src/stream_srv.c +++ b/src/stream_srv.c @@ -664,6 +664,8 @@ osmo_stream_srv_closed_cb_t closed_cb; osmo_stream_srv_read_cb_t read_cb; osmo_stream_srv_read_cb2_t iofd_read_cb; + osmo_stream_srv_segmentation_cb_t segmentation_cb; + osmo_stream_srv_segmentation_cb2_t segmentation_cb2; void *data; int flags; }; @@ -1040,7 +1042,37 @@ conn->data = data; }
+/* Callback from iofd, forward to stream_srv user: */ +static int stream_srv_iofd_segmentation_cb2(struct osmo_io_fd *iofd, struct msgb *msg) +{ + struct osmo_stream_srv *conn = osmo_iofd_get_data(iofd); + if (conn->segmentation_cb2) + return conn->segmentation_cb2(conn, msg); + if (conn->segmentation_cb) + return conn->segmentation_cb(msg); + OSMO_ASSERT(0); + return 0; +} + +/* Configure server side segmentation for the iofd */ +static void configure_srv_segmentation_cb(struct osmo_stream_srv *conn) +{ + /* Copy default settings */ + struct osmo_io_ops client_ops; + osmo_iofd_get_ioops(conn->iofd, &client_ops); + /* Set segmentation cb for this client */ + if (conn->segmentation_cb || conn->segmentation_cb2) + client_ops.segmentation_cb2 = stream_srv_iofd_segmentation_cb2; + else + client_ops.segmentation_cb2 = NULL; + osmo_iofd_set_ioops(conn->iofd, &client_ops); +} + /*! Set the segmentation callback for target osmo_stream_srv structure. + * \param[in,out] conn Target Stream Server to modify + * \param[in] segmentation_cb Segmentation callback to be set + * + * DEPRECATED: Use osmo_stream_srv_set_segmentation_cb2() instead. * * A segmentation call-back can optionally be used when a packet based protocol (like TCP) is used within a * STREAM style socket that does not preserve message boundaries within the stream. If a segmentation @@ -1048,22 +1080,41 @@ * complete single messages, and not arbitrary segments of the stream. * * This function only works with osmo_stream_srv in osmo_io mode, created by osmo_stream_srv_create2()! - * The connection has to have been established prior to calling this function. - * - * \param[in,out] conn Target Stream Server to modify - * \param[in] segmentation_cb Segmentation callback to be set */ + * The connection has to have been established prior to calling this function. + * + */ void osmo_stream_srv_set_segmentation_cb(struct osmo_stream_srv *conn, osmo_stream_srv_segmentation_cb_t segmentation_cb) { /* Note that the following implies that iofd != NULL, since * osmo_stream_srv_create2() creates the iofd member, too */ OSMO_ASSERT(conn->mode == OSMO_STREAM_MODE_OSMO_IO); - /* Copy default settings */ - struct osmo_io_ops conn_ops; - osmo_iofd_get_ioops(conn->iofd, &conn_ops); - /* Set segmentation cb for this connection */ - conn_ops.segmentation_cb = segmentation_cb; - osmo_iofd_set_ioops(conn->iofd, &conn_ops); + conn->segmentation_cb = segmentation_cb; + conn->segmentation_cb2 = NULL; + configure_srv_segmentation_cb(conn); +} + +/*! Set the segmentation callback for target osmo_stream_srv structure. + * \param[in,out] conn Target Stream Server to modify + * \param[in] segmentation_cb2 Segmentation callback to be set + * + * A segmentation call-back can optionally be used when a packet based protocol (like TCP) is used within a + * STREAM style socket that does not preserve message boundaries within the stream. If a segmentation + * call-back is given, the osmo_stream_srv library code will makes sure that the read_cb called only for + * complete single messages, and not arbitrary segments of the stream. + * + * This function only works with osmo_stream_srv in osmo_io mode, created by osmo_stream_srv_create2()! + * The connection has to have been established prior to calling this function. + */ +void osmo_stream_srv_set_segmentation_cb2(struct osmo_stream_srv *conn, + osmo_stream_srv_segmentation_cb2_t segmentation_cb2) +{ + /* Note that the following implies that iofd != NULL, since + * osmo_stream_srv_create2() creates the iofd member, too */ + OSMO_ASSERT(conn->mode == OSMO_STREAM_MODE_OSMO_IO); + conn->segmentation_cb = NULL; + conn->segmentation_cb2 = segmentation_cb2; + configure_srv_segmentation_cb(conn); }
/*! Retrieve application private data of the stream server