osmo-pcap-server: Try to read the the data with a simple state machine

This commit is contained in:
Holger Hans Peter Freyther 2011-06-01 18:49:07 +02:00
parent 9df7dc5f69
commit 39d904f149
2 changed files with 60 additions and 22 deletions

View File

@ -36,6 +36,10 @@
struct osmo_pcap_server; struct osmo_pcap_server;
#define STATE_INITIAL 0
#define STATE_DATA 1
struct osmo_pcap_conn { struct osmo_pcap_conn {
/* list of connections */ /* list of connections */
struct llist_head entry; struct llist_head entry;
@ -55,6 +59,12 @@ struct osmo_pcap_conn {
/* last time */ /* last time */
struct tm last_write; struct tm last_write;
/* read buffering */
int state;
int pend;
char buf[4096];
struct osmo_pcap_data *data;
}; };
struct osmo_pcap_server { struct osmo_pcap_server {

View File

@ -167,49 +167,76 @@ struct osmo_pcap_conn *osmo_pcap_server_find(struct osmo_pcap_server *server,
conn->rem_fd.fd = -1; conn->rem_fd.fd = -1;
conn->local_fd = -1; conn->local_fd = -1;
conn->server = server; conn->server = server;
conn->data = (struct osmo_pcap_data *) &conn->buf[0];
llist_add_tail(&conn->entry, &server->conn); llist_add_tail(&conn->entry, &server->conn);
return 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; int rc;
rc = read(fd->fd, conn->buf, sizeof(*conn->data));
conn = fd->data; if (rc != sizeof(*conn->data)) {
data = (struct osmo_pcap_data *) &buf[0];
rc = read(fd->fd, buf, sizeof(*data));
if (rc != sizeof(*data)) {
LOGP(DSERVER, LOGL_ERROR, "Failed to read from %s\n", conn->name); LOGP(DSERVER, LOGL_ERROR, "Failed to read from %s\n", conn->name);
close_connection(conn); close_connection(conn);
return -1; return -1;
} }
data->len = ntohs(data->len); conn->data->len = ntohs(conn->data->len);
if (data->len > 2000) { if (conn->data->len > 2000) {
LOGP(DSERVER, LOGL_ERROR, "Unplausible result %u\n", data->len); LOGP(DSERVER, LOGL_ERROR, "Unplausible result %u\n", conn->data->len);
close_connection(conn); close_connection(conn);
return -1; return -1;
} }
rc = read(fd->fd, &data->data[0], data->len); conn->state = STATE_DATA;
if (rc != data->len) { 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, 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); close_connection(conn);
return -1; return -1;
} }
switch (data->type) { conn->pend -= rc;
case PKT_LINK_HDR: if (conn->pend < 0) {
link_data(conn, data); LOGP(DSERVER, LOGL_ERROR,
break; "Someone got the pending read wrong: %d\n", conn->pend);
case PKT_LINK_DATA: close_connection(conn);
write_data(conn, data); return -1;
break; } 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; return 0;
@ -232,6 +259,7 @@ static void new_connection(struct osmo_pcap_server *server,
client->rem_fd.data = client; client->rem_fd.data = client;
client->rem_fd.when = BSC_FD_READ; client->rem_fd.when = BSC_FD_READ;
client->rem_fd.cb = read_cb; client->rem_fd.cb = read_cb;
client->state = STATE_INITIAL;
} }
static int accept_cb(struct osmo_fd *fd, unsigned int when) static int accept_cb(struct osmo_fd *fd, unsigned int when)