@@ -10,6 +10,12 @@ initiator does not receive a response to it's query, it will resend the | |||||
request until it does. It is required that the responder be able to | request until it does. It is required that the responder be able to | ||||
detect this, and resend the last response. | detect this, and resend the last response. | ||||
The respondent will cache message responses after the session has been | |||||
confirmed, but before that, it is unneccessary, as there is no harm to | |||||
reprocess the messages. The more complicated part is dealing w/ a | |||||
missed confirmed reply, as the state will need to be back tracked (saved) | |||||
to decode the repeated confirm request. | |||||
both sides: | both sides: | ||||
meta-AD('com.funkthat.lora.irrigation.<type>.v0.0.1') | meta-AD('com.funkthat.lora.irrigation.<type>.v0.0.1') | ||||
key(<defined by type>) | key(<defined by type>) | ||||
@@ -5,6 +5,19 @@ static const size_t MAC_LEN = 8; | |||||
static const size_t CHALLENGE_LEN = 16; | static const size_t CHALLENGE_LEN = 16; | ||||
static const uint8_t domain[] = "com.funkthat.lora.irrigation.shared.v0.0.1"; | static const uint8_t domain[] = "com.funkthat.lora.irrigation.shared.v0.0.1"; | ||||
static int comms_pktbuf_equal(struct pktbuf a, struct pktbuf b); | |||||
/* returns 1 if equal, 0 if not equal */ | |||||
static int | |||||
comms_pktbuf_equal(struct pktbuf a, struct pktbuf b) | |||||
{ | |||||
if (a.pktlen != b.pktlen) | |||||
return 0; | |||||
return memcmp(a.pkt, b.pkt, a.pktlen) == 0; | |||||
} | |||||
size_t | size_t | ||||
_strobe_state_size() | _strobe_state_size() | ||||
{ | { | ||||
@@ -48,6 +61,14 @@ comms_process(struct comms_state *cs, struct pktbuf pbin, struct pktbuf *pbout) | |||||
struct pktbuf pbmsg, pbrep; | struct pktbuf pbmsg, pbrep; | ||||
ssize_t cnt, ret, msglen; | ssize_t cnt, ret, msglen; | ||||
/* if the current msg matches the previous */ | |||||
if (comms_pktbuf_equal(pbin, cs->cs_prevmsg)) { | |||||
/* send the previous response */ | |||||
pbout->pktlen = cs->cs_prevmsgresp.pktlen; | |||||
memcpy(pbout->pkt, cs->cs_prevmsgresp.pkt, pbout->pktlen); | |||||
return; | |||||
} | |||||
strobe_attach_buffer(&cs->cs_state, pbin.pkt, pbin.pktlen); | strobe_attach_buffer(&cs->cs_state, pbin.pkt, pbin.pktlen); | ||||
cnt = strobe_get(&cs->cs_state, APP_CIPHERTEXT, buf, pbin.pktlen - | cnt = strobe_get(&cs->cs_state, APP_CIPHERTEXT, buf, pbin.pktlen - | ||||
@@ -108,8 +129,23 @@ comms_process(struct comms_state *cs, struct pktbuf pbin, struct pktbuf *pbout) | |||||
ret += strobe_put(&cs->cs_state, MAC, NULL, MAC_LEN); | ret += strobe_put(&cs->cs_state, MAC, NULL, MAC_LEN); | ||||
break; | break; | ||||
} | |||||
} | |||||
} | } | ||||
/* set the output buffer length */ | |||||
pbout->pktlen = ret; | pbout->pktlen = ret; | ||||
if (ret != 0) { | |||||
/* we accepted a new message store it */ | |||||
/* store the req */ | |||||
cs->cs_prevmsg.pkt = cs->cs_prevmsgbuf; | |||||
cs->cs_prevmsg.pktlen = pbin.pktlen; | |||||
memcpy(cs->cs_prevmsg.pkt, pbin.pkt, pbin.pktlen); | |||||
/* store the response */ | |||||
cs->cs_prevmsgresp.pkt = cs->cs_prevmsgrespbuf; | |||||
cs->cs_prevmsgresp.pktlen = pbout->pktlen; | |||||
memcpy(cs->cs_prevmsgresp.pkt, pbout->pkt, pbout->pktlen); | |||||
} | |||||
} | } |
@@ -3,6 +3,8 @@ | |||||
#include <strobe.h> | #include <strobe.h> | ||||
#define COMMS_MAXMSG 64 | |||||
struct pktbuf { | struct pktbuf { | ||||
uint8_t *pkt; | uint8_t *pkt; | ||||
uint16_t pktlen; | uint16_t pktlen; | ||||
@@ -23,6 +25,12 @@ struct comms_state { | |||||
strobe_s cs_start; /* special starting state cache */ | strobe_s cs_start; /* special starting state cache */ | ||||
process_msgfunc_t cs_procmsg; | process_msgfunc_t cs_procmsg; | ||||
struct pktbuf cs_prevmsg; | |||||
struct pktbuf cs_prevmsgresp; | |||||
uint8_t cs_prevmsgbuf[COMMS_MAXMSG]; | |||||
uint8_t cs_prevmsgrespbuf[COMMS_MAXMSG]; | |||||
}; | }; | ||||
size_t _strobe_state_size(); | size_t _strobe_state_size(); | ||||
@@ -311,6 +311,19 @@ class TestLORANode(unittest.IsolatedAsyncioTestCase): | |||||
_self.assertEqual(expectlen, | _self.assertEqual(expectlen, | ||||
outbuf.pktlen) | outbuf.pktlen) | ||||
# save what was originally replied | |||||
origmsg = outbuf._from() | |||||
# pretend that the reply didn't make it | |||||
r = make_pktbuf(gb) | |||||
outbuf = make_pktbuf(outbytes) | |||||
lora_comms.comms_process(commstate, r, | |||||
outbuf) | |||||
# make sure that the reply matches previous | |||||
_self.assertEqual(origmsg, outbuf._from()) | |||||
# pass the reply back | # pass the reply back | ||||
await self.put(outbytes[:outbuf.pktlen]) | await self.put(outbytes[:outbuf.pktlen]) | ||||
@@ -1,5 +1,5 @@ | |||||
from ctypes import Structure, POINTER, CFUNCTYPE, pointer | from ctypes import Structure, POINTER, CFUNCTYPE, pointer | ||||
from ctypes import c_uint8, c_uint16, c_ssize_t, c_size_t, c_uint64 | |||||
from ctypes import c_uint8, c_uint16, c_ssize_t, c_size_t, c_uint64, c_int | |||||
from ctypes import CDLL | from ctypes import CDLL | ||||
class PktBuf(Structure): | class PktBuf(Structure): | ||||
@@ -21,7 +21,6 @@ def make_pktbuf(s): | |||||
if isinstance(s, bytearray): | if isinstance(s, bytearray): | ||||
obj = s | obj = s | ||||
pb.pkt = pointer(c_uint8.from_buffer(s)) | pb.pkt = pointer(c_uint8.from_buffer(s)) | ||||
#print('mp:', repr(pb.pkt)) | |||||
else: | else: | ||||
obj = (c_uint8 * len(s))(*s) | obj = (c_uint8 * len(s))(*s) | ||||
pb.pkt = obj | pb.pkt = obj | ||||
@@ -44,8 +43,15 @@ class CommsState(Structure): | |||||
_fields_ = [ | _fields_ = [ | ||||
# The alignment of these may be off | # The alignment of these may be off | ||||
('cs_state', c_uint64 * _strobe_state_u64_cnt), | ('cs_state', c_uint64 * _strobe_state_u64_cnt), | ||||
('cs_comm_state', c_int), | |||||
('cs_start', c_uint64 * _strobe_state_u64_cnt), | ('cs_start', c_uint64 * _strobe_state_u64_cnt), | ||||
('cs_procmsg', process_msgfunc_t), | ('cs_procmsg', process_msgfunc_t), | ||||
('cs_prevmsg', PktBuf), | |||||
('cs_prevmsgresp', PktBuf), | |||||
('cs_prevmsgbuf', c_uint8 * 64), | |||||
('cs_prevmsgrespbuf', c_uint8 * 64), | |||||
] | ] | ||||
for func, ret, args in [ | for func, ret, args in [ | ||||