mirror of https://gerrit.osmocom.org/osmo-pcap
osmo-pcap-server: Try to read the the data with a simple state machine
This commit is contained in:
parent
9df7dc5f69
commit
39d904f149
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue