From 39d904f14929b7096bd146a67ea80913199fe693 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 1 Jun 2011 18:49:07 +0200 Subject: osmo-pcap-server: Try to read the the data with a simple state machine --- include/osmo-pcap/osmo_pcap_server.h | 10 +++++ src/osmo_server_network.c | 72 +++++++++++++++++++++++++----------- 2 files changed, 60 insertions(+), 22 deletions(-) diff --git a/include/osmo-pcap/osmo_pcap_server.h b/include/osmo-pcap/osmo_pcap_server.h index a94724c..b408c47 100644 --- a/include/osmo-pcap/osmo_pcap_server.h +++ b/include/osmo-pcap/osmo_pcap_server.h @@ -36,6 +36,10 @@ struct osmo_pcap_server; + +#define STATE_INITIAL 0 +#define STATE_DATA 1 + struct osmo_pcap_conn { /* list of connections */ struct llist_head entry; @@ -55,6 +59,12 @@ struct osmo_pcap_conn { /* last time */ struct tm last_write; + + /* read buffering */ + int state; + int pend; + char buf[4096]; + struct osmo_pcap_data *data; }; struct osmo_pcap_server { diff --git a/src/osmo_server_network.c b/src/osmo_server_network.c index d1948a8..3a4ef27 100644 --- a/src/osmo_server_network.c +++ b/src/osmo_server_network.c @@ -167,49 +167,76 @@ struct osmo_pcap_conn *osmo_pcap_server_find(struct osmo_pcap_server *server, conn->rem_fd.fd = -1; conn->local_fd = -1; conn->server = server; + conn->data = (struct osmo_pcap_data *) &conn->buf[0]; llist_add_tail(&conn->entry, &server->conn); return conn; } -static int read_cb(struct osmo_fd *fd, unsigned int what) +static int read_cb_initial(struct osmo_fd *fd, struct osmo_pcap_conn *conn) { - struct osmo_pcap_data *data; - struct osmo_pcap_conn *conn; - char buf[4096]; int rc; + rc = read(fd->fd, conn->buf, sizeof(*conn->data)); - conn = fd->data; - data = (struct osmo_pcap_data *) &buf[0]; - - rc = read(fd->fd, buf, sizeof(*data)); - if (rc != sizeof(*data)) { + if (rc != sizeof(*conn->data)) { LOGP(DSERVER, LOGL_ERROR, "Failed to read from %s\n", conn->name); close_connection(conn); return -1; } - data->len = ntohs(data->len); - if (data->len > 2000) { - LOGP(DSERVER, LOGL_ERROR, "Unplausible result %u\n", data->len); + conn->data->len = ntohs(conn->data->len); + if (conn->data->len > 2000) { + LOGP(DSERVER, LOGL_ERROR, "Unplausible result %u\n", conn->data->len); close_connection(conn); return -1; } - rc = read(fd->fd, &data->data[0], data->len); - if (rc != data->len) { + conn->state = STATE_DATA; + conn->pend = conn->data->len; + return 0; +} + +static int read_cb_data(struct osmo_fd *fd, struct osmo_pcap_conn *conn) +{ + int rc; + rc = read(fd->fd, &conn->data->data[conn->data->len - conn->pend], conn->pend); + if (rc <= 0) { LOGP(DSERVER, LOGL_ERROR, - "Too short packet. Got %d, wanted %d\n", rc, data->len); + "Too short packet. Got %d, wanted %d\n", rc, conn->data->len); close_connection(conn); return -1; } - switch (data->type) { - case PKT_LINK_HDR: - link_data(conn, data); - break; - case PKT_LINK_DATA: - write_data(conn, data); - break; + conn->pend -= rc; + if (conn->pend < 0) { + LOGP(DSERVER, LOGL_ERROR, + "Someone got the pending read wrong: %d\n", conn->pend); + close_connection(conn); + return -1; + } else if (conn->pend == 0) { + conn->state = STATE_INITIAL; + switch (conn->data->type) { + case PKT_LINK_HDR: + link_data(conn, conn->data); + break; + case PKT_LINK_DATA: + write_data(conn, conn->data); + break; + } + } + + return 0; +} + +static int read_cb(struct osmo_fd *fd, unsigned int what) +{ + struct osmo_pcap_conn *conn; + + conn = fd->data; + + if (conn->state == STATE_INITIAL) { + return read_cb_initial(fd, conn); + } else if (conn->state == STATE_DATA) { + return read_cb_data(fd, conn); } return 0; @@ -232,6 +259,7 @@ static void new_connection(struct osmo_pcap_server *server, client->rem_fd.data = client; client->rem_fd.when = BSC_FD_READ; client->rem_fd.cb = read_cb; + client->state = STATE_INITIAL; } static int accept_cb(struct osmo_fd *fd, unsigned int when) -- cgit v1.2.3