mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
59a46e0e88
Conflicts: cpu/arm_common/hwtimer_cpu.c sys/include/vtimer.h sys/vtimer.c
169 lines
5.3 KiB
C
169 lines
5.3 KiB
C
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "vtimer.h"
|
|
#include "thread.h"
|
|
#include "semaphore.h"
|
|
#include "bordermultiplex.h"
|
|
#include "flowcontrol.h"
|
|
|
|
|
|
static int set_timeout(vtimer_t *timeout, long useconds, void *args);
|
|
static void sending_slot(void);
|
|
|
|
char sending_slot_stack[SENDING_SLOT_STACK_SIZE];
|
|
unsigned int sending_slot_pid;
|
|
|
|
flowcontrol_stat_t slwin_stat;
|
|
sem_t connection_established;
|
|
int16_t synack_seqnum = -1;
|
|
|
|
ipv6_addr_t init_threeway_handshake() {
|
|
border_syn_packet_t *syn;
|
|
msg_t m;
|
|
m.content.ptr = NULL;
|
|
msg_send(&m,border_get_serial_reader(),1);
|
|
msg_receive(&m);
|
|
|
|
syn = (border_syn_packet_t *)m.content.ptr;
|
|
border_conf_header_t *synack = (border_conf_header_t *)get_serial_out_buffer(0);
|
|
ipv6_addr_t addr;
|
|
memcpy(&addr, &(syn->addr), sizeof (ipv6_addr_t));
|
|
|
|
slwin_stat.next_exp = syn->next_seq_num;
|
|
slwin_stat.last_frame = syn->next_exp - 1;
|
|
slwin_stat.last_ack = slwin_stat.last_frame;
|
|
|
|
synack->empty = 0;
|
|
synack->type = BORDER_PACKET_CONF_TYPE;
|
|
synack->conftype = BORDER_CONF_SYNACK;
|
|
|
|
sending_slot_pid = thread_create(sending_slot_stack, SENDING_SLOT_STACK_SIZE, PRIORITY_MAIN-1, CREATE_SLEEPING, sending_slot, "sending slot");
|
|
flowcontrol_send_over_uart((border_packet_t *)synack, sizeof (border_conf_header_t));
|
|
|
|
synack_seqnum = synack->seq_num;
|
|
|
|
return addr;
|
|
}
|
|
|
|
ipv6_addr_t flowcontrol_init() {
|
|
int i;
|
|
|
|
sem_init(&slwin_stat.send_win_not_full,BORDER_SWS);
|
|
for(i = 0; i < BORDER_SWS; i++) {
|
|
slwin_stat.send_win[i].frame_len = 0;
|
|
}
|
|
memset(&slwin_stat.send_win,0, sizeof(struct send_slot) * BORDER_SWS);
|
|
|
|
for(i = 0; i < BORDER_RWS; i++) {
|
|
slwin_stat.recv_win[i].received = 0;
|
|
slwin_stat.recv_win[i].frame_len = 0;
|
|
}
|
|
memset(&slwin_stat.recv_win,0, sizeof(struct recv_slot) * BORDER_RWS);
|
|
|
|
return init_threeway_handshake();
|
|
}
|
|
|
|
static void sending_slot(void) {
|
|
msg_t m;
|
|
uint8_t seq_num;
|
|
struct send_slot *slot;
|
|
border_packet_t *tmp;
|
|
|
|
while(1) {
|
|
msg_receive(&m);
|
|
seq_num = *((uint8_t *)m.content.ptr);
|
|
slot = &(slwin_stat.send_win[seq_num % BORDER_SWS]);
|
|
tmp = (border_packet_t*) slot->frame;
|
|
|
|
if (seq_num == tmp->seq_num) {
|
|
writepacket(slot->frame,slot->frame_len);
|
|
|
|
if (set_timeout(&slot->timeout, BORDER_SL_TIMEOUT, (void*) m.content.ptr) != 0) {
|
|
printf("ERROR: Error invoking timeout timer\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int set_timeout(vtimer_t *timeout, long useconds, void *args) {
|
|
timex_t interval;
|
|
interval.seconds = useconds / 1000000;
|
|
interval.microseconds = (useconds % 1000000) * 1000;
|
|
|
|
return vtimer_set_msg(timeout, interval, sending_slot_pid, args);
|
|
}
|
|
|
|
static int in_window(uint8_t seq_num, uint8_t min, uint8_t max) {
|
|
uint8_t pos = seq_num - min;
|
|
uint8_t maxpos = max - min + 1;
|
|
return pos < maxpos;
|
|
}
|
|
|
|
void flowcontrol_send_over_uart(border_packet_t *packet, int len) {
|
|
struct send_slot *slot;
|
|
uint8_t args[] = {packet->seq_num};
|
|
|
|
sem_wait(&(slwin_stat.send_win_not_full));
|
|
packet->seq_num = ++slwin_stat.last_frame;
|
|
slot = &(slwin_stat.send_win[packet->seq_num % BORDER_SWS]);
|
|
memcpy(slot->frame, (uint8_t *)packet, len);
|
|
slot->frame_len = len;
|
|
if (set_timeout(&slot->timeout, BORDER_SL_TIMEOUT, (void *)args) != 0) {
|
|
printf("ERROR: Error invoking timeout timer\n");
|
|
return;
|
|
}
|
|
writepacket((uint8_t *)packet, len);
|
|
}
|
|
|
|
void send_ack(uint8_t seq_num) {
|
|
border_packet_t *packet = (border_packet_t *)get_serial_out_buffer(0);
|
|
packet->empty = 0;
|
|
packet->type = BORDER_PACKET_ACK_TYPE;
|
|
packet->seq_num = seq_num;
|
|
writepacket((uint8_t *)packet, sizeof (border_packet_t));
|
|
}
|
|
|
|
void flowcontrol_deliver_from_uart(border_packet_t *packet, int len) {
|
|
if (packet->type == BORDER_PACKET_ACK_TYPE) {
|
|
if (in_window(packet->seq_num, slwin_stat.last_ack+1, slwin_stat.last_frame)) {
|
|
if (synack_seqnum == packet->seq_num) {
|
|
synack_seqnum = -1;
|
|
sem_signal(&connection_established);
|
|
}
|
|
do {
|
|
struct send_slot *slot;
|
|
slot = &(slwin_stat.send_win[++slwin_stat.last_ack % BORDER_SWS]);
|
|
vtimer_remove(&slot->timeout);
|
|
memset(&slot->frame,0,BORDER_BUFFER_SIZE);
|
|
sem_signal(&slwin_stat.send_win_not_full);
|
|
} while (slwin_stat.last_ack != packet->seq_num);
|
|
}
|
|
} else {
|
|
struct recv_slot *slot;
|
|
|
|
slot = &(slwin_stat.recv_win[packet->seq_num % BORDER_RWS]);
|
|
if ( !in_window(packet->seq_num,
|
|
slwin_stat.next_exp,
|
|
slwin_stat.next_exp + BORDER_RWS - 1)) {
|
|
return;
|
|
}
|
|
|
|
memcpy(slot->frame, (uint8_t *)packet, len);
|
|
slot->received = 1;
|
|
|
|
if (packet->seq_num == slwin_stat.next_exp) {
|
|
while (slot->received) {
|
|
demultiplex((border_packet_t *)slot->frame, slot->frame_len);
|
|
memset(&slot->frame,0,BORDER_BUFFER_SIZE);
|
|
slot->received = 0;
|
|
slot = &slwin_stat.recv_win[++(slwin_stat.next_exp) % BORDER_RWS];
|
|
}
|
|
}
|
|
|
|
send_ack(slwin_stat.next_exp - 1);
|
|
}
|
|
}
|