mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
9e20944fde
helper, increased stack sizes of network threads
425 lines
10 KiB
C
425 lines
10 KiB
C
/*
|
|
* socket.c
|
|
*
|
|
* Created on: 16.09.2011
|
|
* Author: Oliver
|
|
*/
|
|
#include <thread.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "udp.h"
|
|
#include "tcp.h"
|
|
#include "socket.h"
|
|
|
|
void print_socket(uint8_t socket)
|
|
{
|
|
socket = socket - 1;
|
|
printf ("---SOCKET---\n");
|
|
printf("Value: %i, Domain: %i, Type: %i, Protocol: %i \n", sockets[socket].in_socket.socket_id, sockets[socket].in_socket.domain, sockets[socket].in_socket.type, sockets[socket].in_socket.protocol);
|
|
printf("Port: %i, Family: %i\n", sockets[socket].in_socket.sa.sin6_port, sockets[socket].in_socket.sa.sin6_family);
|
|
ipv6_print_addr(&sockets[socket].in_socket.sa.sin6_addr);
|
|
}
|
|
|
|
bool exists_socket(uint8_t socket)
|
|
{
|
|
if (sockets[socket-1].in_socket.socket_id == 0)
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
socket_internal_t* getSocket(uint8_t s)
|
|
{
|
|
if (exists_socket(s))
|
|
return &sockets[s-1];
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
bool isUDPSocket(uint8_t s)
|
|
{
|
|
if ( (exists_socket(s)) &&
|
|
(getSocket(s)->in_socket.domain == PF_INET6) &&
|
|
(getSocket(s)->in_socket.type == SOCK_DGRAM) &&
|
|
((getSocket(s)->in_socket.protocol == IPPROTO_UDP) ||
|
|
(getSocket(s)->in_socket.protocol == 0)))
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
bool isTCPSocket(uint8_t s)
|
|
{
|
|
if ( (exists_socket(s)) &&
|
|
(getSocket(s)->in_socket.domain == PF_INET6) &&
|
|
(getSocket(s)->in_socket.type == SOCK_STREAM) &&
|
|
((getSocket(s)->in_socket.protocol == IPPROTO_TCP) ||
|
|
(getSocket(s)->in_socket.protocol == 0)))
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
int bind_udp_socket(int s, struct sockaddr_in6 *name, int namelen, uint8_t pid)
|
|
{
|
|
int i;
|
|
if (!exists_socket(s))
|
|
{
|
|
return -1;
|
|
}
|
|
for (i = 1; i < MAX_SOCKETS+1; i++)
|
|
{
|
|
if (isUDPSocket(i) && (getSocket(i)->in_socket.sa.sin6_port == name->sin6_port))
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
memcpy(&getSocket(s)->in_socket.sa, name, namelen);
|
|
getSocket(s)->pid = pid;
|
|
return 1;
|
|
}
|
|
|
|
int bind_tcp_socket(int s, struct sockaddr_in6 *name, int namelen, uint8_t pid)
|
|
{
|
|
int i;
|
|
if (!exists_socket(s))
|
|
{
|
|
return -1;
|
|
}
|
|
for (i = 1; i < MAX_SOCKETS+1; i++)
|
|
{
|
|
if (isTCPSocket(i) && (getSocket(i)->in_socket.sa.sin6_port == name->sin6_port))
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
memcpy(&getSocket(s)->in_socket.sa, name, namelen);
|
|
getSocket(s)->pid = pid;
|
|
return 1;
|
|
}
|
|
|
|
int socket(int domain, int type, int protocol)
|
|
{
|
|
int i = 1;
|
|
while (getSocket(i) != NULL)
|
|
{
|
|
i++;
|
|
}
|
|
if (i > MAX_SOCKETS+1)
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
struct socket_t *current_socket = &sockets[i-1].in_socket;
|
|
current_socket->socket_id = i;
|
|
current_socket->domain = domain;
|
|
current_socket->type = type;
|
|
current_socket->protocol = protocol;
|
|
return current_socket->socket_id;
|
|
}
|
|
}
|
|
|
|
int connect(int socket, struct sockaddr_in6 *addr, uint32_t addrlen)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
int32_t send(int s, void *msg, uint64_t len, int flags)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
int32_t recv(int s, void *buf, uint64_t len, int flags)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
int32_t recvfrom(int s, void *buf, uint64_t len, int flags, struct sockaddr_in6 *from, uint32_t *fromlen)
|
|
{
|
|
if (isUDPSocket(s))
|
|
{
|
|
msg_t m_recv, m_send;
|
|
struct ipv6_hdr_t *ipv6_header;
|
|
struct udp_hdr_t *udp_header;
|
|
uint8_t *payload;
|
|
uint16_t payload_size = 0;
|
|
msg_receive(&m_recv);
|
|
|
|
ipv6_header = ((struct ipv6_hdr_t*)&buffer_udp);
|
|
udp_header = ((struct udp_hdr_t*)(&buffer_udp[IPV6_HDR_LEN]));
|
|
payload = &buffer_udp[IPV6_HDR_LEN+UDP_HDR_LEN];
|
|
|
|
memset(buf, 0, len);
|
|
memcpy(buf, payload, udp_header->length);
|
|
payload_size = udp_header->length;
|
|
memcpy(&from->sin6_addr, &ipv6_header->srcaddr, 16);
|
|
memset(&from->sin6_family, AF_INET6, 1);
|
|
memset(&from->sin6_flowinfo, 0, 4);
|
|
memcpy(&from->sin6_port, &udp_header->src_port, sizeof(udp_header->src_port));
|
|
memcpy(fromlen, (void*)(sizeof(sockaddr_in6)), sizeof(fromlen));
|
|
msg_reply(&m_recv, &m_send);
|
|
return payload_size;
|
|
}
|
|
else if (isTCPSocket(s))
|
|
{
|
|
return recv(s, buf, len, flags);
|
|
}
|
|
else
|
|
{
|
|
printf("Socket Type not supported!\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int32_t sendto(int s, void *msg, uint64_t len, int flags, struct sockaddr_in6 *to, uint32_t tolen)
|
|
{
|
|
if (exists_socket(s) && isUDPSocket(s) && (getSocket(s)->in_socket.sa.sin6_port == 0))
|
|
{
|
|
uint8_t send_buffer[BUFFER_SIZE];
|
|
|
|
struct ipv6_hdr_t *temp_ipv6_header = ((struct ipv6_hdr_t*)(&send_buffer));
|
|
struct udp_hdr_t *temp_udp_header = ((struct udp_hdr_t*)(&send_buffer[IPV6_HDR_LEN]));
|
|
uint8_t *payload = &send_buffer[IPV6_HDR_LEN+UDP_HDR_LEN];
|
|
|
|
ipv6_print_addr(&to->sin6_addr);
|
|
|
|
memcpy(&(temp_ipv6_header->destaddr), &to->sin6_addr, 16);
|
|
ipv6_get_saddr(&(temp_ipv6_header->srcaddr), &(temp_ipv6_header->destaddr));
|
|
temp_ipv6_header->version_trafficclass = IPV6_VER;
|
|
temp_ipv6_header->trafficclass_flowlabel = 0;
|
|
temp_ipv6_header->flowlabel = 0;
|
|
temp_ipv6_header->nextheader = IPPROTO_UDP;
|
|
temp_ipv6_header->hoplimit = MULTIHOP_HOPLIMIT;
|
|
|
|
|
|
temp_udp_header->src_port = 0;
|
|
temp_udp_header->dst_port = to->sin6_port;
|
|
temp_udp_header->checksum = 0;
|
|
|
|
memcpy(payload, msg, len);
|
|
temp_udp_header->length = UDP_HDR_LEN + len;
|
|
temp_ipv6_header->length = UDP_HDR_LEN + len;
|
|
|
|
temp_udp_header->checksum = ~udp_csum(temp_ipv6_header, temp_udp_header);
|
|
|
|
printf("Content of IPv6 Packet: length: %i\n", temp_ipv6_header->length);
|
|
printf("Content of UDP Packet: src_port: %i, dst_port: %i, length: %i, checksum: %x\n", temp_udp_header->src_port, temp_udp_header->dst_port, temp_udp_header->length, temp_udp_header->checksum);
|
|
sixlowpan_send(&to->sin6_addr, (uint8_t*)(temp_udp_header), temp_udp_header->length, IPPROTO_UDP);
|
|
return temp_udp_header->length;
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int close(int s)
|
|
{
|
|
if (exists_socket(s))
|
|
{
|
|
memset(getSocket(s), 0, sizeof(socket_t));
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int bind(int s, struct sockaddr_in6 *name, int namelen, uint8_t pid)
|
|
{
|
|
if (exists_socket(s))
|
|
{
|
|
socket_t *current_socket = &getSocket(s)->in_socket;
|
|
switch (current_socket->domain)
|
|
{
|
|
case (PF_INET):
|
|
{
|
|
// Not provided
|
|
return -1;
|
|
break;
|
|
}
|
|
case (PF_INET6):
|
|
{
|
|
switch (current_socket->type)
|
|
{
|
|
// TCP
|
|
case (SOCK_STREAM):
|
|
{
|
|
if ((current_socket->protocol == 0) || (current_socket->protocol == IPPROTO_TCP))
|
|
{
|
|
return bind_tcp_socket(s, name, namelen, pid);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
// UDP
|
|
case (SOCK_DGRAM):
|
|
{
|
|
if ((current_socket->protocol == 0) || (current_socket->protocol == IPPROTO_UDP))
|
|
{
|
|
return bind_udp_socket(s, name, namelen, pid);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case (SOCK_SEQPACKET):
|
|
{
|
|
// not provided
|
|
return -1;
|
|
break;
|
|
}
|
|
case (SOCK_RAW):
|
|
{
|
|
// not provided
|
|
return -1;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
return -1;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case (PF_UNIX):
|
|
{
|
|
// Not provided
|
|
return -1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("SOCKET DOES NOT EXIST!\n");
|
|
return -1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int listen(int s, int backlog)
|
|
{
|
|
if (isTCPSocket(s) && getSocket(s)->in_socket.tcp_socket_status.state == CLOSED)
|
|
{
|
|
socket_internal_t *current_socket = getSocket(s);
|
|
current_socket->in_socket.tcp_socket_status.state = LISTEN;
|
|
memset(current_socket->queued_sockets, 0, MAX_QUEUED_SOCKETS*sizeof(socket_t));
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int accept(int s, struct sockaddr_in6 *addr, uint32_t addrlen)
|
|
{
|
|
if (isTCPSocket(s) && (getSocket(s)->in_socket.tcp_socket_status.state == LISTEN))
|
|
{
|
|
if (getSocket(s)->queued_sockets[0].socket_id != 0)
|
|
{
|
|
// Got waiting Connections (SYN received), get new socket number and establish connection
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
// No waiting connections, waiting for message from TCP Layer
|
|
msg_t msg_recv;
|
|
msg_receive(&msg_recv);
|
|
// Got new connection request, get new socket number and establish connection:
|
|
|
|
return 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int shutdown(int s , int how)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
socket_internal_t *get_udp_socket(uint16_t port)
|
|
{
|
|
uint8_t i = 1;
|
|
while (i < MAX_SOCKETS+1)
|
|
{
|
|
if ((exists_socket(i)) && isUDPSocket(i) && (getSocket(i)->in_socket.sa.sin6_port == port))
|
|
{
|
|
return getSocket(i);
|
|
}
|
|
i++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
socket_internal_t *get_tcp_socket(uint16_t port)
|
|
{
|
|
uint8_t i = 1;
|
|
while (i < MAX_SOCKETS+1)
|
|
{
|
|
if ((exists_socket(i)) && isTCPSocket(i) && (getSocket(i)->in_socket.sa.sin6_port == port))
|
|
{
|
|
return getSocket(i);
|
|
}
|
|
i++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
socket_t *new_tcp_queued_socket(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, socket_internal_t *socket)
|
|
{
|
|
int i;
|
|
for (i = 0; i < MAX_QUEUED_SOCKETS; i++)
|
|
{
|
|
if (socket->queued_sockets[i].socket_id == 0)
|
|
{
|
|
socket_t *current_socket = &socket->queued_sockets[i];
|
|
current_socket->socket_id = i+1;
|
|
current_socket->domain = PF_INET6;
|
|
current_socket->type = SOCK_STREAM;
|
|
current_socket->protocol = IPPROTO_TCP;
|
|
|
|
memcpy(¤t_socket->sa.sin6_addr, (void*) &ipv6_header->srcaddr, sizeof(ipv6_header->srcaddr));
|
|
current_socket->sa.sin6_family = AF_INET6;
|
|
|
|
// TODO: Decide what to do about "sa.sin6_flowlinfo"
|
|
//memcpy(current_socket->sa.sin6_flowinfo, ipv6_header->flowlabel, sizeof(ipv6_header->flowlabel));
|
|
|
|
memcpy(¤t_socket->sa.sin6_port, (void*) &tcp_header->src_port, sizeof(tcp_header->src_port));
|
|
|
|
// TCP Values
|
|
memcpy(¤t_socket->tcp_socket_status.ack_nr, (void*) tcp_header->ack_nr, sizeof(tcp_header->ack_nr));
|
|
memcpy(¤t_socket->tcp_socket_status.seq_nr, (void*) tcp_header->seq_nr, sizeof(tcp_header->seq_nr));
|
|
memcpy(¤t_socket->tcp_socket_status.window, (void*) &tcp_header->window, sizeof(tcp_header->window));
|
|
current_socket->tcp_socket_status.state = SYN_RCVD;
|
|
return current_socket;
|
|
}
|
|
else if (socket->queued_sockets[i].sa.sin6_port == tcp_header->src_port)
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|