forked from M-Labs/artiq
runtime/net_server: refactor to support multiple services
This commit is contained in:
parent
7f4490a543
commit
6ae41e6024
|
@ -127,11 +127,21 @@ static void network_init(void)
|
||||||
netif_set_link_up(&netif);
|
netif_set_link_up(&netif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct net_server_instance session_inst = {
|
||||||
|
.port = 1381,
|
||||||
|
.start = session_start,
|
||||||
|
.end = session_end,
|
||||||
|
.input = session_input,
|
||||||
|
.poll = session_poll,
|
||||||
|
.ack_consumed = session_ack_consumed,
|
||||||
|
.ack_sent = session_ack_sent
|
||||||
|
};
|
||||||
|
|
||||||
static void regular_main(void)
|
static void regular_main(void)
|
||||||
{
|
{
|
||||||
puts("Accepting sessions on Ethernet.");
|
puts("Accepting sessions on Ethernet.");
|
||||||
network_init();
|
network_init();
|
||||||
net_server_init();
|
net_server_init(&session_inst);
|
||||||
moninj_init();
|
moninj_init();
|
||||||
|
|
||||||
session_end();
|
session_end();
|
||||||
|
|
|
@ -13,22 +13,23 @@
|
||||||
#include <netif/etharp.h>
|
#include <netif/etharp.h>
|
||||||
#include <liteethif.h>
|
#include <liteethif.h>
|
||||||
|
|
||||||
#include "session.h"
|
|
||||||
#include "net_server.h"
|
#include "net_server.h"
|
||||||
|
|
||||||
struct net_server_connstate {
|
struct net_server_connstate {
|
||||||
|
struct net_server_instance *instance;
|
||||||
int magic_recognized;
|
int magic_recognized;
|
||||||
struct pbuf *rp;
|
struct pbuf *rp;
|
||||||
int rp_offset;
|
int rp_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct net_server_connstate *cs_new(void)
|
static struct net_server_connstate *cs_new(struct net_server_instance *instance)
|
||||||
{
|
{
|
||||||
struct net_server_connstate *cs;
|
struct net_server_connstate *cs;
|
||||||
|
|
||||||
cs = (struct net_server_connstate *)mem_malloc(sizeof(struct net_server_connstate));
|
cs = (struct net_server_connstate *)mem_malloc(sizeof(struct net_server_connstate));
|
||||||
if(!cs)
|
if(!cs)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
cs->instance = instance;
|
||||||
cs->magic_recognized = 0;
|
cs->magic_recognized = 0;
|
||||||
cs->rp = NULL;
|
cs->rp = NULL;
|
||||||
cs->rp_offset = 0;
|
cs->rp_offset = 0;
|
||||||
|
@ -49,15 +50,15 @@ static int magic_ok(struct net_server_connstate *cs)
|
||||||
return cs->magic_recognized >= 14;
|
return cs->magic_recognized >= 14;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct net_server_connstate *active_cs;
|
|
||||||
static struct tcp_pcb *active_pcb;
|
|
||||||
|
|
||||||
static void net_server_close(struct net_server_connstate *cs, struct tcp_pcb *pcb)
|
static void net_server_close(struct net_server_connstate *cs, struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
if(cs == active_cs) {
|
struct net_server_instance *instance;
|
||||||
session_end();
|
|
||||||
active_cs = NULL;
|
instance = cs->instance;
|
||||||
active_pcb = NULL;
|
if(cs == instance->open_session_cs) {
|
||||||
|
instance->end();
|
||||||
|
instance->open_session_cs = NULL;
|
||||||
|
instance->open_session_pcb = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pcb) {
|
if(pcb) {
|
||||||
|
@ -91,26 +92,32 @@ static err_t net_server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err
|
||||||
|
|
||||||
static err_t net_server_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
|
static err_t net_server_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
|
||||||
{
|
{
|
||||||
session_ack_sent(len);
|
struct net_server_connstate *cs;
|
||||||
|
|
||||||
|
cs = (struct net_server_connstate *)arg;
|
||||||
|
cs->instance->ack_sent(len);
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcp_pcb_service(void *arg, struct tcp_pcb *pcb)
|
static void tcp_pcb_service(void *arg, struct tcp_pcb *pcb)
|
||||||
{
|
{
|
||||||
struct net_server_connstate *cs;
|
struct net_server_connstate *cs;
|
||||||
|
struct net_server_instance *instance;
|
||||||
int remaining_in_pbuf;
|
int remaining_in_pbuf;
|
||||||
char *rpp;
|
char *rpp;
|
||||||
struct pbuf *next;
|
struct pbuf *next;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
cs = (struct net_server_connstate *)arg;
|
cs = (struct net_server_connstate *)arg;
|
||||||
|
instance = cs->instance;
|
||||||
|
|
||||||
|
/* Reader interface */
|
||||||
while(cs->rp) {
|
while(cs->rp) {
|
||||||
remaining_in_pbuf = cs->rp->len - cs->rp_offset;
|
remaining_in_pbuf = cs->rp->len - cs->rp_offset;
|
||||||
rpp = (char *)cs->rp->payload;
|
rpp = (char *)cs->rp->payload;
|
||||||
while(remaining_in_pbuf > 0) {
|
while(remaining_in_pbuf > 0) {
|
||||||
if(cs == active_cs) {
|
if(cs == instance->open_session_cs) {
|
||||||
r = session_input(&rpp[cs->rp_offset], remaining_in_pbuf);
|
r = instance->input(&rpp[cs->rp_offset], remaining_in_pbuf);
|
||||||
if(r > 0) {
|
if(r > 0) {
|
||||||
tcp_recved(pcb, r);
|
tcp_recved(pcb, r);
|
||||||
cs->rp_offset += r;
|
cs->rp_offset += r;
|
||||||
|
@ -123,11 +130,12 @@ static void tcp_pcb_service(void *arg, struct tcp_pcb *pcb)
|
||||||
if(rpp[cs->rp_offset] == net_server_magic[cs->magic_recognized]) {
|
if(rpp[cs->rp_offset] == net_server_magic[cs->magic_recognized]) {
|
||||||
cs->magic_recognized++;
|
cs->magic_recognized++;
|
||||||
if(magic_ok(cs)) {
|
if(magic_ok(cs)) {
|
||||||
if(active_cs)
|
if(instance->open_session_cs)
|
||||||
net_server_close(active_cs, active_pcb);
|
net_server_close(instance->open_session_cs,
|
||||||
session_start();
|
instance->open_session_pcb);
|
||||||
active_cs = cs;
|
instance->start();
|
||||||
active_pcb = pcb;
|
instance->open_session_cs = cs;
|
||||||
|
instance->open_session_pcb = pcb;
|
||||||
tcp_sent(pcb, net_server_sent);
|
tcp_sent(pcb, net_server_sent);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -150,6 +158,23 @@ static void tcp_pcb_service(void *arg, struct tcp_pcb *pcb)
|
||||||
cs->rp = NULL;
|
cs->rp = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Writer interface */
|
||||||
|
if(cs == instance->open_session_cs) {
|
||||||
|
void *data;
|
||||||
|
int len, sndbuf;
|
||||||
|
|
||||||
|
cs->instance->poll(&data, &len);
|
||||||
|
if(len > 0) {
|
||||||
|
sndbuf = tcp_sndbuf(pcb);
|
||||||
|
if(len > sndbuf)
|
||||||
|
len = sndbuf;
|
||||||
|
tcp_write(pcb, data, len, 0);
|
||||||
|
instance->ack_consumed(len);
|
||||||
|
}
|
||||||
|
if(len < 0)
|
||||||
|
net_server_close(cs, pcb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void net_server_err(void *arg, err_t err)
|
static void net_server_err(void *arg, err_t err)
|
||||||
|
@ -160,29 +185,33 @@ static void net_server_err(void *arg, err_t err)
|
||||||
net_server_close(cs, NULL);
|
net_server_close(cs, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct tcp_pcb *listen_pcb;
|
|
||||||
|
|
||||||
static err_t net_server_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
|
static err_t net_server_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||||
{
|
{
|
||||||
|
struct net_server_instance *instance;
|
||||||
struct net_server_connstate *cs;
|
struct net_server_connstate *cs;
|
||||||
|
|
||||||
cs = cs_new();
|
instance = (struct net_server_instance *)arg;
|
||||||
|
cs = cs_new(instance);
|
||||||
if(!cs)
|
if(!cs)
|
||||||
return ERR_MEM;
|
return ERR_MEM;
|
||||||
tcp_accepted(listen_pcb);
|
tcp_accepted(instance->listen_pcb);
|
||||||
tcp_arg(newpcb, cs);
|
tcp_arg(newpcb, cs);
|
||||||
tcp_recv(newpcb, net_server_recv);
|
tcp_recv(newpcb, net_server_recv);
|
||||||
tcp_err(newpcb, net_server_err);
|
tcp_err(newpcb, net_server_err);
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_server_init(void)
|
void net_server_init(struct net_server_instance *instance)
|
||||||
{
|
{
|
||||||
listen_pcb = tcp_new();
|
struct tcp_pcb *bind_pcb;
|
||||||
listen_pcb->so_options |= SOF_KEEPALIVE;
|
|
||||||
tcp_bind(listen_pcb, IP_ADDR_ANY, 1381);
|
bind_pcb = tcp_new();
|
||||||
listen_pcb = tcp_listen(listen_pcb);
|
bind_pcb->so_options |= SOF_KEEPALIVE;
|
||||||
tcp_accept(listen_pcb, net_server_accept);
|
tcp_bind(bind_pcb, IP_ADDR_ANY, instance->port);
|
||||||
|
|
||||||
|
instance->listen_pcb = tcp_listen(bind_pcb);
|
||||||
|
tcp_arg(instance->listen_pcb, instance);
|
||||||
|
tcp_accept(instance->listen_pcb, net_server_accept);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern struct tcp_pcb *tcp_active_pcbs;
|
extern struct tcp_pcb *tcp_active_pcbs;
|
||||||
|
@ -190,29 +219,17 @@ extern struct tcp_pcb *tcp_active_pcbs;
|
||||||
void net_server_service(void)
|
void net_server_service(void)
|
||||||
{
|
{
|
||||||
struct tcp_pcb *pcb;
|
struct tcp_pcb *pcb;
|
||||||
void *data;
|
|
||||||
int len, sndbuf;
|
|
||||||
|
|
||||||
/* Assume all active TCP PCBs with a non-NULL arg are our connections. */
|
/*
|
||||||
|
* Assume all active TCP PCBs with a non-NULL arg are our connections.
|
||||||
|
* lwip defines "active PCB" as being able to send/receive data.
|
||||||
|
*/
|
||||||
pcb = tcp_active_pcbs;
|
pcb = tcp_active_pcbs;
|
||||||
while(pcb) {
|
while(pcb) {
|
||||||
if(pcb->callback_arg)
|
if(pcb->callback_arg)
|
||||||
tcp_pcb_service(pcb->callback_arg, pcb);
|
tcp_pcb_service(pcb->callback_arg, pcb);
|
||||||
pcb = pcb->next;
|
pcb = pcb->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(active_cs) {
|
|
||||||
session_poll(&data, &len);
|
|
||||||
if(len > 0) {
|
|
||||||
sndbuf = tcp_sndbuf(active_pcb);
|
|
||||||
if(len > sndbuf)
|
|
||||||
len = sndbuf;
|
|
||||||
tcp_write(active_pcb, data, len, 0);
|
|
||||||
session_ack_consumed(len);
|
|
||||||
}
|
|
||||||
if(len < 0)
|
|
||||||
net_server_close(active_cs, active_pcb);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CSR_ETHMAC_BASE */
|
#endif /* CSR_ETHMAC_BASE */
|
||||||
|
|
|
@ -1,7 +1,26 @@
|
||||||
#ifndef __NET_SERVER_H
|
#ifndef __NET_SERVER_H
|
||||||
#define __NET_SERVER_H
|
#define __NET_SERVER_H
|
||||||
|
|
||||||
void net_server_init(void);
|
struct net_server_connstate;
|
||||||
|
struct tcp_pcb;
|
||||||
|
|
||||||
|
struct net_server_instance {
|
||||||
|
int port;
|
||||||
|
|
||||||
|
void (*start)(void);
|
||||||
|
void (*end)(void);
|
||||||
|
int (*input)(void *data, int length);
|
||||||
|
void (*poll)(void **data, int *length);
|
||||||
|
void (*ack_consumed)(int length);
|
||||||
|
void (*ack_sent)(int length);
|
||||||
|
|
||||||
|
/* internal use */
|
||||||
|
struct tcp_pcb *listen_pcb;
|
||||||
|
struct net_server_connstate *open_session_cs;
|
||||||
|
struct tcp_pcb *open_session_pcb;
|
||||||
|
};
|
||||||
|
|
||||||
|
void net_server_init(struct net_server_instance *instance);
|
||||||
void net_server_service(void);
|
void net_server_service(void);
|
||||||
|
|
||||||
#endif /* __NET_SERVER_H */
|
#endif /* __NET_SERVER_H */
|
||||||
|
|
Loading…
Reference in New Issue