pespin has uploaded this change for review. (
https://gerrit.osmocom.org/c/libosmo-netif/+/34080 )
Change subject: WIP: stream_cli: Forward SCTP MSG_NOTIFICATION to upper layers
......................................................................
WIP: stream_cli: Forward SCTP MSG_NOTIFICATION to upper layers
Same mechanism as already used in strea_srv.
Change-Id: I4cb94d264109f1b763cccd44c6ba049cc7509319
---
M src/stream_cli.c
1 file changed, 114 insertions(+), 2 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-netif refs/changes/80/34080/1
diff --git a/src/stream_cli.c b/src/stream_cli.c
index e90b5e4..cc63297 100644
--- a/src/stream_cli.c
+++ b/src/stream_cli.c
@@ -913,18 +913,119 @@
}
}
+#ifdef HAVE_LIBSCTP
+static int _sctp_recvmsg_wrapper(int fd, struct msgb *msg)
+{
+ struct sctp_sndrcvinfo sinfo;
+ int flags = 0;
+ int ret;
+ uint8_t *data = msg->tail;
+
+ ret = sctp_recvmsg(fd, data, msgb_tailroom(msg),
+ NULL, NULL, &sinfo, &flags);
+ msgb_sctp_msg_flags(msg) = 0;
+ msgb_sctp_ppid(msg) = ntohl(sinfo.sinfo_ppid);
+ msgb_sctp_stream(msg) = sinfo.sinfo_stream;
+ if (flags & MSG_NOTIFICATION) {
+ union sctp_notification *notif = (union sctp_notification *)data;
+ LOGP(DLINP, LOGL_INFO, "NOTIFICATION %u flags=0x%x\n",
notif->sn_header.sn_type, notif->sn_header.sn_flags);
+ msgb_put(msg, sizeof(union sctp_notification));
+ msgb_sctp_msg_flags(msg) = OSMO_STREAM_SCTP_MSG_FLAGS_NOTIFICATION;
+ switch (notif->sn_header.sn_type) {
+ case SCTP_ASSOC_CHANGE:
+ LOGP(DLINP, LOGL_INFO, "===> ASSOC CHANGE:");
+ switch (notif->sn_assoc_change.sac_state) {
+ case SCTP_COMM_UP:
+ LOGPC(DLINP, LOGL_INFO, " UP\n");
+ break;
+ case SCTP_COMM_LOST:
+ LOGPC(DLINP, LOGL_INFO, " LOST\n");
+ /* Handle this like a regular disconnect */
+ return 0;
+ case SCTP_RESTART:
+ LOGPC(DLINP, LOGL_INFO, " RESTART\n");
+ break;
+ case SCTP_SHUTDOWN_COMP:
+ LOGPC(DLINP, LOGL_INFO, " SHUTDOWN COMP\n");
+ break;
+ case SCTP_CANT_STR_ASSOC:
+ LOGPC(DLINP, LOGL_INFO, " CANT STR ASSOC\n");
+ break;
+ }
+ break;
+ case SCTP_SEND_FAILED:
+ LOGP(DLINP, LOGL_INFO, "===> SEND FAILED\n");
+ break;
+ case SCTP_PEER_ADDR_CHANGE:
+ {
+ char addr_str[INET6_ADDRSTRLEN + 10];
+ struct sockaddr_storage sa = notif->sn_paddr_change.spc_aaddr;
+ osmo_sockaddr_to_str_buf(addr_str, sizeof(addr_str),
+ (const struct osmo_sockaddr *)&sa);
+ LOGP(DLINP, LOGL_INFO, "===> PEER ADDR CHANGE: %s %s err=%s\n",
+ addr_str, osmo_sctp_paddr_chg_str(notif->sn_paddr_change.spc_state),
+ (notif->sn_paddr_change.spc_state == SCTP_ADDR_UNREACHABLE) ?
+ osmo_sctp_sn_error_str(notif->sn_paddr_change.spc_error) : "None");
+ }
+ break;
+ case SCTP_SHUTDOWN_EVENT:
+ LOGP(DLINP, LOGL_INFO, "===> SHUTDOWN EVT\n");
+ /* Handle this like a regular disconnect */
+ return 0;
+ }
+ return -EAGAIN;
+ }
+ return ret;
+}
+#endif
+
/*! \brief Receive data via an Osmocom stream client
* \param[in] cli Stream Client through which we want to send
* \param msg pre-allocate message buffer to which received data is appended
- * \returns number of bytes read; <=0 in case of error */
+ * \returns number of bytes read; <=0 in case of erro
+ *
+ * If conn is an SCTP connection, additional specific considerations shall be taken:
+ * - msg->cb is always filled with SCTP ppid, and SCTP stream values, see
msgb_sctp_*() APIs.
+ * - If an SCTP notification was received when reading from the SCTP socket,
+ * msgb_sctp_msg_flags(msg) will contain bit flag
+ * OSMO_STREAM_SCTP_MSG_FLAGS_NOTIFICATION set, and the msgb will
+ * contain a "union sctp_notification" instead of user data. In this case
the
+ * return code will be either 0 (if conn is considered dead after the
+ * notification) or -EAGAIN (if conn is considered still alive after the
+ * notification) resembling the standard recv() API.
+ */
int osmo_stream_cli_recv(struct osmo_stream_cli *cli, struct msgb *msg)
{
int ret;
OSMO_ASSERT(cli);
OSMO_ASSERT(msg);
- ret = recv(cli->ofd.fd, msg->tail, msgb_tailroom(msg), 0);
+ switch (cli->sk_domain) {
+ case AF_UNIX:
+ ret = recv(cli->ofd.fd, msg->tail, msgb_tailroom(msg), 0);
+ break;
+ case AF_INET:
+ case AF_INET6:
+ case AF_UNSPEC:
+ switch (cli->proto) {
+#ifdef HAVE_LIBSCTP
+ case IPPROTO_SCTP:
+ ret = _sctp_recvmsg_wrapper(cli->ofd.fd, msg);
+ break;
+#endif
+ case IPPROTO_TCP:
+ default:
+ ret = recv(cli->ofd.fd, msg->tail, msgb_tailroom(msg), 0);
+ break;
+ }
+ break;
+ default:
+ ret = -ENOTSUP;
+ }
+
if (ret < 0) {
+ if (ret == -EAGAIN)
+ return ret;
if (errno == EPIPE || errno == ECONNRESET)
LOGSCLI(cli, LOGL_ERROR, "lost connection with srv\n");
osmo_stream_cli_reconnect(cli);
--
To view, visit
https://gerrit.osmocom.org/c/libosmo-netif/+/34080
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-netif
Gerrit-Branch: master
Gerrit-Change-Id: I4cb94d264109f1b763cccd44c6ba049cc7509319
Gerrit-Change-Number: 34080
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-MessageType: newchange