Browse Source
Currently, the tcp and udp implementations are bound to each other in a module called *destiny*. Thus, when using only one of them then the other one gets also compiled into the binary and initialized, which results in unnecessary RAM usage and workload for the CPU. The approach in this PR defines a common module named *socket_base*, which contains functions used by the posix layer. Compiled by it's own, those functions return negative error codes, to symbolize upper layers that they are not supported. When also including the modules *udp* or *tcp* respectively, functions from *socket_base* get overwritten with the correct functionality. Defining *udp* or *tcp* in a Makefile also includes *socket_base*. Defining *pnet* in a Makefile also includes *socket_base*.dev/timer

41 changed files with 1896 additions and 1613 deletions
@ -1 +1,2 @@
|
||||
PSEUDOMODULES += defaulttransceiver
|
||||
PSEUDOMODULES += transport_layer
|
||||
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2013, 2014 INRIA. |
||||
* |
||||
* This file is subject to the terms and conditions of the GNU Lesser |
||||
* General Public License v2.1. See the file LICENSE in the top level |
||||
* directory for more details. |
||||
*/ |
||||
|
||||
/**
|
||||
* @defgroup tcp TCP implementation |
||||
* @ingroup net |
||||
* @brief This module implements the TCP transport layer protocol. |
||||
* This includes an (experimental) 6LoWPAN TCP header ompression. |
||||
* @see <a href="http://tools.ietf.org/html/draft-aayadi-6lowpan-tcphc-01"> |
||||
* RFC draft-aayadi-6lowpan-tcphc-01 - TCP header compression for |
||||
* 6LoWPAN |
||||
* </a> |
||||
* @{ |
||||
* @file |
||||
* @brief tcp functions |
||||
* @author Oliver Gesch <oliver.gesch@googlemail.com> |
||||
* @author Martin Lenders <mlenders@inf.fu-berlin.de> |
||||
* @author Cenk Gündoğan <cnkgndgn@gmail.com> |
||||
*/ |
||||
|
||||
#ifndef TCP_H |
||||
#define TCP_H |
||||
|
||||
#include "socket_base/in.h" |
||||
#include "socket_base/socket.h" |
||||
#include "socket_base/types.h" |
||||
|
||||
/**
|
||||
* Initializes tcp. |
||||
* |
||||
* @return 0 on success, other else. |
||||
*/ |
||||
int tcp_init_transport_layer(void); |
||||
|
||||
#endif /* TCP_H */ |
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2013, 2014 INRIA. |
||||
* |
||||
* This file is subject to the terms and conditions of the GNU Lesser |
||||
* General Public License v2.1. See the file LICENSE in the top level |
||||
* directory for more details. |
||||
*/ |
||||
|
||||
/**
|
||||
* @defgroup tcp UDP implementation |
||||
* @ingroup net |
||||
* @brief This module implements the transport layer protocol UDP. |
||||
* This includes 6LoWPAN UDP header compression. |
||||
* @see <a href="http://tools.ietf.org/html/rfc6282#section-4.3"> |
||||
* RFC 6282 - Compression Format for IPv6 Datagrams over |
||||
* IEEE 802.15.4-Based Networks - UDP Header Compression |
||||
* </a> |
||||
* @{ |
||||
* @file |
||||
* @brief udp functions |
||||
* @author Oliver Gesch <oliver.gesch@googlemail.com> |
||||
* @author Martin Lenders <mlenders@inf.fu-berlin.de> |
||||
* @author Cenk Gündoğan <cnkgndgn@gmail.com> |
||||
*/ |
||||
|
||||
#ifndef UDP_H |
||||
#define UDP_H |
||||
|
||||
#include "socket_base/in.h" |
||||
#include "socket_base/socket.h" |
||||
#include "socket_base/types.h" |
||||
|
||||
/**
|
||||
* Initializes udp. |
||||
* |
||||
* @return 0 on success, other else. |
||||
*/ |
||||
int udp_init_transport_layer(void); |
||||
|
||||
#endif /* UDP_H */ |
@ -1,81 +0,0 @@
|
||||
/**
|
||||
* Destiny transport layer implementation |
||||
* |
||||
* Copyright (C) 2013 INRIA. |
||||
* |
||||
* This file is subject to the terms and conditions of the GNU Lesser |
||||
* General Public License v2.1. See the file LICENSE in the top level |
||||
* directory for more details. |
||||
* |
||||
* @ingroup destiny |
||||
* @{ |
||||
* @file destiny.c |
||||
* @brief transpor layer functions |
||||
* @author Oliver Gesch <oliver.gesch@googlemail.com> |
||||
* @} |
||||
*/ |
||||
|
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
#include <stdlib.h> |
||||
|
||||
#include "thread.h" |
||||
|
||||
#include "destiny.h" |
||||
#include "vtimer.h" |
||||
|
||||
#include "socket.h" |
||||
#include "tcp.h" |
||||
#include "tcp_timer.h" |
||||
#include "udp.h" |
||||
|
||||
char tcp_stack_buffer[TCP_STACK_SIZE]; |
||||
char udp_stack_buffer[UDP_STACK_SIZE]; |
||||
|
||||
char tcp_timer_stack[TCP_TIMER_STACKSIZE]; |
||||
|
||||
int destiny_init_transport_layer(void) |
||||
{ |
||||
printf("Initializing transport layer packages. Size of socket_type: %u\n", |
||||
(unsigned int) sizeof(socket_internal_t)); |
||||
/* SOCKETS */ |
||||
memset(sockets, 0, MAX_SOCKETS * sizeof(socket_internal_t)); |
||||
|
||||
/* UDP */ |
||||
kernel_pid_t udp_thread_pid = thread_create(udp_stack_buffer, UDP_STACK_SIZE, |
||||
PRIORITY_MAIN, CREATE_STACKTEST, |
||||
udp_packet_handler, NULL, "udp_packet_handler"); |
||||
|
||||
if (udp_thread_pid == KERNEL_PID_UNDEF) { |
||||
return -1; |
||||
} |
||||
|
||||
ipv6_register_next_header_handler(IPV6_PROTO_NUM_UDP, udp_thread_pid); |
||||
|
||||
/* TCP */ |
||||
timex_t now; |
||||
vtimer_now(&now); |
||||
srand(timex_uint64(now)); |
||||
#ifdef TCP_HC |
||||
printf("TCP_HC enabled!\n"); |
||||
global_context_counter = rand(); |
||||
#endif |
||||
global_sequence_counter = rand(); |
||||
|
||||
kernel_pid_t tcp_thread_pid = thread_create(tcp_stack_buffer, TCP_STACK_SIZE, |
||||
PRIORITY_MAIN, CREATE_STACKTEST, |
||||
tcp_packet_handler, NULL, "tcp_packet_handler"); |
||||
|
||||
if (tcp_thread_pid == KERNEL_PID_UNDEF) { |
||||
return -1; |
||||
} |
||||
|
||||
ipv6_register_next_header_handler(IPV6_PROTO_NUM_TCP, tcp_thread_pid); |
||||
|
||||
if (thread_create(tcp_timer_stack, TCP_TIMER_STACKSIZE, PRIORITY_MAIN + 1, |
||||
CREATE_STACKTEST, tcp_general_timer, NULL, "tcp_general_timer") < 0) { |
||||
return -1; |
||||
} |
||||
|
||||
return 0; |
||||
} |
@ -1,412 +0,0 @@
|
||||
/**
|
||||
* Destiny TCP implementation |
||||
* |
||||
* Copyright (C) 2013 INRIA. |
||||
* |
||||
* This file is subject to the terms and conditions of the GNU Lesser |
||||
* General Public License v2.1. See the file LICENSE in the top level |
||||
* directory for more details. |
||||
* |
||||
* @ingroup destiny |
||||
* @{ |
||||
* @file tcp.c |
||||
* @brief TCP implementation |
||||
* @author Oliver Gesch <oliver.gesch@googlemail.com> |
||||
* @} |
||||
*/ |
||||
|
||||
#include <inttypes.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include "sixlowpan.h" |
||||
#include "thread.h" |
||||
#include "vtimer.h" |
||||
|
||||
#include "destiny/in.h" |
||||
|
||||
#include "net_help.h" |
||||
|
||||
#include "msg_help.h" |
||||
#include "socket.h" |
||||
#include "tcp_hc.h" |
||||
#include "tcp_timer.h" |
||||
|
||||
#include "tcp.h" |
||||
|
||||
#ifdef TCP_HC |
||||
mutex_t global_context_counter_mutex; |
||||
uint8_t global_context_counter; |
||||
#endif |
||||
|
||||
mutex_t global_sequence_counter_mutex; |
||||
uint32_t global_sequence_counter; |
||||
|
||||
void printTCPHeader(tcp_hdr_t *tcp_header) |
||||
{ |
||||
printf("\nBEGIN: TCP HEADER\n"); |
||||
printf("ack_nr: %" PRIu32 "\n", tcp_header->ack_nr); |
||||
printf("checksum: %i\n", tcp_header->checksum); |
||||
printf("data_offset: %i\n", tcp_header->data_offset); |
||||
printf("dst_port: %i\n", tcp_header->dst_port); |
||||
printf("reserved_flags: %i\n", tcp_header->reserved_flags); |
||||
printf("seq_nr: %" PRIu32 "\n", tcp_header->seq_nr); |
||||
printf("src_port: %i\n", tcp_header->src_port); |
||||
printf("urg_pointer: %i\n", tcp_header->urg_pointer); |
||||
printf("window: %i\n", tcp_header->window); |
||||
printf("END: TCP HEADER\n"); |
||||
} |
||||
|
||||
void printArrayRange_tcp(uint8_t *udp_header, uint16_t len) |
||||
{ |
||||
int i = 0; |
||||
printf("-------------MEMORY-------------\n"); |
||||
|
||||
for (i = 0; i < len; i++) { |
||||
printf("%#x ", *(udp_header + i)); |
||||
} |
||||
|
||||
printf("-------------MEMORY-------------\n"); |
||||
} |
||||
|
||||
uint16_t tcp_csum(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header) |
||||
{ |
||||
uint16_t sum; |
||||
uint16_t len = NTOHS(ipv6_header->length); |
||||
|
||||
sum = len + IPPROTO_TCP; |
||||
sum = csum(sum, (uint8_t *)&ipv6_header->srcaddr, 2 * sizeof(ipv6_addr_t)); |
||||
sum = csum(sum, (uint8_t *)tcp_header, len); |
||||
return (sum == 0) ? 0xffff : HTONS(sum); |
||||
} |
||||
|
||||
uint8_t handle_payload(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, |
||||
socket_internal_t *tcp_socket, uint8_t *payload) |
||||
{ |
||||
(void) tcp_header; |
||||
|
||||
msg_t m_send_tcp, m_recv_tcp; |
||||
uint8_t tcp_payload_len = NTOHS(ipv6_header->length) - TCP_HDR_LEN; |
||||
uint8_t acknowledged_bytes = 0; |
||||
|
||||
if (tcp_payload_len > tcp_socket->socket_values.tcp_control.rcv_wnd) { |
||||
mutex_lock(&tcp_socket->tcp_buffer_mutex); |
||||
memcpy(tcp_socket->tcp_input_buffer, payload, |
||||
tcp_socket->socket_values.tcp_control.rcv_wnd); |
||||
acknowledged_bytes = tcp_socket->socket_values.tcp_control.rcv_wnd; |
||||
tcp_socket->socket_values.tcp_control.rcv_wnd = 0; |
||||
tcp_socket->tcp_input_buffer_end = tcp_socket->tcp_input_buffer_end + |
||||
tcp_socket->socket_values.tcp_control.rcv_wnd; |
||||
mutex_unlock(&tcp_socket->tcp_buffer_mutex); |
||||
} |
||||
else { |
||||
mutex_lock(&tcp_socket->tcp_buffer_mutex); |
||||
memcpy(tcp_socket->tcp_input_buffer, payload, tcp_payload_len); |
||||
tcp_socket->socket_values.tcp_control.rcv_wnd = |
||||
tcp_socket->socket_values.tcp_control.rcv_wnd - tcp_payload_len; |
||||
acknowledged_bytes = tcp_payload_len; |
||||
tcp_socket->tcp_input_buffer_end = tcp_socket->tcp_input_buffer_end + |
||||
tcp_payload_len; |
||||
mutex_unlock(&tcp_socket->tcp_buffer_mutex); |
||||
} |
||||
|
||||
if (thread_getstatus(tcp_socket->recv_pid) == STATUS_RECEIVE_BLOCKED) { |
||||
net_msg_send_recv(&m_send_tcp, &m_recv_tcp, tcp_socket->recv_pid, UNDEFINED); |
||||
} |
||||
|
||||
return acknowledged_bytes; |
||||
} |
||||
|
||||
void handle_tcp_ack_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, |
||||
socket_internal_t *tcp_socket) |
||||
{ |
||||
msg_t m_recv_tcp, m_send_tcp; |
||||
kernel_pid_t target_pid = KERNEL_PID_UNDEF; |
||||
|
||||
if (tcp_socket->socket_values.tcp_control.state == TCP_LAST_ACK) { |
||||
target_pid = tcp_socket->recv_pid; |
||||
close_socket(tcp_socket); |
||||
msg_send(&m_send_tcp, target_pid, 0); |
||||
return; |
||||
} |
||||
else if (tcp_socket->socket_values.tcp_control.state == TCP_CLOSING) { |
||||
msg_send(&m_send_tcp, tcp_socket->recv_pid, 0); |
||||
msg_send(&m_send_tcp, tcp_socket->send_pid, 0); |
||||
return; |
||||
} |
||||
else if (get_waiting_connection_socket(tcp_socket->socket_id, ipv6_header, |
||||
tcp_header) != NULL) { |
||||
m_send_tcp.content.ptr = (char *)tcp_header; |
||||
net_msg_send_recv(&m_send_tcp, &m_recv_tcp, tcp_socket->recv_pid, TCP_ACK); |
||||
return; |
||||
} |
||||
else if (tcp_socket->socket_values.tcp_control.state == TCP_ESTABLISHED) { |
||||
if (check_tcp_consistency(&tcp_socket->socket_values, tcp_header, 0) == PACKET_OK) { |
||||
m_send_tcp.content.ptr = (char *)tcp_header; |
||||
net_msg_send(&m_send_tcp, tcp_socket->send_pid, 0, TCP_ACK); |
||||
return; |
||||
} |
||||
} |
||||
|
||||
printf("NO WAY OF HANDLING THIS ACK!\n"); |
||||
} |
||||
|
||||
void handle_tcp_rst_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, |
||||
socket_internal_t *tcp_socket) |
||||
{ |
||||
(void) ipv6_header; |
||||
(void) tcp_header; |
||||
(void) tcp_socket; |
||||
|
||||
/* TODO: Reset connection */ |
||||
} |
||||
|
||||
void handle_tcp_syn_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, |
||||
socket_internal_t *tcp_socket) |
||||
{ |
||||
msg_t m_send_tcp; |
||||
|
||||
if (tcp_socket->socket_values.tcp_control.state == TCP_LISTEN) { |
||||
socket_internal_t *new_socket = new_tcp_queued_socket(ipv6_header, |
||||
tcp_header); |
||||
|
||||
if (new_socket != NULL) { |
||||
#ifdef TCP_HC |
||||
update_tcp_hc_context(true, new_socket, tcp_header); |
||||
#endif |
||||
/* notify socket function destiny_socket_accept(..) that a new
|
||||
* connection request has arrived. No need to wait for an answer |
||||
* because the server destiny_socket_accept() function isnt reading |
||||
* from anything other than the queued sockets */ |
||||
net_msg_send(&m_send_tcp, tcp_socket->recv_pid, 0, TCP_SYN); |
||||
} |
||||
else { |
||||
printf("Dropped TCP SYN Message because an error occured while "\
|
||||
"requesting a new queued socket!\n"); |
||||
} |
||||
} |
||||
else { |
||||
printf("Dropped TCP SYN Message because socket was not in state TCP_LISTEN!"); |
||||
} |
||||
} |
||||
|
||||
void handle_tcp_syn_ack_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, |
||||
socket_internal_t *tcp_socket) |
||||
{ |
||||
(void) ipv6_header; |
||||
|
||||
msg_t m_send_tcp; |
||||
|
||||
if (tcp_socket->socket_values.tcp_control.state == TCP_SYN_SENT) { |
||||
m_send_tcp.content.ptr = (char *) tcp_header; |
||||
net_msg_send(&m_send_tcp, tcp_socket->recv_pid, 0, TCP_SYN_ACK); |
||||
} |
||||
else { |
||||
printf("Socket not in state TCP_SYN_SENT, dropping SYN-ACK-packet!"); |
||||
} |
||||
} |
||||
|
||||
void handle_tcp_fin_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, |
||||
socket_internal_t *tcp_socket) |
||||
{ |
||||
(void) ipv6_header; |
||||
|
||||
msg_t m_send; |
||||
socket_t *current_tcp_socket = &tcp_socket->socket_values; |
||||
uint8_t send_buffer[BUFFER_SIZE]; |
||||
ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t *)(&send_buffer)); |
||||
tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t *)(&send_buffer[IPV6_HDR_LEN])); |
||||
|
||||
set_tcp_cb(¤t_tcp_socket->tcp_control, tcp_header->seq_nr + 1, |
||||
current_tcp_socket->tcp_control.send_wnd, tcp_header->ack_nr + 1, |
||||
tcp_header->ack_nr, tcp_header->window); |
||||
|
||||
#ifdef TCP_HC |
||||
current_tcp_socket->tcp_control.tcp_context.hc_type = COMPRESSED_HEADER; |
||||
#endif |
||||
|
||||
if (current_tcp_socket->tcp_control.state == TCP_FIN_WAIT_1) { |
||||
current_tcp_socket->tcp_control.state = TCP_CLOSING; |
||||
|
||||
send_tcp(tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_FIN_ACK, 0); |
||||
} |
||||
else { |
||||
current_tcp_socket->tcp_control.state = TCP_LAST_ACK; |
||||
|
||||
send_tcp(tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_FIN_ACK, 0); |
||||
} |
||||
|
||||
net_msg_send(&m_send, tcp_socket->recv_pid, 0, CLOSE_CONN); |
||||
} |
||||
|
||||
void handle_tcp_fin_ack_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, |
||||
socket_internal_t *tcp_socket) |
||||
{ |
||||
(void) ipv6_header; |
||||
|
||||
msg_t m_send; |
||||
socket_t *current_tcp_socket = &tcp_socket->socket_values; |
||||
uint8_t send_buffer[BUFFER_SIZE]; |
||||
ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t *)(&send_buffer)); |
||||
tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t *)(&send_buffer[IPV6_HDR_LEN])); |
||||
|
||||
current_tcp_socket->tcp_control.state = TCP_CLOSED; |
||||
|
||||
set_tcp_cb(¤t_tcp_socket->tcp_control, tcp_header->seq_nr + 1, |
||||
current_tcp_socket->tcp_control.send_wnd, tcp_header->ack_nr, |
||||
tcp_header->ack_nr, tcp_header->window); |
||||
|
||||
#ifdef TCP_HC |
||||
current_tcp_socket->tcp_control.tcp_context.hc_type = COMPRESSED_HEADER; |
||||
#endif |
||||
|
||||
send_tcp(tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_ACK, 0); |
||||
|
||||
msg_send(&m_send, tcp_socket->send_pid, 0); |
||||
msg_send(&m_send, tcp_socket->recv_pid, 0); |
||||
} |
||||
|
||||
void handle_tcp_no_flags_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, |
||||
socket_internal_t *tcp_socket, uint8_t *payload, uint8_t tcp_payload_len) |
||||
{ |
||||
uint8_t read_bytes = 0; |
||||
socket_t *current_tcp_socket = &tcp_socket->socket_values; |
||||
uint8_t send_buffer[BUFFER_SIZE]; |
||||
ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t *)(&send_buffer)); |
||||
tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t *)(&send_buffer[IPV6_HDR_LEN])); |
||||
|
||||
if (check_tcp_consistency(current_tcp_socket, tcp_header, tcp_payload_len) == PACKET_OK) { |
||||
read_bytes = handle_payload(ipv6_header, tcp_header, tcp_socket, payload); |
||||
|
||||
/* Refresh TCP status values */ |
||||
current_tcp_socket->tcp_control.state = TCP_ESTABLISHED; |
||||
|
||||
set_tcp_cb(¤t_tcp_socket->tcp_control, |
||||
tcp_header->seq_nr + read_bytes, |
||||
current_tcp_socket->tcp_control.rcv_wnd, |
||||
current_tcp_socket->tcp_control.send_nxt, |
||||
current_tcp_socket->tcp_control.send_una, |
||||
current_tcp_socket->tcp_control.send_wnd); |
||||
|
||||
/* Send packet */ |
||||
// block_continue_thread();
|
||||
#ifdef TCP_HC |
||||
current_tcp_socket->tcp_control.tcp_context.hc_type = COMPRESSED_HEADER; |
||||
#endif |
||||
send_tcp(tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_ACK, 0); |
||||
} |
||||
/* ACK packet probably got lost */ |
||||
else { |
||||
// block_continue_thread();
|
||||
#ifdef TCP_HC |
||||
current_tcp_socket->tcp_control.tcp_context.hc_type = FULL_HEADER; |
||||
#endif |
||||
send_tcp(tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_ACK, 0); |
||||
} |
||||
} |
||||
|
||||
void *tcp_packet_handler(void *arg) |
||||
{ |
||||
(void) arg; |
||||
|
||||
msg_t m_recv_ip, m_send_ip; |
||||
ipv6_hdr_t *ipv6_header; |
||||
tcp_hdr_t *tcp_header; |
||||
uint8_t *payload; |
||||
socket_internal_t *tcp_socket = NULL; |
||||
uint16_t chksum; |
||||
|
||||
while (1) { |
||||
msg_receive(&m_recv_ip); |
||||
|
||||
ipv6_header = ((ipv6_hdr_t *)m_recv_ip.content.ptr); |
||||
tcp_header = ((tcp_hdr_t *)(m_recv_ip.content.ptr + IPV6_HDR_LEN)); |
||||
#ifdef TCP_HC |
||||
tcp_socket = decompress_tcp_packet(ipv6_header); |
||||
#else |
||||
switch_tcp_packet_byte_order(tcp_header); |
||||
tcp_socket = get_tcp_socket(ipv6_header, tcp_header); |
||||
#endif |
||||
chksum = tcp_csum(ipv6_header, tcp_header); |
||||
|
||||
payload = (uint8_t *)(m_recv_ip.content.ptr + IPV6_HDR_LEN + tcp_header->data_offset * 4); |
||||
|
||||
if ((chksum == 0xffff) && (tcp_socket != NULL)) { |
||||
#ifdef TCP_HC |
||||
update_tcp_hc_context(true, tcp_socket, tcp_header); |
||||
#endif |
||||
/* Remove reserved bits from tcp flags field */ |
||||
uint8_t tcp_flags = tcp_header->reserved_flags; |
||||
|
||||
switch (tcp_flags) { |
||||
case TCP_ACK: { |
||||
/* only ACK Bit set */ |
||||
uint8_t tcp_payload_len = NTOHS(ipv6_header->length) - TCP_HDR_LEN; |
||||
uint8_t state = tcp_socket->socket_values.tcp_control.state; |
||||
|
||||
if ((tcp_payload_len > 0) && (state == TCP_ESTABLISHED)) { |
||||
/* handle data segments only when the connection was established successfully */ |
||||
handle_tcp_no_flags_packet(ipv6_header, tcp_header, tcp_socket, payload, tcp_payload_len); |
||||
} |
||||
else if (tcp_payload_len == 0 |
||||
&& (state == TCP_ESTABLISHED || state == TCP_SYN_RCVD |
||||
|| state == TCP_CLOSING || state == TCP_LAST_ACK)) { |
||||
/* no payload, acknowledging data only */ |
||||
handle_tcp_ack_packet(ipv6_header, tcp_header, tcp_socket); |
||||
} |
||||
break; |
||||
} |
||||
|
||||
case TCP_RST: { |
||||
printf("RST Bit set!\n"); |
||||
/* only RST Bit set */ |
||||
handle_tcp_rst_packet(ipv6_header, tcp_header, tcp_socket); |
||||
break; |
||||
} |
||||
|
||||
case TCP_SYN: { |
||||
/* only SYN Bit set, look for matching, listening socket
|
||||
* and request new queued socket */ |
||||
printf("SYN Bit set!\n"); |
||||
handle_tcp_syn_packet(ipv6_header, tcp_header, tcp_socket); |
||||
break; |
||||
} |
||||
|
||||
case TCP_SYN_ACK: { |
||||
/* only SYN and ACK Bit set, complete three way handshake
|
||||
* when socket in state TCP_SYN_SENT */ |
||||
handle_tcp_syn_ack_packet(ipv6_header, tcp_header, tcp_socket); |
||||
break; |
||||
} |
||||
|
||||
case TCP_FIN_ACK: { |
||||
if (tcp_socket->socket_values.tcp_control.state == TCP_ESTABLISHED) { |
||||
/* this is the first FIN */ |
||||
printf("FIN ACK Bit set!\n"); |
||||
handle_tcp_fin_packet(ipv6_header, tcp_header, tcp_socket); |
||||
} |
||||
else { |
||||
/* this is the response to FIN */ |
||||
handle_tcp_fin_ack_packet(ipv6_header, tcp_header, tcp_socket); |
||||
} |
||||
break; |
||||
} |
||||
|
||||
default: { |
||||
printf("Unable to process the incoming segment!\n"); |
||||
} |
||||
} |
||||
} |
||||
else { |
||||
printf("Wrong checksum (%x) or no corresponding socket found!\n", |
||||
chksum); |
||||
printArrayRange(((uint8_t *)ipv6_header), IPV6_HDR_LEN + |
||||
NTOHS(ipv6_header->length), "Incoming"); |
||||
print_tcp_status(INC_PACKET, ipv6_header, tcp_header, |
||||
&tcp_socket->socket_values); |
||||
} |
||||
|
||||
msg_reply(&m_recv_ip, &m_send_ip); |
||||
} |
||||
} |
@ -1,84 +0,0 @@
|
||||
/**
|
||||
* Destiny UDP implementation |
||||
* |
||||
* Copyright (C) 2013 INRIA. |
||||
* |
||||
* This file is subject to the terms and conditions of the GNU Lesser |
||||
* General Public License v2.1. See the file LICENSE in the top level |
||||
* directory for more details. |
||||
* |
||||
* @ingroup destiny |
||||
* @{ |
||||
* @file udp.c |
||||
* @brief UDP implementation |
||||
* @author Oliver Gesch <oliver.gesch@googlemail.com> |
||||
* @} |
||||
*/ |
||||
|
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
|
||||
#include "ipv6.h" |
||||
#include "msg.h" |
||||
#include "sixlowpan.h" |
||||
#include "thread.h" |
||||
|
||||
#include "destiny/in.h" |
||||
|
||||
#include "net_help.h" |
||||
|
||||
#include "msg_help.h" |
||||
#include "socket.h" |
||||
|
||||
#include "udp.h" |
||||
|
||||
msg_t udp_msg_queue[UDP_PKT_RECV_BUF_SIZE]; |
||||
|
||||
uint16_t udp_csum(ipv6_hdr_t *ipv6_header, udp_hdr_t *udp_header) |
||||
{ |
||||
uint16_t sum; |
||||
uint16_t len = NTOHS(udp_header->length); |
||||
|
||||
sum = len + IPPROTO_UDP; |
||||
sum = csum(sum, (uint8_t *)&ipv6_header->srcaddr, 2 * sizeof(ipv6_addr_t)); |
||||
sum = csum(sum, (uint8_t *)udp_header, len); |
||||
return (sum == 0) ? 0xffff : HTONS(sum); |
||||
} |
||||
|
||||
void *udp_packet_handler(void *arg) |
||||
{ |
||||
(void) arg; |
||||
|
||||
msg_t m_recv_ip, m_send_ip, m_recv_udp, m_send_udp; |
||||
ipv6_hdr_t *ipv6_header; |
||||
udp_hdr_t *udp_header; |
||||
socket_internal_t *udp_socket = NULL; |
||||
uint16_t chksum; |
||||
|
||||
msg_init_queue(udp_msg_queue, UDP_PKT_RECV_BUF_SIZE); |
||||
|
||||
while (1) { |
||||
msg_receive(&m_recv_ip); |
||||
ipv6_header = ((ipv6_hdr_t *)m_recv_ip.content.ptr); |
||||
udp_header = ((udp_hdr_t *)(m_recv_ip.content.ptr + IPV6_HDR_LEN)); |
||||
|
||||
chksum = ipv6_csum(ipv6_header, (uint8_t*) udp_header, NTOHS(udp_header->length), IPPROTO_UDP); |
||||
|
||||
if (chksum == 0xffff) { |
||||
udp_socket = get_udp_socket(udp_header); |
||||
|
||||
if (udp_socket != NULL) { |
||||
m_send_udp.content.ptr = (char *)ipv6_header; |
||||
msg_send_receive(&m_send_udp, &m_recv_udp, udp_socket->recv_pid); |
||||
} |
||||
else { |
||||
printf("Dropped UDP Message because no thread ID was found for delivery!\n"); |
||||
} |
||||
} |
||||
else { |
||||
printf("Wrong checksum (%x)!\n", chksum); |
||||
} |
||||
|
||||
msg_reply(&m_recv_ip, &m_send_ip); |
||||
} |
||||
} |
@ -1,34 +0,0 @@
|
||||
/**
|
||||
* Destiny TCP header |
||||
* |
||||
* Copyright (C) 2013 INRIA. |
||||
* |
||||
* This file is subject to the terms and conditions of the GNU Lesser |
||||
* General Public License v2.1. See the file LICENSE in the top level |
||||
* directory for more details. |
||||
* |
||||
* @ingroup destiny |
||||
* @{ |
||||
* @file |
||||
* @brief UDP data structs and prototypes |
||||
* @author Oliver Gesch <oliver.gesch@googlemail.com> |
||||
*/ |
||||
|
||||
|
||||
#ifndef UDP_H_ |
||||
#define UDP_H_ |
||||
|
||||
#include "ipv6.h" |
||||
#include "destiny/types.h" |
||||
|
||||
#define UDP_STACK_SIZE KERNEL_CONF_STACKSIZE_MAIN |
||||
#define UDP_PKT_RECV_BUF_SIZE (64) |
||||
|
||||
uint16_t udp_csum(ipv6_hdr_t *ipv6_header, udp_hdr_t *udp_header); |
||||
void *udp_packet_handler(void *); |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
#endif /* UDP_H_ */ |
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base |