pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-pcap/+/39944?usp=email )
Change subject: client: use osmo_stream_cli to transmit data to pcap-server ......................................................................
client: use osmo_stream_cli to transmit data to pcap-server
Similarly to previous work done in osmo-pcap-server, the switch to osmo_stream doesn't cover the TLS-enabled scenario, since moving TLS related code to osmo_stream requires significant amount of work and can be done in a subsequent step.
Related: SYS#7290 Change-Id: I72e8a6ceb4fb1eb70372e13bb139ead0e2bc0860 --- M include/osmo-pcap/osmo_pcap_client.h M src/Makefile.am M src/osmo_client_network.c M src/osmo_client_vty.c 4 files changed, 143 insertions(+), 35 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-pcap refs/changes/44/39944/1
diff --git a/include/osmo-pcap/osmo_pcap_client.h b/include/osmo-pcap/osmo_pcap_client.h index 1b66488..fdd59f9 100644 --- a/include/osmo-pcap/osmo_pcap_client.h +++ b/include/osmo-pcap/osmo_pcap_client.h @@ -70,7 +70,7 @@ char *srv_ip; int srv_port; char *source_ip; - struct osmo_wqueue wqueue; + struct osmo_stream_cli *cli; struct osmo_timer_list timer; enum osmo_pcap_protocol protocol;
@@ -87,6 +87,7 @@ unsigned tls_log_level;
struct osmo_tls_session tls_session; + struct osmo_wqueue wqueue;
/* back pointer */ struct osmo_pcap_client *client; diff --git a/src/Makefile.am b/src/Makefile.am index 504952f..b45bf84 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,6 +26,7 @@ $(NULL)
osmo_pcap_client_LDADD = \ + $(LIBOSMONETIF_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(LIBOSMOVTY_LIBS) \ $(LIBOSMOCORE_LIBS) \ diff --git a/src/osmo_client_network.c b/src/osmo_client_network.c index abdb7d3..412fe56 100644 --- a/src/osmo_client_network.c +++ b/src/osmo_client_network.c @@ -32,6 +32,8 @@ #include <osmocom/core/select.h> #include <osmocom/core/socket.h>
+#include <osmocom/netif/stream.h> + #include <arpa/inet.h> #include <netinet/in.h> #include <netdb.h> @@ -61,13 +63,26 @@
static void write_data(struct osmo_pcap_client_conn *conn, struct msgb *msg) { - if (osmo_wqueue_enqueue_quiet(&conn->wqueue, msg) != 0) { - LOGCONN(conn, LOGL_ERROR, "Failed to enqueue msg (capacity: %u/%u)\n", - conn->wqueue.current_length, conn->wqueue.max_length); + if (conn->tls_on) { + if (osmo_wqueue_enqueue_quiet(&conn->wqueue, msg) != 0) { + LOGCONN(conn, LOGL_ERROR, "Failed to enqueue msg (capacity: %u/%u)\n", + conn->wqueue.current_length, conn->wqueue.max_length); + rate_ctr_inc2(conn->client->ctrg, CLIENT_CTR_QERR); + msgb_free(msg); + } + return; + } + + if (!conn->cli) { + LOGCONN(conn, LOGL_NOTICE, "Failed to enqueue msg (no stream)\n"); rate_ctr_inc2(conn->client->ctrg, CLIENT_CTR_QERR); msgb_free(msg); return; } + osmo_stream_cli_send(conn->cli, msg); + /* FIXME: osmo_stream_cli_send() doesn't have a rc, hence we cannot never increment on error: + * rate_ctr_inc2(conn->client->ctrg, CLIENT_CTR_QERR); + */ }
static int read_cb(struct osmo_fd *fd) @@ -128,22 +143,15 @@ * The write queue needs to work differently for GNUtls. Before we can * send data we will need to complete handshake. */ - if (conn->tls_on) { - if (!osmo_tls_init_client_session(conn)) { - lost_connection(conn); - return -1; - } - conn->tls_session.handshake_done = handshake_done_cb; - conn->tls_session.error = tls_error_cb; - - /* fd->data now points somewhere else, stop */ - return 0; - } else { - conn->wqueue.bfd.cb = osmo_wqueue_bfd_cb; - conn->wqueue.bfd.data = conn; - osmo_wqueue_clear(&conn->wqueue); - osmo_client_conn_send_link(conn); + if (!osmo_tls_init_client_session(conn)) { + lost_connection(conn); + return -1; } + conn->tls_session.handshake_done = handshake_done_cb; + conn->tls_session.error = tls_error_cb; + + /* fd->data now points somewhere else, stop */ + return 0; }
if (what & OSMO_FD_READ) @@ -446,15 +454,13 @@ write_data(conn, msg); }
-void osmo_client_conn_connect(struct osmo_pcap_client_conn *conn) +static void osmo_client_conn_connect_tls(struct osmo_pcap_client_conn *conn) { int rc; uint16_t srv_port; int sock_type, sock_proto; unsigned int when;
- osmo_client_conn_disconnect(conn); - conn->wqueue.read_cb = read_cb; conn->wqueue.write_cb = write_cb; osmo_wqueue_clear(&conn->wqueue); @@ -490,6 +496,91 @@ rate_ctr_inc2(conn->client->ctrg, CLIENT_CTR_CONNECT); }
+static int stream_cli_connect_cb(struct osmo_stream_cli *cli) +{ + struct osmo_pcap_client_conn *conn = osmo_stream_cli_get_data(cli); + osmo_client_conn_send_link(conn); + return 0; +} + +static int stream_cli_disconnect_cb(struct osmo_stream_cli *cli) +{ + struct osmo_pcap_client_conn *conn = osmo_stream_cli_get_data(cli); + lost_connection(conn); + return 0; +} + +static int stream_cli_read_cb(struct osmo_stream_cli *cli, int res, struct msgb *msg) +{ + struct osmo_pcap_client_conn *conn = osmo_stream_cli_get_data(cli); + + msgb_free(msg); + if (res <= 0) { + LOGCONN(conn, LOGL_ERROR, "Lost connection on read\n"); + lost_connection(conn); + } + return 0; +} + +void osmo_client_conn_connect(struct osmo_pcap_client_conn *conn) +{ + uint16_t srv_port; + int sock_type, sock_proto; + struct osmo_stream_cli *cli; + + osmo_client_conn_disconnect(conn); + + /* We still don't support the tls layer through osmo_stream... */ + if (conn->tls_on) { + osmo_client_conn_connect_tls(conn); + return; + } + + switch (conn->protocol) { + case PROTOCOL_OSMOPCAP: + srv_port = conn->srv_port; + sock_type = SOCK_STREAM; + sock_proto = IPPROTO_TCP; + break; + case PROTOCOL_IPIP: + srv_port = 0; + sock_type = SOCK_RAW; + sock_proto = IPPROTO_IPIP; + break; + default: + OSMO_ASSERT(0); + break; + } + + OSMO_ASSERT(!conn->cli); + conn->cli = cli = osmo_stream_cli_create(conn); + osmo_stream_cli_set_name(cli, conn->name); + osmo_stream_cli_set_data(cli, conn); + osmo_stream_cli_set_type(cli, sock_type); + osmo_stream_cli_set_proto(cli, sock_proto); + osmo_stream_cli_set_local_addr(cli, conn->source_ip); + osmo_stream_cli_set_local_port(cli, 0); + osmo_stream_cli_set_addr(cli, conn->srv_ip); + osmo_stream_cli_set_port(cli, srv_port); + osmo_stream_cli_set_nodelay(cli, true); + osmo_stream_cli_set_tx_queue_max_length(cli, conn->wqueue.max_length); + + /* Reconnect is handled by upper layers: */ + osmo_stream_cli_set_reconnect_timeout(cli, -1); + osmo_stream_cli_set_connect_cb(cli, stream_cli_connect_cb); + osmo_stream_cli_set_disconnect_cb(cli, stream_cli_disconnect_cb); + osmo_stream_cli_set_read_cb2(cli, stream_cli_read_cb); + + if (osmo_stream_cli_open(cli)) { + LOGCONN(conn, LOGL_ERROR, "cannot open OML BTS link: %s\n", strerror(errno)); + conn->cli = NULL; + osmo_stream_cli_destroy(cli); + return; + } + + rate_ctr_inc2(conn->client->ctrg, CLIENT_CTR_CONNECT); +} + void osmo_client_conn_reconnect(struct osmo_pcap_client_conn *conn) { lost_connection(conn); @@ -497,12 +588,20 @@
void osmo_client_conn_disconnect(struct osmo_pcap_client_conn *conn) { - if (conn->wqueue.bfd.fd >= 0) { - osmo_tls_release(&conn->tls_session); - osmo_fd_unregister(&conn->wqueue.bfd); - close(conn->wqueue.bfd.fd); - conn->wqueue.bfd.fd = -1; - } - osmo_timer_del(&conn->timer); + + if (conn->tls_on) { + if (conn->wqueue.bfd.fd >= 0) { + osmo_tls_release(&conn->tls_session); + osmo_fd_unregister(&conn->wqueue.bfd); + close(conn->wqueue.bfd.fd); + conn->wqueue.bfd.fd = -1; + } + } else { + if (conn->cli) { + struct osmo_stream_cli *cli = conn->cli; + conn->cli = NULL; + osmo_stream_cli_destroy(cli); + } + } } diff --git a/src/osmo_client_vty.c b/src/osmo_client_vty.c index 1824324..127e52f 100644 --- a/src/osmo_client_vty.c +++ b/src/osmo_client_vty.c @@ -25,6 +25,7 @@ #include <osmo-pcap/common.h>
#include <osmocom/core/talloc.h> +#include <osmocom/netif/stream.h>
#include <stdlib.h>
@@ -262,12 +263,12 @@ { struct osmo_pcap_client_conn *conn = get_conn(vty);
- if (!conn->tls_on) { - if (conn->wqueue.bfd.fd >= 0) - osmo_client_conn_reconnect(conn); - } + if (conn->tls_on) + return CMD_SUCCESS;
+ osmo_client_conn_disconnect(conn); conn->tls_on = true; + osmo_client_conn_connect(conn); return CMD_SUCCESS; }
@@ -278,10 +279,12 @@ { struct osmo_pcap_client_conn *conn = get_conn(vty);
- if (conn->tls_on) - osmo_client_conn_reconnect(conn); + if (!conn->tls_on) + return CMD_SUCCESS;
+ osmo_client_conn_disconnect(conn); conn->tls_on = false; + osmo_client_conn_connect(conn); return CMD_SUCCESS; }
@@ -568,6 +571,10 @@ struct osmo_pcap_client_conn *conn = get_conn(vty);
conn->wqueue.max_length = atoi(argv[0]); + /* Apply on conn immediately if already created: */ + if (conn->cli) + osmo_stream_cli_set_tx_queue_max_length(conn->cli, conn->wqueue.max_length); + return CMD_SUCCESS; }