arehbein has uploaded this change for review.
stream: Add server-side (segmentation) support for IPAC
With this commit, IPAC segmentation is taken care of by setting the protocol being streamed
Depends on change I3a639e6896cc3b3fc8e9b2e1a58254710efa0d3f
Related: OS#5753, OS#5751
Change-Id: I6c91ff385cb5f36ab6b6c96d0e44997995d0d24c
---
M include/osmocom/netif/stream.h
M src/stream.c
M tests/stream/stream_test.c
M tests/stream/stream_test.ok
4 files changed, 334 insertions(+), 21 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-netif refs/changes/97/33197/1
diff --git a/include/osmocom/netif/stream.h b/include/osmocom/netif/stream.h
index 0e983a4..c9b7a88 100644
--- a/include/osmocom/netif/stream.h
+++ b/include/osmocom/netif/stream.h
@@ -21,6 +21,18 @@
/*! \brief Osmocom Stream Server Link: A server socket listening/accepting */
struct osmo_stream_srv_link;
+/*! \brief Type of protocol transported by the data stream */
+enum osmo_stream_proto {
+ OSMO_STREAM_UNSPECIFIED = 0,
+ OSMO_STREAM_IPAC,
+ /* TODO: Add protocols for which libosmo-netif should be able to handle segmentation */
+ _NUM_OSMO_STREAM_PROTOS
+};
+
+/*! \brief Shortcut for unsetting the stream protocol (gets rid of segmentation pertaining to stream protocol) */
+#define osmo_stream_srv_link_unset_stream_proto(struct_osmo_stream_srv_link_ptr)\
+ osmo_stream_srv_link_set_stream_proto(struct_osmo_stream_srv_link_ptr, OSMO_STREAM_UNSPECIFIED)
+
struct osmo_stream_srv_link *osmo_stream_srv_link_create(void *ctx);
void osmo_stream_srv_link_destroy(struct osmo_stream_srv_link *link);
@@ -29,6 +41,7 @@
int osmo_stream_srv_link_set_addrs(struct osmo_stream_srv_link *link, const char **addr, size_t addrcnt);
void osmo_stream_srv_link_set_port(struct osmo_stream_srv_link *link, uint16_t port);
void osmo_stream_srv_link_set_proto(struct osmo_stream_srv_link *link, uint16_t proto);
+void osmo_stream_srv_link_set_stream_proto(struct osmo_stream_srv_link *link, enum osmo_stream_proto osp);
int osmo_stream_srv_link_set_type(struct osmo_stream_srv_link *link, int type);
int osmo_stream_srv_link_set_domain(struct osmo_stream_srv_link *link, int domain);
void osmo_stream_srv_link_set_accept_cb(struct osmo_stream_srv_link *link, int (*accept_cb)(struct osmo_stream_srv_link *link, int fd));
diff --git a/src/stream.c b/src/stream.c
index d6b16d3..a033455 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -36,6 +36,7 @@
#include <osmocom/core/select.h>
#include <osmocom/core/utils.h>
#include <osmocom/gsm/tlv.h>
+#include <osmocom/gsm/ipa.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/osmo_io.h>
#include <osmocom/core/panic.h>
@@ -78,6 +79,11 @@
#define MSG_NOSIGNAL 0
#endif
+static int (*segmentation_cbs[_NUM_OSMO_STREAM_PROTOS])(struct msgb *) = {
+ [OSMO_STREAM_UNSPECIFIED] = NULL,
+ [OSMO_STREAM_IPAC] = ipa_segmentation_cb,
+};
+
/* is any of the bytes from offset .. u8_size in 'u8' non-zero? return offset or -1 if all zero */
static int byte_nonzero(const uint8_t *u8, unsigned int offset, unsigned int u8_size)
{
@@ -640,7 +646,7 @@
}
}
-static void stream_cli_iofd_write_cb(struct osmo_io_fd *iofd, int res, struct msgb *msg)
+static void stream_cli_iofd_write_cb(struct osmo_io_fd *iofd, int res, const struct msgb *msg)
{
struct osmo_stream_cli *cli = osmo_iofd_get_data(iofd);
@@ -1189,6 +1195,7 @@
int sk_domain;
int sk_type;
uint16_t proto;
+ enum osmo_stream_proto stream_proto;
int (*accept_cb)(struct osmo_stream_srv_link *srv, int fd);
void *data;
int flags;
@@ -1279,22 +1286,7 @@
link->sk_domain = AF_UNSPEC;
link->sk_type = SOCK_STREAM;
link->proto = IPPROTO_TCP;
- osmo_fd_setup(&link->ofd, -1, OSMO_FD_READ | OSMO_FD_WRITE, osmo_stream_srv_ofd_cb, link, 0);
-
- return link;
-}
-
-struct osmo_stream_srv_link *osmo_stream_srv_link_create_iofd(void *ctx, const char *name)
-{
- struct osmo_stream_srv_link *link;
-
- link = talloc_zero(ctx, struct osmo_stream_srv_link);
- if (!link)
- return NULL;
-
- link->sk_domain = AF_UNSPEC;
- link->sk_type = SOCK_STREAM;
- link->proto = IPPROTO_TCP;
+ link->stream_proto = OSMO_STREAM_UNSPECIFIED;
osmo_fd_setup(&link->ofd, -1, OSMO_FD_READ | OSMO_FD_WRITE, osmo_stream_srv_ofd_cb, link, 0);
return link;
@@ -1431,6 +1423,23 @@
.write_cb = stream_srv_iofd_write_cb,
};
+/*! \brief Set the protocol transported by the stream for the stream server link
+ * \param[in] link Stream Server Link to modify
+ * \param[in] proto Protocol (like IPPROTO_TCP (default), IPPROTO_SCTP, ...).
+ */
+void osmo_stream_srv_link_set_stream_proto(struct osmo_stream_srv_link *link,
+ enum osmo_stream_proto osp)
+{
+ if (!(OSMO_STREAM_UNSPECIFIED <= osp && osp < _NUM_OSMO_STREAM_PROTOS)) {
+ LOGP(DLINP, LOGL_ERROR, "Unexpected value (%d) for variable of type "
+ "'enum osmo_stream_proto'\n", osp);
+ return;
+ }
+ link->stream_proto = osp;
+ srv_ioops.segmentation_cb = segmentation_cbs[osp];
+ link->flags |= OSMO_STREAM_SRV_F_RECONF;
+}
+
/*! \brief Set the socket type for the stream server link
* \param[in] link Stream Server Link to modify
* \param[in] type Socket Type (like SOCK_STREAM (default), SOCK_SEQPACKET, ...)
@@ -1765,7 +1774,8 @@
}
conn->mode = OSMO_STREAM_MODE_OSMO_IO;
conn->srv = link;
- conn->iofd = osmo_iofd_setup(conn, fd, name, OSMO_IO_FD_MODE_READ_WRITE, &srv_ioops, conn);
+ conn->iofd = osmo_iofd_setup(conn, fd, name, OSMO_IO_FD_MODE_READ_WRITE,
+ &srv_ioops, conn);
conn->iofd_read_cb = read_cb;
conn->closed_cb = closed_cb;
conn->data = data;
diff --git a/tests/stream/stream_test.c b/tests/stream/stream_test.c
index 36a222e..b537d5e 100644
--- a/tests/stream/stream_test.c
+++ b/tests/stream/stream_test.c
@@ -8,18 +8,23 @@
* (at your option) any later version.
*/
+#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
#include <unistd.h>
#include <errno.h>
+#include <osmocom/core/byteswap.h>
#include <osmocom/core/select.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/logging.h>
#include <osmocom/core/application.h>
#include <osmocom/core/timer.h>
+#include <osmocom/gsm/protocol/ipaccess.h>
#include <osmocom/netif/stream.h>
@@ -363,10 +368,233 @@
printf("{%lu.%06lu} %s test complete.\n\n", tv.tv_sec, tv.tv_usec, ASTR(autoreconnect));
}
+/* Segmentation test code (using IPA) */
+struct ipa_head {
+ uint16_t len;
+ uint8_t proto;
+ uint8_t data[0];
+} __attribute__ ((packed));
+
+#define IPAC_MSG_PING_LEN 0x01
+static const uint8_t ipac_msg_ping[] = {
+ 0x00, IPAC_MSG_PING_LEN,
+ IPAC_PROTO_IPACCESS,
+ IPAC_MSGT_PING
+};
+#define IPAC_MSG_PONG_LEN 0x01
+static const uint8_t ipac_msg_pong[] = {
+ 0x00, IPAC_MSG_PONG_LEN,
+ IPAC_PROTO_IPACCESS,
+ IPAC_MSGT_PONG
+};
+#define IPAC_MSG_ID_REQ_LEN 0x03
+static const uint8_t ipac_msg_idreq[] = {
+ 0x00, IPAC_MSG_ID_REQ_LEN,
+ IPAC_PROTO_IPACCESS,
+ IPAC_MSGT_ID_GET,
+ 0x01, IPAC_IDTAG_UNITNAME
+};
+#define ipac_msg_idreq_half (sizeof (ipac_msg_idreq)/2)
+#define ipac_msg_idreq_other_half (sizeof (ipac_msg_idreq) - ipac_msg_idreq_half)
+#define IPAC_MSG_ID_RESP_LEN 0x07
+static const uint8_t ipac_msg_idresp[] = {
+ 0x00, IPAC_MSG_ID_RESP_LEN,
+ IPAC_PROTO_IPACCESS,
+ IPAC_MSGT_ID_RESP,
+ 0x01, IPAC_IDTAG_UNITNAME, 0xde, 0xad, 0xbe, 0xef
+};
+
+#define put_ipa_msg(unsigned_char_ptr, struct_msgb_ptr, byte_array) do {\
+ (unsigned_char_ptr) = msgb_put(struct_msgb_ptr, sizeof (byte_array));\
+ memcpy(unsigned_char_ptr, byte_array, sizeof (byte_array));\
+} while (0)
+
+/* Array indices correspond to enum values stringified on the right */
+static const char * const IPAC_MSG_TYPES[] = {
+ [0] = "IPAC_MSGT_PING",
+ [1] = "IPAC_MSGT_PONG",
+ [2] = "UNEXPECTED VALUE",
+ [3] = "UNEXPECTED VALUE",
+ [4] = "IPAC_MSGT_ID_GET",
+ [5] = "IPAC_MSGT_ID_RESP",
+};
+
+#define IPAC_MSGT_OFFSET 3
+/* Append a message to UCHAR_PTR_DST. SRC_IPAC_MSG_BUF is expected to be a
+ * message buffer containing an * IPA message of type IPAC_PROTO_ACCESS that is
+ * syntactically correct up to offset 3 (IPAC_MSGT_OFFSET).
+ * Uses a counter so that appended messages can be distinguished easily in the logs */
+#define CLI_APPEND_MSG(OSMO_STREAM_CLI_PTR, UCHAR_PTR_DST, STRUCT_MSGB_PTR, SRC_IPAC_MSG_BUF) do {\
+ LOGCLI(OSMO_STREAM_CLI_PTR, "[0%u-cli] Appending msg of type %s into buffer\n",\
+ ++msglognum_cli, IPAC_MSG_TYPES[SRC_IPAC_MSG_BUF[IPAC_MSGT_OFFSET]]);\
+ LOGCLI(OSMO_STREAM_CLI_PTR, "\t(msg dump: %s)\n", osmo_hexdump(SRC_IPAC_MSG_BUF,\
+ sizeof(SRC_IPAC_MSG_BUF)));\
+ put_ipa_msg(UCHAR_PTR_DST, STRUCT_MSGB_PTR, SRC_IPAC_MSG_BUF);\
+} while (0)
+
+static unsigned msglognum_cli = 0;
+static int test_segm_cli_connect_cb(struct osmo_stream_cli *cli)
+{
+ printf("Connect callback triggered (segmentation test)\n");
+ unsigned char *data;
+ struct msgb *m = msgb_alloc_headroom(128, 0, "IPA messages");
+ if (m == NULL) {
+ fprintf(stderr, "Cannot allocate message\n");
+ return -ENOMEM;
+ }
+
+ /* Send 4 and 1/2 messages */
+ CLI_APPEND_MSG(cli, data, m, ipac_msg_ping);
+ CLI_APPEND_MSG(cli, data, m, ipac_msg_pong);
+ CLI_APPEND_MSG(cli, data, m, ipac_msg_ping);
+ CLI_APPEND_MSG(cli, data, m, ipac_msg_idresp);
+
+ LOGCLI(cli, "[0%u.5-cli] Appending *half* of msg of type %s into buffer\n",
+ msglognum_cli, IPAC_MSG_TYPES[ipac_msg_idreq[3]]);
+ LOGCLI(cli, "\t(dump: %s)\n", osmo_hexdump(ipac_msg_idreq, ipac_msg_idreq_half));
+ data = msgb_put(m, ipac_msg_idreq_half);
+ memcpy(data, ipac_msg_idreq, ipac_msg_idreq_half);
+
+ LOGCLI(cli, "Sending 4 1/2 messages as one:\n");
+ LOGCLI(cli, "\t(msg dump: %s)\n\n", osmo_hexdump(m->data, m->len));
+ osmo_stream_cli_send(cli, m);
+ return 0;
+}
+
+static bool all_msgs_processed = false;
+
+static int test_segm_stream_cli_read_cb(struct osmo_stream_cli *osc, struct msgb *msg)
+{
+ unsigned char *data;
+ struct ipa_head *h = (struct ipa_head *) msg->data;
+ uint8_t ipa_msg_type = ((uint8_t *)h)[sizeof(struct ipa_head)];
+ LOGCLI(osc, "Received message from stream (total len = %" PRIu16 ")\n", msgb_length(msg));
+ if (ipa_msg_type < 0 || 5 < ipa_msg_type) {
+ fprintf(stderr, "Received unexpected IPAC message type %"PRIu8"\n", ipa_msg_type);
+ return -ENOMSG;
+ }
+ LOGCLI(osc, "\tType: %s\n", IPAC_MSG_TYPES[ipa_msg_type]);
+ if (ipa_msg_type == IPAC_MSGT_ID_GET) {
+ LOGCLI(osc, "Got IPAC_MSGT_ID_GET from server\n");
+ LOGCLI(osc, "[%u-cli] Sending second half of IPAC_MSGT_ID_GET\n", ++msglognum_cli);
+ data = msgb_put(msg, ipac_msg_idreq_other_half);
+ memcpy(data, ipac_msg_idreq + ipac_msg_idreq_half,
+ ipac_msg_idreq_other_half);
+ LOGCLI(osc, "\t(msg dump: %s)\n", osmo_hexdump(data, ipac_msg_idreq_other_half));
+ osmo_stream_cli_send(osc, msg);
+ } else if (ipa_msg_type == IPAC_MSGT_ID_RESP) {
+ LOGCLI(osc, "\tresult= %s\n", osmo_hexdump(msg->data, msg->len));
+ LOGCLI(osc, "\texpected=%s\n",
+ osmo_hexdump(ipac_msg_idresp, sizeof(ipac_msg_idresp)));
+ }
+ printf("\n");
+ return 0;
+}
+
+static void *test_segm_run_client(void)
+{
+ struct osmo_stream_cli *osc;
+ void *ctx = talloc_named_const(NULL, 0, "test_segm_run_client");
+
+ (void) msgb_talloc_ctx_init(ctx, 0);
+ osc = osmo_stream_cli_create_iofd(ctx, "IPA test client");
+ if (osc == NULL) {
+ fprintf(stderr, "osmo_stream_cli_create_iofd()\n");
+ return NULL;
+ }
+ osmo_stream_cli_set_addr(osc, "127.0.0.11");
+ osmo_stream_cli_set_port(osc, 1111);
+ osmo_stream_cli_set_connect_cb(osc, test_segm_cli_connect_cb);
+ osmo_stream_cli_set_data(osc, ctx);
+ osmo_stream_cli_set_iofd_read_cb(osc, test_segm_stream_cli_read_cb);
+ osmo_stream_cli_set_nodelay(osc, true);
+ if (osmo_stream_cli_open(osc) < 0) {
+ fprintf(stderr, "Cannot open stream client\n");
+ return NULL;
+ }
+
+ return NULL;
+}
+
+static bool test_segm_ipa(void *ctx, const char *host, unsigned port,
+ struct osmo_stream_srv_link *srv)
+{
+ int rc;
+ const int max_test_duration = 2;
+ struct timespec start, now;
+ test_segm_run_client();
+
+ rc = clock_gettime(CLOCK_MONOTONIC, &start);
+ if (rc < 0) {
+ fprintf(stderr, "clock_gettime(): %s\n", strerror(errno));
+ return EXIT_FAILURE;
+ }
+ while (!all_msgs_processed) {
+ osmo_gettimeofday_override_add(0, 1); /* small increment to easily spot iterations */
+ osmo_select_main(1);
+ rc = clock_gettime(CLOCK_MONOTONIC, &now);
+ if (rc < 0) {
+ fprintf(stderr, "clock_gettime(): %s\n", strerror(errno));
+ return EXIT_FAILURE;
+ }
+ if (now.tv_sec - start.tv_sec > max_test_duration) {
+ fprintf(stderr, "test_segm_ipa(): Timeout\n");
+ osmo_stream_srv_link_unset_stream_proto(srv);
+ return EXIT_FAILURE;
+ }
+ }
+
+ osmo_stream_srv_link_unset_stream_proto(srv);
+ return EXIT_SUCCESS;
+}
+
+static unsigned msgnum_srv = 0;
+int test_segm_stream_srv_read_cb(struct osmo_stream_srv *conn, struct msgb *msg)
+{
+ unsigned char *data;
+ struct msgb *m;
+ uint8_t *msgt = msg->data + sizeof(struct ipa_head);
+ LOGSRV(conn, "[%u-srv] Received message from stream (len = %" PRIu16 ")\n",
+ ++msgnum_srv, msgb_length(msg));
+ msgb_pull(msg, sizeof(struct ipa_head));
+ LOGSRV(conn, "\tIPA data: %s\n", osmo_hexdump(msg->data, msg->len));
+ LOGSRV(conn, "\tType: %s\n", IPAC_MSG_TYPES[*msgt]);
+ LOGSRV(conn, "\t(msg dump: %s)\n", osmo_hexdump(msg->data - sizeof(struct ipa_head),
+ msg->len + sizeof(struct ipa_head)));
+ if (*msgt == IPAC_MSGT_ID_RESP) { /* */
+ LOGSRV(conn, "Send IPAC_MSGT_ID_GET to trigger client to send 2nd half\n\n");
+ m = msgb_alloc_headroom(128, 0, "IPA messages");
+ if (m == NULL) {
+ fprintf(stderr, "Cannot allocate message\n");
+ return -ENOMEM;
+ }
+ put_ipa_msg(data, m, ipac_msg_idreq);
+ osmo_stream_srv_send(conn, m);
+ } else if (*msgt == IPAC_MSGT_ID_GET) {
+ all_msgs_processed = true;
+ }
+ return 0;
+}
+
+static int test_segm_stream_srv_accept_cb(struct osmo_stream_srv_link *srv, int fd)
+{
+ void *ctx = talloc_named_const(NULL, 0, "test_segm_stream_srv_accept_cb");
+ struct osmo_stream_srv *oss =
+ osmo_stream_srv_create_iofd(ctx, "srv link", srv, fd,
+ test_segm_stream_srv_read_cb,
+ close_cb_srv, NULL);
+ if (oss == NULL) {
+ fprintf(stderr, "Error while creating connection\n");
+ return -1;
+ }
+
+ return 0;
+}
int main(void)
{
struct osmo_stream_srv_link *srv;
+ bool rc;
char *host = "127.0.0.11";
unsigned port = 1111;
void *tall_test = talloc_named_const(NULL, 1, "osmo_stream_test");
@@ -402,8 +630,14 @@
test_recon(tall_test, host, port, 12, srv, true);
test_recon(tall_test, host, port, 8, srv, false);
- osmo_stream_srv_link_destroy(srv);
+ osmo_stream_srv_link_set_accept_cb(srv,
+ test_segm_stream_srv_accept_cb);
+ osmo_stream_srv_link_set_stream_proto(srv, OSMO_STREAM_IPAC);
+ if (osmo_stream_srv_link_open(srv) < 0) {
+ printf("Unable to open server\n");
+ return EXIT_FAILURE;
+ }
+ rc = test_segm_ipa(tall_test, host, port, srv);
printf("Stream tests completed\n");
-
- return EXIT_SUCCESS;
+ return rc;
}
diff --git a/tests/stream/stream_test.ok b/tests/stream/stream_test.ok
index 2106295..7763212 100644
--- a/tests/stream/stream_test.ok
+++ b/tests/stream/stream_test.ok
@@ -48,4 +48,46 @@
{11.000019} [OK] Client's read_cb_cli(): 0-byte read, auto-reconnect will be triggered if enabled
{20.000019} non-reconnecting test complete.
+Connect callback triggered (segmentation test)
+{20.000020} [OK] Client's test_segm_cli_connect_cb(): [01-cli] Appending msg of type IPAC_MSGT_PING into buffer
+{20.000020} [OK] Client's test_segm_cli_connect_cb(): (msg dump: 00 01 fe 00 )
+{20.000020} [OK] Client's test_segm_cli_connect_cb(): [02-cli] Appending msg of type IPAC_MSGT_PONG into buffer
+{20.000020} [OK] Client's test_segm_cli_connect_cb(): (msg dump: 00 01 fe 01 )
+{20.000020} [OK] Client's test_segm_cli_connect_cb(): [03-cli] Appending msg of type IPAC_MSGT_PING into buffer
+{20.000020} [OK] Client's test_segm_cli_connect_cb(): (msg dump: 00 01 fe 00 )
+{20.000020} [OK] Client's test_segm_cli_connect_cb(): [04-cli] Appending msg of type IPAC_MSGT_ID_RESP into buffer
+{20.000020} [OK] Client's test_segm_cli_connect_cb(): (msg dump: 00 07 fe 05 01 01 de ad be ef )
+{20.000020} [OK] Client's test_segm_cli_connect_cb(): [04.5-cli] Appending *half* of msg of type IPAC_MSGT_ID_GET into buffer
+{20.000020} [OK] Client's test_segm_cli_connect_cb(): (dump: 00 03 fe )
+{20.000020} [OK] Client's test_segm_cli_connect_cb(): Sending 4 1/2 messages as one:
+{20.000020} [OK] Client's test_segm_cli_connect_cb(): (msg dump: 00 01 fe 00 00 01 fe 01 00 01 fe 00 00 07 fe 05 01 01 de ad be ef 00 03 fe )
+
+{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): [1-srv] Received message from stream (len = 4)
+{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): IPA data: 00
+{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): Type: IPAC_MSGT_PING
+{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): (msg dump: 00 01 fe 00 )
+{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): [2-srv] Received message from stream (len = 4)
+{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): IPA data: 01
+{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): Type: IPAC_MSGT_PONG
+{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): (msg dump: 00 01 fe 01 )
+{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): [3-srv] Received message from stream (len = 4)
+{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): IPA data: 00
+{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): Type: IPAC_MSGT_PING
+{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): (msg dump: 00 01 fe 00 )
+{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): [4-srv] Received message from stream (len = 10)
+{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): IPA data: 05 01 01 de ad be ef
+{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): Type: IPAC_MSGT_ID_RESP
+{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): (msg dump: 00 07 fe 05 01 01 de ad be ef )
+{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): Send IPAC_MSGT_ID_GET to trigger client to send 2nd half
+
+{20.000024} [OK] Client's test_segm_stream_cli_read_cb(): Received message from stream (total len = 6)
+{20.000024} [OK] Client's test_segm_stream_cli_read_cb(): Type: IPAC_MSGT_ID_GET
+{20.000024} [OK] Client's test_segm_stream_cli_read_cb(): Got IPAC_MSGT_ID_GET from server
+{20.000024} [OK] Client's test_segm_stream_cli_read_cb(): [5-cli] Sending second half of IPAC_MSGT_ID_GET
+{20.000024} [OK] Client's test_segm_stream_cli_read_cb(): (msg dump: 04 01 01 )
+
+{20.000026} [NA|OK] Server's test_segm_stream_srv_read_cb(): [5-srv] Received message from stream (len = 6)
+{20.000026} [NA|OK] Server's test_segm_stream_srv_read_cb(): IPA data: 04 01 01
+{20.000026} [NA|OK] Server's test_segm_stream_srv_read_cb(): Type: IPAC_MSGT_ID_GET
+{20.000026} [NA|OK] Server's test_segm_stream_srv_read_cb(): (msg dump: 00 03 fe 04 01 01 )
Stream tests completed
To view, visit change 33197. To unsubscribe, or for help writing mail filters, visit settings.