mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-18 20:57:56 +00:00
refactored packet radio code mostly into separate file.
began writing stateful packet decoder.
This commit is contained in:
parent
70af7fae0d
commit
190a5e693f
@ -200,6 +200,7 @@ ATOM(char, overlayinterfaces, 0, cf_opt_char_boolean,, "")
|
||||
ATOM(char, broadcasts, 0, cf_opt_char_boolean,, "")
|
||||
ATOM(char, packettx, 0, cf_opt_char_boolean,, "")
|
||||
ATOM(char, packetrx, 0, cf_opt_char_boolean,, "")
|
||||
ATOM(char, packetradio, 0, cf_opt_char_boolean,, "")
|
||||
ATOM(char, packetconstruction, 0, cf_opt_char_boolean,, "")
|
||||
ATOM(char, rhizome, 0, cf_opt_char_boolean,, "")
|
||||
ATOM(char, rhizome_tx, 0, cf_opt_char_boolean,, "")
|
||||
|
@ -412,7 +412,7 @@ overlay_interface_init(const char *name, struct in_addr src_addr, struct in_addr
|
||||
return WHYF("dummy or packet radio interface file name overrun: %s", alloca_str_toprint(strbuf_str(d)));
|
||||
}
|
||||
if ((interface->alarm.poll.fd = open(dummyfile,O_APPEND|O_RDWR)) < 1) {
|
||||
return WHYF("could not open dummy or packet radio interface file %s for append", dummyfile);
|
||||
return WHYF("could not open dummy or packet radio interface file %s for append (errno=%d)", dummyfile,errno);
|
||||
}
|
||||
|
||||
bzero(&interface->address, sizeof(interface->address));
|
||||
@ -548,59 +548,22 @@ struct dummy_packet{
|
||||
int payload_length;
|
||||
|
||||
/* TODO ? ;
|
||||
half-power beam height (uint16)
|
||||
half-power beam width (uint16)
|
||||
range in metres, centre beam (uint32)
|
||||
latitude (uint32)
|
||||
longitude (uint32)
|
||||
X/Z direction (uint16)
|
||||
Y direction (uint16)
|
||||
speed in metres per second (uint16)
|
||||
TX frequency in Hz, uncorrected for doppler (which must be done at the receiving end to take into account
|
||||
relative motion)
|
||||
coding method (use for doppler response etc) null terminated string
|
||||
half-power beam height (uint16)
|
||||
half-power beam width (uint16)
|
||||
range in metres, centre beam (uint32)
|
||||
latitude (uint32)
|
||||
longitude (uint32)
|
||||
X/Z direction (uint16)
|
||||
Y direction (uint16)
|
||||
speed in metres per second (uint16)
|
||||
TX frequency in Hz, uncorrected for doppler (which must be done at the receiving end to take into account
|
||||
relative motion)
|
||||
coding method (use for doppler response etc) null terminated string
|
||||
*/
|
||||
|
||||
unsigned char payload[1400];
|
||||
};
|
||||
|
||||
void overlay_packetradio_poll(struct sched_ent *alarm)
|
||||
{
|
||||
overlay_interface *interface = (overlay_interface *)alarm;
|
||||
time_ms_t now = gettime_ms();
|
||||
|
||||
// We will almost certainly support more than one type of packet radio
|
||||
// so lets parameterise this.
|
||||
switch(1) {
|
||||
case 1:
|
||||
// Read data from the serial port
|
||||
break;
|
||||
}
|
||||
|
||||
// tick the interface
|
||||
if (interface->tick_ms>0 &&
|
||||
(interface->last_tick_ms == -1 || now >= interface->last_tick_ms + interface->tick_ms)) {
|
||||
// tick the interface
|
||||
overlay_route_queue_advertisements(interface);
|
||||
interface->last_tick_ms=now;
|
||||
}
|
||||
|
||||
unsigned char buffer[8192];
|
||||
ssize_t nread = read(alarm->poll.fd, buffer,8192);
|
||||
if (nread == -1){
|
||||
WHY_perror("read");
|
||||
return;
|
||||
}
|
||||
if (nread>0) {
|
||||
buffer[8191]=0;
|
||||
if (nread<8192) buffer[nread]=0;
|
||||
DEBUGF("Read '%s'",buffer);
|
||||
}
|
||||
|
||||
schedule(alarm);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
void overlay_dummy_poll(struct sched_ent *alarm)
|
||||
{
|
||||
@ -618,8 +581,8 @@ void overlay_dummy_poll(struct sched_ent *alarm)
|
||||
|
||||
if (interface->recv_offset >= length) {
|
||||
/* if there's no input, while we want to check for more soon,
|
||||
we need to allow all other low priority alarms to fire first,
|
||||
otherwise we'll dominate the scheduler without accomplishing anything */
|
||||
we need to allow all other low priority alarms to fire first,
|
||||
otherwise we'll dominate the scheduler without accomplishing anything */
|
||||
alarm->alarm = gettime_ms() + 5;
|
||||
if (interface->last_tick_ms != -1 && alarm->alarm > interface->last_tick_ms + interface->tick_ms)
|
||||
alarm->alarm = interface->last_tick_ms + interface->tick_ms;
|
||||
@ -648,7 +611,7 @@ void overlay_dummy_poll(struct sched_ent *alarm)
|
||||
|
||||
if (((!interface->drop_unicasts) && memcmp(&packet.dst_addr, &interface->address, sizeof(packet.dst_addr))==0) ||
|
||||
((!interface->drop_broadcasts) &&
|
||||
memcmp(&packet.dst_addr, &interface->broadcast_address, sizeof(packet.dst_addr))==0)){
|
||||
memcmp(&packet.dst_addr, &interface->broadcast_address, sizeof(packet.dst_addr))==0)){
|
||||
|
||||
if (packetOkOverlay(interface, packet.payload, packet.payload_length, -1,
|
||||
(struct sockaddr*)&packet.src_addr, sizeof(packet.src_addr))) {
|
||||
|
149
overlay_packetradio.c
Normal file
149
overlay_packetradio.c
Normal file
@ -0,0 +1,149 @@
|
||||
#include "serval.h"
|
||||
#include "conf.h"
|
||||
|
||||
/* interface decoder states. broadly based on RFC1055 */
|
||||
#define DC_NORMAL 0
|
||||
#define DC_ESC 1
|
||||
#define DC_END 2
|
||||
|
||||
/* SLIP-style escape characters used for serial packet radio interfaces */
|
||||
#define SLIP_END 0300
|
||||
#define SLIP_ESC 0333
|
||||
#define SLIP_ESC_END 0334
|
||||
#define SLIP_ESC_ESC 0335
|
||||
|
||||
int overlay_rx_packet_complete(overlay_interface *interface)
|
||||
{
|
||||
if (interface->recv_offset) {
|
||||
// dispatch received packet
|
||||
if (packetOkOverlay(interface, interface->buffer, interface->recv_offset, -1,
|
||||
NULL,0)) {
|
||||
if (config.debug.packetradio)
|
||||
WARN("Corrupted or unsupported packet from packet radio interface");
|
||||
}
|
||||
}
|
||||
interface->recv_offset=0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_rx_packet_append_byte(overlay_interface *interface,unsigned char byte)
|
||||
{
|
||||
// Make sure we don't put the data outside the RX buffer
|
||||
if (interface->recv_offset<0
|
||||
||interface->recv_offset>=OVERLAY_INTERFACE_RX_BUFFER_SIZE)
|
||||
interface->recv_offset=0;
|
||||
|
||||
interface->buffer[interface->recv_offset++]=byte;
|
||||
if (interface->recv_offset==OVERLAY_INTERFACE_RX_BUFFER_SIZE) {
|
||||
// packet fills buffer. Who knows, we might be able to decode what we
|
||||
// have of it.
|
||||
return overlay_rx_packet_complete(interface);
|
||||
}
|
||||
|
||||
if (config.debug.packetradio) DEBUGF("RXd %d bytes",interface->recv_offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void overlay_packetradio_poll(struct sched_ent *alarm)
|
||||
{
|
||||
overlay_interface *interface = (overlay_interface *)alarm;
|
||||
time_ms_t now = gettime_ms();
|
||||
|
||||
// Read data from the serial port
|
||||
// We will almost certainly support more than one type of packet radio
|
||||
// so lets parameterise this.
|
||||
switch(1) {
|
||||
case 1:
|
||||
{
|
||||
unsigned char buffer[OVERLAY_INTERFACE_RX_BUFFER_SIZE];
|
||||
ssize_t nread = read(alarm->poll.fd, buffer, OVERLAY_INTERFACE_RX_BUFFER_SIZE);
|
||||
if (nread == -1){
|
||||
WHY_perror("read");
|
||||
return;
|
||||
}
|
||||
if (nread>0) {
|
||||
/*
|
||||
Examine received bytes for end of packet marker.
|
||||
The challenge is that we need to make sure that the packet encapsulation
|
||||
is self-synchronising in the event that a data error occurs (including
|
||||
failure to receive an arbitrary number of bytes).
|
||||
For now we will reuse the antiquated and sub-optimal method described in
|
||||
RFC1055 for SLIP, but with a couple of tweaks to reduce byte wastage when
|
||||
encountering ESC and END characters in packets.
|
||||
*/
|
||||
int i;
|
||||
for(i=0;i<nread;i++)
|
||||
{
|
||||
switch (interface->decoder_state) {
|
||||
case DC_ESC:
|
||||
// escaped character
|
||||
switch(buffer[i]) {
|
||||
case SLIP_ESC_END: // escaped END byte
|
||||
overlay_rx_packet_append_byte(interface,SLIP_END); break;
|
||||
case SLIP_ESC_ESC: // escaped escape character
|
||||
overlay_rx_packet_append_byte(interface,SLIP_ESC); break;
|
||||
default: /* unknown escape character
|
||||
This is where the inefficiency comes, because
|
||||
we don't use the spare bits.
|
||||
We can reduce the inefficiency by making ESC <otherbyte>
|
||||
mean literally that. */
|
||||
overlay_rx_packet_append_byte(interface,SLIP_ESC);
|
||||
overlay_rx_packet_append_byte(interface,buffer[i]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case DC_END:
|
||||
// character preceeded by END character
|
||||
switch(buffer[i]) {
|
||||
case SLIP_ESC_END:
|
||||
overlay_rx_packet_complete(interface);
|
||||
break;
|
||||
default:
|
||||
overlay_rx_packet_append_byte(interface,SLIP_END);
|
||||
overlay_rx_packet_append_byte(interface,buffer[i]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// non-escape character
|
||||
switch(buffer[i]) {
|
||||
case SLIP_ESC:
|
||||
interface->decoder_state=DC_ESC; break;
|
||||
case SLIP_END:
|
||||
interface->decoder_state=DC_END; break;
|
||||
default:
|
||||
overlay_rx_packet_append_byte(interface,buffer[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// tick the interface
|
||||
if (interface->tick_ms>0 &&
|
||||
(interface->last_tick_ms == -1 || now >= interface->last_tick_ms + interface->tick_ms)) {
|
||||
// tick the interface
|
||||
overlay_route_queue_advertisements(interface);
|
||||
interface->last_tick_ms=now;
|
||||
}
|
||||
|
||||
unsigned char buffer[8192];
|
||||
ssize_t nread = read(alarm->poll.fd, buffer,8192);
|
||||
if (nread == -1){
|
||||
WHY_perror("read");
|
||||
return;
|
||||
}
|
||||
if (nread>0) {
|
||||
buffer[8191]=0;
|
||||
if (nread<8192) buffer[nread]=0;
|
||||
DEBUGF("Read '%s'",buffer);
|
||||
}
|
||||
|
||||
schedule(alarm);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
12
serval.h
12
serval.h
@ -350,11 +350,19 @@ extern int overlayMode;
|
||||
#define INTERFACE_STATE_DOWN 2
|
||||
#define INTERFACE_STATE_DETECTING 3
|
||||
|
||||
// Specify the size of the receive buffer.
|
||||
// This effectively sets the MRU for packet radio interfaces
|
||||
// where we have to buffer packets on the receive side
|
||||
#define OVERLAY_INTERFACE_RX_BUFFER_SIZE 2048
|
||||
|
||||
typedef struct overlay_interface {
|
||||
struct sched_ent alarm;
|
||||
char name[256];
|
||||
int recv_offset;
|
||||
int fileP; // dummyP
|
||||
unsigned char buffer[OVERLAY_INTERFACE_RX_BUFFER_SIZE];
|
||||
int recv_offset; /* either dummy file offset or number of bytes in RX buffer
|
||||
for packet radio interfaces */
|
||||
char decoder_state; // decoder state for packet radio interfaces
|
||||
int fileP; // non-zero for dummy and packet radio serial interfaces
|
||||
char drop_broadcasts;
|
||||
char drop_unicasts;
|
||||
int port;
|
||||
|
@ -31,6 +31,7 @@ SERVAL_SOURCES = $(SERVAL_BASE)audiodevices.c \
|
||||
$(SERVAL_BASE)overlay_buffer.c \
|
||||
$(SERVAL_BASE)overlay_interface.c \
|
||||
$(SERVAL_BASE)overlay_link.c \
|
||||
$(SERVAL_BASE)overlay_packetradio.c \
|
||||
$(SERVAL_BASE)overlay_queue.c \
|
||||
$(SERVAL_BASE)overlay_mdp.c \
|
||||
$(SERVAL_BASE)overlay_mdp_services.c \
|
||||
|
Loading…
Reference in New Issue
Block a user