From 956c3facf1950e8f84291089972ab8323c75767a Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 8 Nov 2016 18:48:57 +0100 Subject: client: Enable a non-blocking connect to the PCAP server If we want to have multiple servers we should not block when trying to connect to one of them. Enable non blocking mode and handle the fd specially until it is connected. E.g. on failed connect the read will become readable but fail, otherwise it becomes writable. Clear the write queue to make sure that the link data is sent first. We might be able to introduce a osmo_wqueue_prepend. Change-Id: Iae2bc264d15aa8598beefc194e3b8c4ebe87320a --- src/osmo_client_network.c | 56 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/src/osmo_client_network.c b/src/osmo_client_network.c index d1d39dc..0662934 100644 --- a/src/osmo_client_network.c +++ b/src/osmo_client_network.c @@ -107,6 +107,7 @@ static void handshake_done_cb(struct osmo_tls_session *session) struct osmo_pcap_client_conn *conn; conn = container_of(session, struct osmo_pcap_client_conn, tls_session); + osmo_wqueue_clear(&conn->wqueue); osmo_client_send_link(conn); } @@ -118,6 +119,38 @@ static void tls_error_cb(struct osmo_tls_session *session) lost_connection(conn); } +int conn_cb(struct osmo_fd *fd, unsigned int what) +{ + /* finally the socket is connected... continue */ + if (what & BSC_FD_WRITE) { + struct osmo_pcap_client_conn *conn = fd->data; + /* + * 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_send_link(conn); + } + } + + if (what & BSC_FD_READ) + read_cb(fd); + return 0; +} + void osmo_client_send_data(struct osmo_pcap_client_conn *conn, struct pcap_pkthdr *in_hdr, const uint8_t *data) { @@ -198,7 +231,8 @@ void osmo_client_connect(struct osmo_pcap_client_conn *conn) osmo_wqueue_clear(&conn->wqueue); fd = osmo_sock_init(AF_INET, SOCK_STREAM, IPPROTO_TCP, - conn->srv_ip, conn->srv_port, OSMO_SOCK_F_CONNECT); + conn->srv_ip, conn->srv_port, + OSMO_SOCK_F_CONNECT | OSMO_SOCK_F_NONBLOCK); if (fd < 0) { LOGP(DCLIENT, LOGL_ERROR, "Failed to connect to %s:%d\n", @@ -216,23 +250,9 @@ void osmo_client_connect(struct osmo_pcap_client_conn *conn) } rate_ctr_inc(&conn->client->ctrg->ctr[CLIENT_CTR_CONNECT]); - - /* - * 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; - } - conn->tls_session.handshake_done = handshake_done_cb; - conn->tls_session.error = tls_error_cb; - } else { - conn->wqueue.bfd.cb = osmo_wqueue_bfd_cb; - conn->wqueue.bfd.data = conn; - osmo_client_send_link(conn); - } + conn->wqueue.bfd.cb = conn_cb; + conn->wqueue.bfd.data = conn; + conn->wqueue.bfd.when = BSC_FD_READ | BSC_FD_WRITE; } void osmo_client_reconnect(struct osmo_pcap_client_conn *conn) -- cgit v1.2.3