int destiny_socket_close(int s) { socket_internal_t *current_socket = get_socket(s); if (current_socket != NULL) { if (is_tcp_socket(s)) { /* Variables */ msg_t m_recv; 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])); /* Check if socket exists and is TCP socket */ if (!is_tcp_socket(s)) { return -1; } /* Check for ESTABLISHED STATE */ if (current_socket->socket_values.tcp_control.state != ESTABLISHED) { close_socket(current_socket); return 0; } current_socket->send_pid = thread_getpid(); /* Refresh local TCP socket information */ current_socket->socket_values.tcp_control.send_una++; current_socket->socket_values.tcp_control.state = FIN_WAIT_1; #ifdef TCP_HC current_socket->socket_values.tcp_control.tcp_context.hc_type = COMPRESSED_HEADER; #endif send_tcp(current_socket, current_tcp_packet, temp_ipv6_header, TCP_FIN, 0); msg_receive(&m_recv); close_socket(current_socket); return 1; } else if (isUDPSocket(s)) { close_socket(current_socket); return 0; } return -1; } else { return -1; } }
void check_sockets(void) { socket_internal_t *current_socket; uint8_t i = 1; while (i < MAX_SOCKETS + 1) { current_socket = get_socket(i); if (is_tcp_socket(i)) { switch (current_socket->socket_values.tcp_control.state) { case ESTABLISHED: { handle_established(current_socket); break; } case SYN_SENT: { handle_synchro_timeout(current_socket); break; } case SYN_RCVD: { handle_synchro_timeout(current_socket); break; } default: { break; } } } i++; } }
int32_t destiny_socket_recvfrom(int s, void *buf, uint32_t len, int flags, sockaddr6_t *from, uint32_t *fromlen) { if (isUDPSocket(s)) { msg_t m_recv, m_send; ipv6_hdr_t *ipv6_header; udp_hdr_t *udp_header; uint8_t *payload; get_socket(s)->recv_pid = thread_getpid(); msg_receive(&m_recv); ipv6_header = ((ipv6_hdr_t *)m_recv.content.ptr); udp_header = ((udp_hdr_t *)(m_recv.content.ptr + IPV6_HDR_LEN)); payload = (uint8_t *)(m_recv.content.ptr + IPV6_HDR_LEN + UDP_HDR_LEN); memset(buf, 0, len); memcpy(buf, payload, udp_header->length - UDP_HDR_LEN); memcpy(&from->sin6_addr, &ipv6_header->srcaddr, 16); from->sin6_family = AF_INET6; from->sin6_flowinfo = 0; from->sin6_port = udp_header->src_port; *fromlen = sizeof(sockaddr6_t); msg_reply(&m_recv, &m_send); return udp_header->length - UDP_HDR_LEN; } else if (is_tcp_socket(s)) { return destiny_socket_recv(s, buf, len, flags); } else { printf("Socket Type not supported!\n"); return -1; } }
int destiny_socket_accept(int s, sockaddr6_t *addr, uint32_t *addrlen) { socket_internal_t *server_socket = get_socket(s); if (is_tcp_socket(s) && (server_socket->socket_values.tcp_control.state == LISTEN)) { socket_internal_t *current_queued_socket = get_waiting_connection_socket(s, NULL, NULL); if (current_queued_socket != NULL) { return handle_new_tcp_connection(current_queued_socket, server_socket, thread_getpid()); } else { /* No waiting connections, waiting for message from TCP Layer */ msg_t msg_recv_client_syn; msg_recv_client_syn.type = UNDEFINED; while (msg_recv_client_syn.type != TCP_SYN) { msg_receive(&msg_recv_client_syn); } current_queued_socket = get_waiting_connection_socket(s, NULL, NULL); return handle_new_tcp_connection(current_queued_socket, server_socket, thread_getpid()); } } else { return -1; } }
int destiny_socket_listen(int s, int backlog) { if (is_tcp_socket(s) && get_socket(s)->socket_values.tcp_control.state == CLOSED) { socket_internal_t *current_socket = get_socket(s); current_socket->socket_values.tcp_control.state = LISTEN; return 0; } else { return -1; } }
socket_internal_t *get_tcp_socket(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header) { uint8_t i = 1; socket_internal_t *current_socket = NULL; socket_internal_t *listening_socket = NULL; uint8_t compare[16]; memset(compare, 0, 16); while (i < MAX_SOCKETS + 1) { current_socket = get_socket(i); /* Check for matching 4 touple, ESTABLISHED connection */ if (is_tcp_socket(i) && is_four_touple(current_socket, ipv6_header, tcp_header)) { return current_socket; } /* Sockets in LISTEN and SYN_RCVD state should only be tested on local TCP values */ else if (is_tcp_socket(i) && ((current_socket->socket_values.tcp_control.state == LISTEN) || (current_socket->socket_values.tcp_control.state == SYN_RCVD)) && (current_socket->socket_values.local_address.sin6_addr.uint8[15] == ipv6_header->destaddr.uint8[15]) && (current_socket->socket_values.local_address.sin6_port == tcp_header->dst_port) && (current_socket->socket_values.foreign_address.sin6_addr.uint8[15] == 0x00) && (current_socket->socket_values.foreign_address.sin6_port == 0)) { listening_socket = current_socket; } i++; } /* Return either NULL if nothing was matched or the listening 2 touple socket */ return listening_socket; }
int bind_tcp_socket(int s, sockaddr6_t *name, int namelen, uint8_t pid) { int i; if (!exists_socket(s)) { return -1; } for (i = 1; i < MAX_SOCKETS + 1; i++) { if (is_tcp_socket(i) && (get_socket(i)->socket_values.local_address.sin6_port == name->sin6_port)) { return -1; } } memcpy(&get_socket(s)->socket_values.local_address, name, namelen); get_socket(s)->recv_pid = pid; get_socket(s)->socket_values.tcp_control.rto = TCP_INITIAL_ACK_TIMEOUT; return 0; }
int32_t destiny_socket_recv(int s, void *buf, uint32_t len, int flags) { /* Variables */ uint8_t read_bytes; msg_t m_recv, m_send; socket_internal_t *current_int_tcp_socket; /* Check if socket exists */ if (!is_tcp_socket(s)) { printf("INFO: NO TCP SOCKET!\n"); return -1; } current_int_tcp_socket = get_socket(s); /* Setting Thread PID */ current_int_tcp_socket->recv_pid = thread_getpid(); if (current_int_tcp_socket->tcp_input_buffer_end > 0) { return read_from_socket(current_int_tcp_socket, buf, len); } msg_receive(&m_recv); if ((exists_socket(s)) && (current_int_tcp_socket->tcp_input_buffer_end > 0)) { read_bytes = read_from_socket(current_int_tcp_socket, buf, len); net_msg_reply(&m_recv, &m_send, UNDEFINED); return read_bytes; } /* Received FIN */ if (m_recv.type == CLOSE_CONN) { /* Sent FIN_ACK, wait for ACK */ msg_receive(&m_recv); /* Received ACK, return with closed socket!*/ return -1; } /* Received Last ACK (connection closed) or no data to read yet */ return -1; }
int32_t destiny_socket_send(int s, const void *buf, uint32_t len, int flags) { /* Variables */ msg_t recv_msg; int32_t sent_bytes = 0, total_sent_bytes = 0; socket_internal_t *current_int_tcp_socket; socket_t *current_tcp_socket; uint8_t send_buffer[BUFFER_SIZE]; memset(send_buffer, 0, 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])); /* Check if socket exists and is TCP socket */ if (!is_tcp_socket(s)) { return -1; } current_int_tcp_socket = get_socket(s); current_tcp_socket = ¤t_int_tcp_socket->socket_values; /* Check for ESTABLISHED STATE */ if (current_tcp_socket->tcp_control.state != ESTABLISHED) { return -1; } /* Add thread PID */ current_int_tcp_socket->send_pid = thread_getpid(); recv_msg.type = UNDEFINED; while (1) { current_tcp_socket->tcp_control.no_of_retries = 0; #ifdef TCP_HC current_tcp_socket->tcp_control.tcp_context.hc_type = COMPRESSED_HEADER; /* Remember TCP Context for possible TCP_RETRY */ tcp_hc_context_t saved_tcp_context; memcpy(&saved_tcp_context, ¤t_tcp_socket->tcp_control.tcp_context, sizeof(tcp_hc_context_t) - 1); #endif while (recv_msg.type != TCP_ACK) { /* Add packet data */ if (current_tcp_socket->tcp_control.send_wnd > current_tcp_socket->tcp_control.mss) { /* Window size > Maximum Segment Size */ if ((len - total_sent_bytes) > current_tcp_socket->tcp_control.mss) { memcpy(&send_buffer[IPV6_HDR_LEN + TCP_HDR_LEN], buf, current_tcp_socket->tcp_control.mss); sent_bytes = current_tcp_socket->tcp_control.mss; total_sent_bytes += sent_bytes; } else { memcpy(&send_buffer[IPV6_HDR_LEN + TCP_HDR_LEN], buf + total_sent_bytes, len - total_sent_bytes); sent_bytes = len - total_sent_bytes; total_sent_bytes = len; } } else { /* Window size <= Maximum Segment Size */ if ((len - total_sent_bytes) > current_tcp_socket->tcp_control.send_wnd) { memcpy(&send_buffer[IPV6_HDR_LEN + TCP_HDR_LEN], buf, current_tcp_socket->tcp_control.send_wnd); sent_bytes = current_tcp_socket->tcp_control.send_wnd; total_sent_bytes += sent_bytes; } else { memcpy(&send_buffer[IPV6_HDR_LEN + TCP_HDR_LEN], buf + total_sent_bytes, len - total_sent_bytes); sent_bytes = len - total_sent_bytes; total_sent_bytes = len; } } current_tcp_socket->tcp_control.send_nxt += sent_bytes; current_tcp_socket->tcp_control.send_wnd -= sent_bytes; if (send_tcp(current_int_tcp_socket, current_tcp_packet, temp_ipv6_header, 0, sent_bytes) != 1) { /* Error while sending tcp data */ current_tcp_socket->tcp_control.send_nxt -= sent_bytes; current_tcp_socket->tcp_control.send_wnd += sent_bytes; #ifdef TCP_HC memcpy(¤t_tcp_socket->tcp_control.tcp_context, &saved_tcp_context, sizeof(tcp_hc_context_t)); current_tcp_socket->tcp_control.tcp_context.hc_type = COMPRESSED_HEADER; #endif printf("Error while sending, returning to application thread!\n"); return -1; } /* Remember current time */ current_tcp_socket->tcp_control.last_packet_time.microseconds = hwtimer_now(); net_msg_receive(&recv_msg); switch (recv_msg.type) { case TCP_ACK: { if (current_tcp_socket->tcp_control.no_of_retries == 0) { calculate_rto(¤t_tcp_socket->tcp_control, hwtimer_now()); } tcp_hdr_t *tcp_header = ((tcp_hdr_t *)(recv_msg.content.ptr)); if ((current_tcp_socket->tcp_control.send_nxt == tcp_header->ack_nr) && (total_sent_bytes == len)) { current_tcp_socket->tcp_control.send_una = tcp_header->ack_nr; current_tcp_socket->tcp_control.send_nxt = tcp_header->ack_nr; current_tcp_socket->tcp_control.send_wnd = tcp_header->window; /* Got ACK for every sent byte */ #ifdef TCP_HC current_tcp_socket->tcp_control.tcp_context.hc_type = COMPRESSED_HEADER; #endif return sent_bytes; } else if ((current_tcp_socket->tcp_control.send_nxt == tcp_header->ack_nr) && (total_sent_bytes != len)) { current_tcp_socket->tcp_control.send_una = tcp_header->ack_nr; current_tcp_socket->tcp_control.send_nxt = tcp_header->ack_nr; current_tcp_socket->tcp_control.send_wnd = tcp_header->window; /* Got ACK for every sent byte */ #ifdef TCP_HC current_tcp_socket->tcp_control.tcp_context.hc_type = COMPRESSED_HEADER; #endif break; } /* else { * TODO: If window size > MSS, ACK was valid only for * a few segments, handle retransmit of missing * segments * break; * } */ break; } case TCP_RETRY: { current_tcp_socket->tcp_control.send_nxt -= sent_bytes; current_tcp_socket->tcp_control.send_wnd += sent_bytes; total_sent_bytes -= sent_bytes; #ifdef TCP_HC memcpy(¤t_tcp_socket->tcp_control.tcp_context, $&saved_tcp_context, sizeof(tcp_hc_context_t)); current_tcp_socket->tcp_control.tcp_context.hc_type = MOSTLY_COMPRESSED_HEADER; #endif break; } case TCP_TIMEOUT: { current_tcp_socket->tcp_control.send_nxt -= sent_bytes; current_tcp_socket->tcp_control.send_wnd += sent_bytes; #ifdef TCP_HC memcpy(¤t_tcp_socket->tcp_control.tcp_context, &saved_tcp_context, sizeof(tcp_hc_context_t)); current_tcp_socket->tcp_control.tcp_context.hc_type = COMPRESSED_HEADER; #endif return -1; break; } } } } return sent_bytes; }