static void fnet_arp_trace(char *str, fnet_arp_header_t *arp_hdr) { char mac_str[FNET_MAC_ADDR_STR_SIZE]; char ip_str[FNET_IP4_ADDR_STR_SIZE]; fnet_printf(FNET_SERIAL_ESC_FG_GREEN"%s", str); /* Print app-specific header.*/ fnet_println("[ARP header]"FNET_SERIAL_ESC_FG_BLACK); fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"); fnet_println("|(HWType) 0x%04x |(PrType) 0x%04x |", fnet_ntohs(arp_hdr->hard_type), fnet_ntohs(arp_hdr->prot_type)); fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"); fnet_println("|(HWSize) 0x%02x |(PrSize) 0x%02x |(Opcode) %5u |", arp_hdr->hard_size, arp_hdr->prot_size, fnet_ntohs(arp_hdr->op)); fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+/\\/\\/\\/-+"); fnet_mac_to_str(arp_hdr->sender_hard_addr, mac_str); fnet_println("|(SenderHWAddr) "FNET_SERIAL_ESC_FG_BLUE"%17s"FNET_SERIAL_ESC_FG_BLACK" |", mac_str); fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+/\\/\\/\\/-+"); fnet_println("|(SenderPrAddr) "FNET_SERIAL_ESC_FG_BLUE"%15s"FNET_SERIAL_ESC_FG_BLACK" |", fnet_inet_ntoa(*(struct in_addr *)(&arp_hdr->sender_prot_addr), ip_str)); fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+/\\/\\/\\/-+"); fnet_mac_to_str(arp_hdr->target_hard_addr, mac_str); fnet_println("|(TargetHWAddr) "FNET_SERIAL_ESC_FG_BLUE"%17s"FNET_SERIAL_ESC_FG_BLACK" |", mac_str); fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+/\\/\\/\\/-+"); fnet_println("|(TargetPrAddr) "FNET_SERIAL_ESC_FG_BLUE"%15s"FNET_SERIAL_ESC_FG_BLACK" |", fnet_inet_ntoa(*(struct in_addr *)(&arp_hdr->targer_prot_addr), ip_str)); fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"); }
static void fnet_udp_trace(fnet_uint8_t *str, fnet_udp_header_t *udp_hdr) { fnet_printf(FNET_SERIAL_ESC_FG_GREEN"%s", str); /* Print app-specific header.*/ fnet_println("[UDP header]"FNET_SERIAL_ESC_FG_BLACK); fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"); fnet_println("|(SrcPort) "FNET_SERIAL_ESC_FG_BLUE"%3u"FNET_SERIAL_ESC_FG_BLACK" |(DestPort) "FNET_SERIAL_ESC_FG_BLUE"%3u"FNET_SERIAL_ESC_FG_BLACK" |", fnet_ntohs(udp_hdr->source_port), fnet_ntohs(udp_hdr->destination_port)); fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"); fnet_println("|(Lenghth) "FNET_SERIAL_ESC_FG_BLUE"%3u"FNET_SERIAL_ESC_FG_BLACK" |(Checksum) 0x%04X |", fnet_ntohs(udp_hdr->length), fnet_ntohs(udp_hdr->checksum)); fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"); }
void fnet_icmp_trace(fnet_uint8_t *str, fnet_icmp_header_t *icmp_hdr) { fnet_printf(FNET_SERIAL_ESC_FG_GREEN"%s", str); /* Print app-specific header.*/ fnet_println("[ICMP header]"FNET_SERIAL_ESC_FG_BLACK); fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"); fnet_println("|(Type) "FNET_SERIAL_ESC_FG_BLUE"%3u"FNET_SERIAL_ESC_FG_BLACK" |(Code) %3u |(Cheksum) 0x%04x |", icmp_hdr->type, icmp_hdr->code, fnet_ntohs(icmp_hdr->checksum)); fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"); }
void fnet_eth_trace(fnet_uint8_t *str, fnet_eth_header_t *eth_hdr) { fnet_uint8_t mac_str[FNET_MAC_ADDR_STR_SIZE]; fnet_printf(FNET_SERIAL_ESC_FG_GREEN"%s", str); /* Print app-specific header.*/ fnet_println("[ETH header]"FNET_SERIAL_ESC_FG_BLACK); fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+/\\/\\/\\/-+"); fnet_println("|(Dest) "FNET_SERIAL_ESC_FG_BLUE"%17s"FNET_SERIAL_ESC_FG_BLACK" |", fnet_mac_to_str(eth_hdr->destination_addr, mac_str)); fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+/\\/\\/\\/-+"); fnet_println("|(Src) "FNET_SERIAL_ESC_FG_BLUE"%17s"FNET_SERIAL_ESC_FG_BLACK" |", fnet_mac_to_str(eth_hdr->source_addr, mac_str)); fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+/\\/\\/\\/-+"); fnet_println("|(Type) 0x%04x |", fnet_ntohs(eth_hdr->type)); fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"); }
static void fnet_igmp_trace(char *str, fnet_igmp_header_t *igmp_hdr) { char ip_str[FNET_IP4_ADDR_STR_SIZE]; fnet_printf(FNET_SERIAL_ESC_FG_GREEN"%s", str); /* Print app-specific header.*/ fnet_println("[IGMP header]"FNET_SERIAL_ESC_FG_BLACK); fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"); fnet_println("|(Type) "FNET_SERIAL_ESC_FG_BLUE"0x%2x"FNET_SERIAL_ESC_FG_BLACK" |(Res Time) %3u |(Cheksum) 0x%04x |", igmp_hdr->type, igmp_hdr->max_resp_time, fnet_ntohs(igmp_hdr->checksum)); fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"); fnet_println("|(Group Addr) "FNET_SERIAL_ESC_FG_BLUE"%15s"FNET_SERIAL_ESC_FG_BLACK" |", fnet_inet_ntoa(*(struct in_addr *)(&igmp_hdr->group_addr), ip_str)); fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"); }
/************************************************************************ * NAME: fapp_bench_udp_tx * * DESCRIPTION: Start TX TCP Benchmark. ************************************************************************/ static void fapp_bench_udp_tx (struct fapp_bench_tx_params *params) { int send_result; char ip_str[FNET_IP_ADDR_STR_SIZE]; int i; int received; const struct linger linger_option ={1, /*l_onoff*/ 4 /*l_linger*/}; const unsigned long bufsize_option = FAPP_BENCH_SOCKET_BUF_SIZE; struct sockaddr foreign_addr; int exit_flag = 0; int sock_err; unsigned int option_len; fnet_shell_desc_t desc = params->desc; int packet_size = params->packet_size; int cur_packet_number; int iterations = params->iteration_number; fnet_address_family_t family = params->foreign_addr.sa_family; if(packet_size > FAPP_BENCH_BUFFER_SIZE) /* Check max size.*/ packet_size = FAPP_BENCH_BUFFER_SIZE; fapp_bench.socket_listen = SOCKET_INVALID; /* ------ Start test.----------- */ fnet_shell_println(desc, FAPP_DELIMITER_STR); fnet_shell_println(desc, " UDP TX Test" ); fnet_shell_println(desc, FAPP_DELIMITER_STR); fnet_shell_println(desc, FAPP_SHELL_INFO_FORMAT_S, "Remote IP addr", fnet_inet_ntop(family, params->foreign_addr.sa_data, ip_str, sizeof(ip_str))); fnet_shell_println(desc, FAPP_SHELL_INFO_FORMAT_D, "Remote Port", fnet_ntohs(params->foreign_addr.sa_port)); fnet_shell_println(desc, FAPP_SHELL_INFO_FORMAT_D, "Message Size", params->packet_size); fnet_shell_println(desc, FAPP_SHELL_INFO_FORMAT_D, "Num. of messages", params->packet_number); fnet_shell_println(desc, FAPP_SHELL_INFO_FORMAT_D, "Num. of iterations", params->iteration_number); fnet_shell_println(desc, FAPP_TOCANCEL_STR); fnet_shell_println(desc, FAPP_DELIMITER_STR); while(iterations--) { /* Create socket */ if((fapp_bench.socket_foreign = socket(family, SOCK_DGRAM, 0)) == SOCKET_INVALID) { FNET_DEBUG("BENCH: Socket creation error.\n"); iterations = 0; goto ERROR_1; } /* Set Socket options. */ if( /* Setup linger option. */ (setsockopt (fapp_bench.socket_foreign, SOL_SOCKET, SO_LINGER, (char *)&linger_option, sizeof(linger_option)) == SOCKET_ERROR) || /* Set socket buffer size. */ (setsockopt(fapp_bench.socket_foreign, SOL_SOCKET, SO_RCVBUF, (char *) &bufsize_option, sizeof(bufsize_option))== SOCKET_ERROR) || (setsockopt(fapp_bench.socket_foreign, SOL_SOCKET, SO_SNDBUF, (char *) &bufsize_option, sizeof(bufsize_option))== SOCKET_ERROR) ) { FNET_DEBUG("BENCH: Socket setsockopt error.\n"); iterations = 0; goto ERROR_2; } /* Bind to the server.*/ fnet_shell_println(desc,"Connecting."); foreign_addr = params->foreign_addr; if(connect(fapp_bench.socket_foreign, &foreign_addr, sizeof(foreign_addr))== FNET_ERR) { fnet_shell_println(desc, "Connection failed."); iterations = 0; goto ERROR_2; } /* Sending.*/ fnet_shell_println(desc,"Sending."); fapp_bench.bytes = 0; fapp_bench.remote_bytes = 0; cur_packet_number = 0; fapp_bench.first_time = fnet_timer_ticks(); while(1) { send_result = send( fapp_bench.socket_foreign, (char*)(&fapp_bench.buffer[0]), packet_size, 0); fapp_bench.last_time = fnet_timer_ticks(); if ( send_result == SOCKET_ERROR ) { option_len = sizeof(sock_err); getsockopt(fapp_bench.socket_foreign, SOL_SOCKET, SO_ERROR, (char*)&sock_err, &option_len); fnet_shell_println(desc, "socket_error = %d", sock_err); iterations = 0; goto ERROR_2; } else { fapp_bench.bytes += send_result; cur_packet_number ++; exit_flag = fnet_shell_ctrlc (desc); /* Check [Ctrl+c]*/ if((cur_packet_number >= params->packet_number)|| exit_flag) { if(exit_flag) { fnet_shell_println(desc, FAPP_SHELL_CANCELED_CTRL_C); iterations = 0; } break;/* => TX END. */ } } } /* Send End mark.*/ for(i=0; i < FAPP_BENCH_TX_UDP_END_ITERATIONS; i++) { unsigned long ack_bytes; /* Send END mark.*/ send( fapp_bench.socket_foreign, (char*)(&fapp_bench.buffer[0]), 1, 0); fnet_timer_delay(1); /* Check ACK. It should contain recieved amount of data.*/ received = recv(fapp_bench.socket_foreign, (char*)(&ack_bytes), sizeof(ack_bytes), 0); if(received == sizeof(ack_bytes)) /* ACK received.*/ { fapp_bench.remote_bytes = fnet_ntohl(ack_bytes); break; } else if(received == SOCKET_ERROR) { break; } else {} } /* Print benchmark results.*/ fapp_bench_print_results (desc); ERROR_2: closesocket(fapp_bench.socket_foreign); } ERROR_1: fnet_shell_println(desc, FAPP_BENCH_COMPLETED_STR); }
/************************************************************************ * NAME: fapp_bench_tcp_tx * * DESCRIPTION: Start TX TCP Benchmark. ************************************************************************/ static void fapp_bench_tcp_tx (struct fapp_bench_tx_params *params) { int send_result; char ip_str[FNET_IP_ADDR_STR_SIZE]; const struct linger linger_option ={1, /*l_onoff*/ 4 /*l_linger*/}; const unsigned long bufsize_option = FAPP_BENCH_SOCKET_BUF_SIZE; const int keepalive_option = 1; const int keepcnt_option = FAPP_BENCH_TCP_KEEPCNT; const int keepintvl_option = FAPP_BENCH_TCP_KEEPINTVL; const int keepidle_option = FAPP_BENCH_TCP_KEEPIDLE; struct sockaddr foreign_addr; int exit_flag = 0; int sock_err ; unsigned int option_len; fnet_shell_desc_t desc = params->desc; fnet_socket_state_t connection_state; int packet_size = params->packet_size; int cur_packet_number; int buffer_offset; int iterations = params->iteration_number; fnet_address_family_t family = params->foreign_addr.sa_family; if(packet_size > FAPP_BENCH_BUFFER_SIZE) /* Check max size.*/ packet_size = FAPP_BENCH_BUFFER_SIZE; fapp_bench.socket_listen = SOCKET_INVALID; /* ------ Start test.----------- */ fnet_shell_println(desc, FAPP_DELIMITER_STR); fnet_shell_println(desc, " TCP TX Test" ); fnet_shell_println(desc, FAPP_DELIMITER_STR); fnet_shell_println(desc, FAPP_SHELL_INFO_FORMAT_S, "Remote IP Addr", fnet_inet_ntop(family, params->foreign_addr.sa_data, ip_str, sizeof(ip_str))); fnet_shell_println(desc, FAPP_SHELL_INFO_FORMAT_D, "Remote Port", fnet_ntohs(params->foreign_addr.sa_port)); fnet_shell_println(desc, FAPP_SHELL_INFO_FORMAT_D, "Message Size", params->packet_size); fnet_shell_println(desc, FAPP_SHELL_INFO_FORMAT_D, "Num. of messages", params->packet_number); fnet_shell_println(desc, FAPP_SHELL_INFO_FORMAT_D, "Num. of iterations", params->iteration_number); fnet_shell_println(desc, FAPP_TOCANCEL_STR); fnet_shell_println(desc, FAPP_DELIMITER_STR); while(iterations--) { /* Create socket */ if((fapp_bench.socket_foreign = socket(family, SOCK_STREAM, 0)) == SOCKET_INVALID) { FNET_DEBUG("BENCH: Socket creation error.\n"); iterations = 0; goto ERROR_1; } /* Set Socket options. */ if( /* Setup linger option. */ (setsockopt (fapp_bench.socket_foreign, SOL_SOCKET, SO_LINGER, (char *)&linger_option, sizeof(linger_option)) == SOCKET_ERROR) || /* Set socket buffer size. */ (setsockopt(fapp_bench.socket_foreign, SOL_SOCKET, SO_RCVBUF, (char *) &bufsize_option, sizeof(bufsize_option))== SOCKET_ERROR) || (setsockopt(fapp_bench.socket_foreign, SOL_SOCKET, SO_SNDBUF, (char *) &bufsize_option, sizeof(bufsize_option))== SOCKET_ERROR) || /* Enable keepalive_option option. */ (setsockopt (fapp_bench.socket_foreign, SOL_SOCKET, SO_KEEPALIVE, (char *)&keepalive_option, sizeof(keepalive_option)) == SOCKET_ERROR) || /* Keepalive probe retransmit limit. */ (setsockopt (fapp_bench.socket_foreign, IPPROTO_TCP, TCP_KEEPCNT, (char *)&keepcnt_option, sizeof(keepcnt_option)) == SOCKET_ERROR) || /* Keepalive retransmit interval.*/ (setsockopt (fapp_bench.socket_foreign, IPPROTO_TCP, TCP_KEEPINTVL, (char *)&keepintvl_option, sizeof(keepintvl_option)) == SOCKET_ERROR) || /* Time between keepalive probes.*/ (setsockopt (fapp_bench.socket_foreign, IPPROTO_TCP, TCP_KEEPIDLE, (char *)&keepidle_option, sizeof(keepidle_option)) == SOCKET_ERROR) ) { FNET_DEBUG("BENCH: Socket setsockopt error.\n"); iterations = 0; goto ERROR_2; } /* Connect to the server.*/ fnet_shell_println(desc,"Connecting."); foreign_addr = params->foreign_addr; connect(fapp_bench.socket_foreign, (struct sockaddr *)(&foreign_addr), sizeof(foreign_addr)); do { option_len = sizeof(connection_state); getsockopt(fapp_bench.socket_foreign, SOL_SOCKET, SO_STATE, (char*)&connection_state, &option_len); } while (connection_state == SS_CONNECTING); if(connection_state != SS_CONNECTED) { fnet_shell_println(desc, "Connection failed."); iterations = 0; goto ERROR_2; } /* Sending.*/ fnet_shell_println(desc,"Sending."); fapp_bench.bytes = 0; fapp_bench.remote_bytes = 0; cur_packet_number = 0; buffer_offset = 0; fapp_bench.first_time = fnet_timer_ticks(); while(1) { send_result = send( fapp_bench.socket_foreign, (char*)(&fapp_bench.buffer[buffer_offset]), (packet_size-buffer_offset), 0); fapp_bench.last_time = fnet_timer_ticks(); if ( send_result == SOCKET_ERROR ) { option_len = sizeof(sock_err); getsockopt(fapp_bench.socket_foreign, SOL_SOCKET, SO_ERROR, (char*)&sock_err, &option_len); fnet_shell_println(desc, "Socket error = %d", sock_err); iterations = 0; #if 0 /* Print benchmark results.*/ fapp_bench_print_results (desc); #endif break; } else if(send_result) { fapp_bench.bytes += send_result; buffer_offset += send_result; if(buffer_offset == packet_size) { cur_packet_number ++; buffer_offset = 0; } exit_flag = fnet_shell_ctrlc(desc); /* Check [Ctrl+c]*/ if((cur_packet_number >= params->packet_number)|| exit_flag) { if(exit_flag) { fnet_shell_println(desc, FAPP_SHELL_CANCELED_CTRL_C); iterations = 0; } /* Print benchmark results.*/ fapp_bench_print_results (desc); break; } } else {} } ERROR_2: closesocket(fapp_bench.socket_foreign); } ERROR_1: fnet_shell_println(desc, FAPP_BENCH_COMPLETED_STR); }
/************************************************************************ * NAME: fapp_bench_udp_rx * * DESCRIPTION: Start Benchmark UDP server. ************************************************************************/ static void fapp_bench_udp_rx (fnet_shell_desc_t desc, fnet_address_family_t family, struct sockaddr *multicast_address /* optional, set to 0*/) { struct sockaddr local_addr; const unsigned long bufsize_option = FAPP_BENCH_SOCKET_BUF_SIZE; int received; char ip_str[FNET_IP_ADDR_STR_SIZE]; struct sockaddr addr; unsigned int addr_len; int is_first = 1; int exit_flag = 0; /* Create listen socket */ if((fapp_bench.socket_listen = socket(family, SOCK_DGRAM, 0)) == SOCKET_INVALID) { FNET_DEBUG("BENCH: Socket creation error.\n"); goto ERROR_1; } /*Bind.*/ fnet_memset_zero(&local_addr, sizeof(local_addr)); local_addr.sa_port = FAPP_BENCH_PORT; local_addr.sa_family = family; if(bind(fapp_bench.socket_listen, &local_addr, sizeof(local_addr)) == SOCKET_ERROR) { FNET_DEBUG("BENCH: Socket bind error.\n"); goto ERROR_2; } /* Set socket options. */ if( /* Set socket buffer size. */ (setsockopt(fapp_bench.socket_listen, SOL_SOCKET, SO_RCVBUF, (char *) &bufsize_option, sizeof(bufsize_option))== SOCKET_ERROR) || (setsockopt(fapp_bench.socket_listen, SOL_SOCKET, SO_SNDBUF, (char *) &bufsize_option, sizeof(bufsize_option))== SOCKET_ERROR) ) { FNET_DEBUG("BENCH: Socket setsockopt error.\n"); goto ERROR_2; } /* Join multicast group, if set. */ if(multicast_address) { #if FNET_CFG_IP4 if(multicast_address->sa_family == AF_INET) { struct ip_mreq mreq; /* Multicast group information.*/ mreq.imr_multiaddr.s_addr = ((struct sockaddr_in*)multicast_address)->sin_addr.s_addr; mreq.imr_interface.s_addr = FNET_HTONL(INADDR_ANY); /* Default Interface.*/ /* Join multicast group. */ if(setsockopt(fapp_bench.socket_listen, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) == SOCKET_ERROR) { FNET_DEBUG("BENCH: Joining to multicast group is failed.\n"); goto ERROR_2; } } #endif #if FNET_CFG_IP6 if(multicast_address->sa_family == AF_INET6) { struct ipv6_mreq mreq6; /* Multicast group information.*/ FNET_IP6_ADDR_COPY(&((struct sockaddr_in6*)multicast_address)->sin6_addr.s6_addr, &mreq6.ipv6imr_multiaddr.s6_addr); mreq6.ipv6imr_interface = ((struct sockaddr_in6*)multicast_address)->sin6_scope_id; /* Join multicast group. */ if(setsockopt(fapp_bench.socket_listen, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mreq6, sizeof(mreq6)) == SOCKET_ERROR) { FNET_DEBUG("BENCH: Joining to multicast group is failed.\n"); goto ERROR_2; } } #endif } /* ------ Start test.----------- */ fnet_shell_println(desc, FAPP_DELIMITER_STR); fnet_shell_println(desc, " UDP RX Test" ); fnet_shell_println(desc, FAPP_DELIMITER_STR); fapp_netif_addr_print(desc, family, fapp_default_netif, FNET_FALSE); if(multicast_address) { fnet_shell_println(desc, FAPP_SHELL_INFO_FORMAT_S, "Multicast Group", fnet_inet_ntop(multicast_address->sa_family, (char*)(multicast_address->sa_data), ip_str, sizeof(ip_str)) ); } fnet_shell_println(desc, FAPP_SHELL_INFO_FORMAT_D, "Local Port", FNET_NTOHS(FAPP_BENCH_PORT)); fnet_shell_println(desc, FAPP_TOCANCEL_STR); fnet_shell_println(desc, FAPP_DELIMITER_STR); while(exit_flag == 0) /* Main loop */ { fnet_shell_println(desc, "Waiting."); fapp_bench.bytes = 0; fapp_bench.remote_bytes = 0; addr_len = sizeof(addr); is_first = 1; while(exit_flag == 0) /* Test loop. */ { /* Receive data */ received = recvfrom (fapp_bench.socket_listen, (char*)(&fapp_bench.buffer[0]), FAPP_BENCH_BUFFER_SIZE, 0, &addr, &addr_len ); if(received >= FAPP_BENCH_UDP_END_BUFFER_LENGTH) { /* Reset timeout. */ fapp_bench.last_time = fnet_timer_ticks(); if(is_first) { if( received > FAPP_BENCH_UDP_END_BUFFER_LENGTH ) { fnet_shell_println(desc,"Receiving from %s:%d", fnet_inet_ntop(addr.sa_family, (char*)(addr.sa_data), ip_str, sizeof(ip_str)), fnet_ntohs(addr.sa_port)); fapp_bench.first_time = fnet_timer_ticks(); is_first = 0; } } else { if(received == FAPP_BENCH_UDP_END_BUFFER_LENGTH ) /* End of transfer. */ { /* Send ACK containing amount of received data.*/ unsigned long ack_bytes = fnet_htonl(fapp_bench.bytes); /* Send several times, just to be sure that it is received/not lost.*/ sendto(fapp_bench.socket_listen, (char*)(&ack_bytes), sizeof(ack_bytes), 0, (struct sockaddr*)&addr, sizeof(addr)); sendto(fapp_bench.socket_listen, (char*)(&ack_bytes), sizeof(ack_bytes), 0, (struct sockaddr*)&addr, sizeof(addr)); sendto(fapp_bench.socket_listen, (char*)(&ack_bytes), sizeof(ack_bytes), 0, (struct sockaddr*)&addr, sizeof(addr)); /* Print benchmark results.*/ fapp_bench_print_results (desc); break; } else fapp_bench.bytes += received; } } else { /* Check error. Check timeout */ if(received == SOCKET_ERROR) { fnet_shell_println(desc, "BENCH: Error (%d).", fnet_error_get()); break; } /* Check timeout. */ if((is_first == 0) && (fnet_timer_get_interval(fapp_bench.last_time, fnet_timer_ticks()) > (FAPP_UDP_TIMEOUT_MS/FNET_TIMER_PERIOD_MS))) { fnet_shell_println(desc, "BENCH: Exit on timeout."); fapp_bench_print_results (desc); break; } } exit_flag = fnet_shell_ctrlc (desc); } } ERROR_2: closesocket(fapp_bench.socket_listen); ERROR_1: fnet_shell_println(desc, FAPP_BENCH_COMPLETED_STR); }
/************************************************************************ * NAME: fapp_bench_tcp_rx * * DESCRIPTION: Start Benchmark TCP server. ************************************************************************/ static void fapp_bench_tcp_rx (fnet_shell_desc_t desc, fnet_address_family_t family) { struct sockaddr local_addr; int received; char ip_str[FNET_IP_ADDR_STR_SIZE]; struct linger linger_option ={1, /*l_onoff*/ 4 /*l_linger*/}; unsigned long bufsize_option = FAPP_BENCH_SOCKET_BUF_SIZE; int keepalive_option = 1; int keepcnt_option = FAPP_BENCH_TCP_KEEPCNT; int keepintvl_option = FAPP_BENCH_TCP_KEEPINTVL; int keepidle_option = FAPP_BENCH_TCP_KEEPIDLE; struct sockaddr foreign_addr; unsigned int addr_len; int exit_flag = 0; fapp_bench.socket_foreign = SOCKET_INVALID; /* Create listen socket */ if((fapp_bench.socket_listen = socket(family, SOCK_STREAM, 0)) == SOCKET_INVALID) { FNET_DEBUG("BENCH: Socket creation error."); goto ERROR_1; } /* Bind socket.*/ fnet_memset_zero(&local_addr, sizeof(local_addr)); local_addr.sa_port = FAPP_BENCH_PORT; local_addr.sa_family = family; if(bind(fapp_bench.socket_listen, &local_addr, sizeof(local_addr)) == SOCKET_ERROR) { FNET_DEBUG("BENCH: Socket bind error."); goto ERROR_2; } /* Set Socket options. */ if( /* Setup linger option. */ (setsockopt (fapp_bench.socket_listen, SOL_SOCKET, SO_LINGER, (char *)&linger_option, sizeof(linger_option)) == SOCKET_ERROR) || /* Set socket buffer size. */ (setsockopt(fapp_bench.socket_listen, SOL_SOCKET, SO_RCVBUF, (char *) &bufsize_option, sizeof(bufsize_option))== SOCKET_ERROR) || (setsockopt(fapp_bench.socket_listen, SOL_SOCKET, SO_SNDBUF, (char *) &bufsize_option, sizeof(bufsize_option))== SOCKET_ERROR) || /* Enable keepalive_option option. */ (setsockopt (fapp_bench.socket_listen, SOL_SOCKET, SO_KEEPALIVE, (char *)&keepalive_option, sizeof(keepalive_option)) == SOCKET_ERROR) || /* Keepalive probe retransmit limit. */ (setsockopt (fapp_bench.socket_listen, IPPROTO_TCP, TCP_KEEPCNT, (char *)&keepcnt_option, sizeof(keepcnt_option)) == SOCKET_ERROR) || /* Keepalive retransmit interval.*/ (setsockopt (fapp_bench.socket_listen, IPPROTO_TCP, TCP_KEEPINTVL, (char *)&keepintvl_option, sizeof(keepintvl_option)) == SOCKET_ERROR) || /* Time between keepalive probes.*/ (setsockopt (fapp_bench.socket_listen, IPPROTO_TCP, TCP_KEEPIDLE, (char *)&keepidle_option, sizeof(keepidle_option)) == SOCKET_ERROR) ) { FNET_DEBUG("BENCH: Socket setsockopt error.\n"); goto ERROR_2; } /* Listen. */ if(listen(fapp_bench.socket_listen, 1) == SOCKET_ERROR) { FNET_DEBUG("BENCH: Socket listen error.\n"); goto ERROR_2; } /* ------ Start test.----------- */ fnet_shell_println(desc, FAPP_DELIMITER_STR); fnet_shell_println(desc, " TCP RX Test"); fnet_shell_println(desc, FAPP_DELIMITER_STR); fapp_netif_addr_print(desc, family, fapp_default_netif, FNET_FALSE); fnet_shell_println(desc, FAPP_SHELL_INFO_FORMAT_D, "Local Port", FNET_NTOHS(FAPP_BENCH_PORT)); fnet_shell_println(desc, FAPP_TOCANCEL_STR); fnet_shell_println(desc, FAPP_DELIMITER_STR); while(exit_flag == 0) { fnet_shell_println(desc, "Waiting."); fapp_bench.bytes = 0; fapp_bench.remote_bytes = 0; if(fapp_bench.socket_foreign != SOCKET_INVALID) { closesocket(fapp_bench.socket_foreign); fapp_bench.socket_foreign = SOCKET_INVALID; } while((fapp_bench.socket_foreign == SOCKET_INVALID) && (exit_flag == 0)) { /*Accept*/ addr_len = sizeof(foreign_addr); fapp_bench.socket_foreign = accept(fapp_bench.socket_listen, &foreign_addr, &addr_len); exit_flag = fnet_shell_ctrlc (desc); if(fapp_bench.socket_foreign != SOCKET_INVALID) { fnet_shell_println(desc,"Receiving from %s:%d", fnet_inet_ntop(foreign_addr.sa_family, (char*)(foreign_addr.sa_data), ip_str, sizeof(ip_str)), fnet_ntohs(foreign_addr.sa_port)); fapp_bench.first_time = fnet_timer_ticks(); while(1) /* Receiving data.*/ { received = recv(fapp_bench.socket_foreign, (char*)(&fapp_bench.buffer[0]), FAPP_BENCH_BUFFER_SIZE, 0); if ((received == SOCKET_ERROR) || exit_flag) { fapp_bench.last_time = fnet_timer_ticks(); /* Print benchmark results.*/ fapp_bench_print_results (desc); break; } else { fapp_bench.bytes += received; } exit_flag = fnet_shell_ctrlc (desc); /* Check [Ctrl+c]*/ } } } } closesocket(fapp_bench.socket_foreign); ERROR_2: closesocket(fapp_bench.socket_listen); ERROR_1: fnet_shell_println(desc, FAPP_BENCH_COMPLETED_STR); }
/************************************************************************ * NAME: fnet_telnet_state_machine * * DESCRIPTION: Telnet server state machine. ************************************************************************/ static void fnet_telnet_state_machine( void *telnet_if_p ) { struct sockaddr foreign_addr; int res; struct fnet_telnet_if *telnet = (struct fnet_telnet_if *)telnet_if_p; char rx_data[1]; int len; int i; struct fnet_telnet_session_if *session; for(i=0; i<FNET_CFG_TELNET_SESSION_MAX; i++) { session = &telnet->session[i]; telnet->session_active = session; do { switch(session->state) { /*---- LISTENING ------------------------------------------------*/ case FNET_TELNET_STATE_LISTENING: len = sizeof(foreign_addr); session->socket_foreign = accept(telnet->socket_listen, (struct sockaddr *) &foreign_addr, &len); if(session->socket_foreign != SOCKET_INVALID) { #if FNET_CFG_DEBUG_TELNET { char ip_str[FNET_IP_ADDR_STR_SIZE]; fnet_inet_ntop(foreign_addr.sa_family, foreign_addr.sa_data, ip_str, sizeof(ip_str)); FNET_DEBUG_TELNET("\nTELNET: New connection: %s; Port: %d.", ip_str, fnet_ntohs(foreign_addr.sa_port)); } #endif /* Init Shell. */ session->shell_descriptor = fnet_shell_init(&session->shell_params); if(session->shell_descriptor == FNET_ERR) { session->shell_descriptor = 0; FNET_DEBUG_TELNET("TELNET: Shell Service registration error."); session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */ } else { listen(telnet->socket_listen, --telnet->backlog); /* Ignor other connections.*/ /* Reset TX timeout. */ session->state = FNET_TELNET_STATE_RECEIVING; /* => WAITING data */ } } break; /*---- NORMAL -----------------------------------------------*/ case FNET_TELNET_STATE_RECEIVING: if(rx_buffer_free_space(session)>0) { res = recv(session->socket_foreign, rx_data, 1, 0); if(res == 1) { if(rx_data[0] == FNET_TELNET_CMD_IAC ) { session->state = FNET_TELNET_STATE_IAC; /*=> Handle IAC */ } else { rx_buffer_write (session, rx_data[0]); } } else if (res == SOCKET_ERROR) { session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */ } } break; /*---- IAC -----------------------------------------------*/ case FNET_TELNET_STATE_IAC: FNET_DEBUG_TELNET("TELNET: STATE_IAC"); if((res = recv(session->socket_foreign, rx_data, 1, 0) )!= SOCKET_ERROR) { if(res) { switch(rx_data[0]) { case FNET_TELNET_CMD_WILL: session->state = FNET_TELNET_STATE_DONT; break; case FNET_TELNET_CMD_DO: session->state = FNET_TELNET_STATE_WONT; break; case FNET_TELNET_CMD_WONT: case FNET_TELNET_CMD_DONT: session->state = FNET_TELNET_STATE_SKIP ; break; case FNET_TELNET_CMD_IAC: /* the IAC need be doubled to be sent as data, and the other 255 codes may be passed transparently. */ rx_buffer_write (session, rx_data[0]); default: session->state = FNET_TELNET_STATE_RECEIVING; /*=> Ignore commands */ } } } else { session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */ } break; /*---- DONT & WONT -----------------------------------------------*/ case FNET_TELNET_STATE_DONT: case FNET_TELNET_STATE_WONT: { char command; if(session->state == FNET_TELNET_STATE_DONT) { FNET_DEBUG_TELNET("TELNET: STATE_DONT"); command = FNET_TELNET_CMD_DONT; } else { FNET_DEBUG_TELNET("TELNET: STATE_WONT"); command = FNET_TELNET_CMD_WONT; } if(tx_buffer_free_space(session) >= 3) { res = recv(session->socket_foreign, rx_data, 1, 0); if(res == 1) { /* Send command. */ fnet_telnet_send_cmd(session, command, rx_data[0]); session->state = FNET_TELNET_STATE_RECEIVING; } else if (res == SOCKET_ERROR) { session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */ } } } break; /*---- SKIP -----------------------------------------------*/ case FNET_TELNET_STATE_SKIP: FNET_DEBUG_TELNET("TELNET: STATE_SKIP"); res = recv(session->socket_foreign, rx_data, 1, 0); if(res == 1) { session->state = FNET_TELNET_STATE_RECEIVING; } else if (res == SOCKET_ERROR) { session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */ } break; /*---- CLOSING --------------------------------------------*/ case FNET_TELNET_STATE_CLOSING: FNET_DEBUG_TELNET("TELNET: STATE_CLOSING"); if(session->shell_descriptor) { fnet_shell_release(session->shell_descriptor); session->shell_descriptor = 0; } session->rx_buffer_head = session->rx_buffer; session->rx_buffer_tail = session->rx_buffer; closesocket(session->socket_foreign); session->socket_foreign = SOCKET_INVALID; listen(telnet->socket_listen, ++telnet->backlog); /* Allow connection.*/ session->state = FNET_TELNET_STATE_LISTENING; /*=> LISTENING */ break; default: break; } } while(session->state == FNET_TELNET_STATE_CLOSING); } }
/************************************************************************ * NAME: fnet_dns_state_machine * * DESCRIPTION: DNS-client state machine. ************************************************************************/ static void fnet_dns_state_machine( void *fnet_dns_if_p ) { int sent_size; int received; unsigned int i; fnet_dns_header_t *header; fnet_dns_rr_header_t *rr_header; fnet_dns_if_t *dns_if = (fnet_dns_if_t *)fnet_dns_if_p; switch(dns_if->state) { /*---- TX --------------------------------------------*/ case FNET_DNS_STATE_TX: FNET_DEBUG_DNS("Sending query..."); sent_size = send(dns_if->socket_cln, dns_if->message, dns_if->message_size, 0U); if (sent_size != (int)dns_if->message_size) { dns_if->state = FNET_DNS_STATE_RELEASE; /* ERROR */ } else { dns_if->last_time = fnet_timer_ticks(); dns_if->state = FNET_DNS_STATE_RX; } break; /*---- RX -----------------------------------------------*/ case FNET_DNS_STATE_RX: /* Receive data */ received = recv(dns_if->socket_cln, dns_if->message, sizeof(dns_if->message), 0U); if(received > 0 ) { header = (fnet_dns_header_t *)fnet_dns_if.message; if((header->id == dns_if->id) && /* Check the ID.*/ ((header->flags & FNET_DNS_HEADER_FLAGS_QR)==FNET_DNS_HEADER_FLAGS_QR)) /* Is response.*/ { for (i=(sizeof(fnet_dns_header_t)-1U); i < (unsigned int)received; i++) { /* [RFC1035 4.1.4.] In order to reduce the size of messages, the domain system utilizes a * compression scheme which eliminates the repetition of domain names in a * message. In this scheme, an entire domain name or a list of labels at * the end of a domain name is replaced with a pointer to a prior occurance * of the same name. * The pointer takes the form of a two octet sequence: * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | 1 1| OFFSET | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ /* => Check for 0xC0. */ if ((unsigned char)dns_if->message[i] == FNET_DNS_NAME_COMPRESSED_MASK) /* look for the beginnig of the response (Question Name == 192 (label compression))*/ { rr_header = (fnet_dns_rr_header_t *)&dns_if->message[i]; /* Check Question Type, Class and Resource Data Length. */ if ( (rr_header->type == dns_if->dns_type) && (rr_header->rr_class == FNET_HTONS(FNET_DNS_HEADER_CLASS_IN))) { /* Resolved.*/ if(rr_header->type == FNET_HTONS(FNET_DNS_TYPE_A)) { dns_if->resolved_ip4_addr[dns_if->addr_number].ip4_addr = *((fnet_ip4_addr_t*)(&rr_header->rdata)); dns_if->resolved_ip4_addr[dns_if->addr_number].ttl = rr_header->ttl; } else /* AF_INET6 */ { FNET_IP6_ADDR_COPY( (fnet_ip6_addr_t*)(&rr_header->rdata), &dns_if->resolved_ip6_addr[dns_if->addr_number].ip6_addr ); dns_if->resolved_ip6_addr[dns_if->addr_number].ttl = rr_header->ttl; } dns_if->addr_number++; } i+=(unsigned int)(sizeof(fnet_dns_rr_header_t)+fnet_ntohs(rr_header->rdlength)-4U-1U); } } } /* else = wrong message.*/ dns_if->state = FNET_DNS_STATE_RELEASE; } else if(received == SOCKET_ERROR) /* Check error.*/ { dns_if->state = FNET_DNS_STATE_RELEASE; /* ERROR */ } else /* No data. Check timeout */ if(fnet_timer_get_interval(dns_if->last_time, fnet_timer_ticks()) > ((FNET_CFG_DNS_RETRANSMISSION_TIMEOUT*1000U)/FNET_TIMER_PERIOD_MS)) { dns_if->iteration++; if(dns_if->iteration > FNET_CFG_DNS_RETRANSMISSION_MAX) { dns_if->state = FNET_DNS_STATE_RELEASE; /* ERROR */ } else { dns_if->state = FNET_DNS_STATE_TX; } } else {} break; /*---- RELEASE -------------------------------------------------*/ case FNET_DNS_STATE_RELEASE: { struct fnet_dns_resolved_addr *addr_list = FNET_NULL; fnet_dns_release(); /* Fill fnet_dns_resolved_addr */ if(dns_if->addr_number > 0) { if(dns_if->addr_family == AF_INET) { for(i=0; i<dns_if->addr_number; i++) { fnet_memset_zero(&dns_if->resolved_ip4_addr_sock[i].resolved_addr, sizeof(dns_if->resolved_ip4_addr_sock[i].resolved_addr)); dns_if->resolved_ip4_addr_sock[i].resolved_addr.sa_family = AF_INET; ((struct sockaddr_in*)(&dns_if->resolved_ip4_addr_sock[i].resolved_addr))->sin_addr.s_addr = dns_if->resolved_ip4_addr[i].ip4_addr; dns_if->resolved_ip4_addr_sock[i].resolved_addr_ttl = dns_if->resolved_ip4_addr[i].ttl; } addr_list = dns_if->resolved_ip4_addr_sock; } else if(dns_if->addr_family == AF_INET6) { for(i=0; i<dns_if->addr_number; i++) { fnet_memset_zero(&dns_if->resolved_ip6_addr_sock[i].resolved_addr, sizeof(dns_if->resolved_ip4_addr_sock[i].resolved_addr)); dns_if->resolved_ip6_addr_sock[i].resolved_addr.sa_family = AF_INET6; FNET_IP6_ADDR_COPY(&dns_if->resolved_ip6_addr[i].ip6_addr, &((struct sockaddr_in6*)(&dns_if->resolved_ip6_addr_sock[i].resolved_addr))->sin6_addr.s6_addr); dns_if->resolved_ip6_addr_sock[i].resolved_addr_ttl = dns_if->resolved_ip6_addr[i].ttl; } addr_list = dns_if->resolved_ip6_addr_sock; } else {} } dns_if->handler(addr_list, dns_if->addr_number, dns_if->handler_cookie); /* User Callback.*/ } break; default: break; } }
/************************************************************************ * NAME: fnet_http_state_machine * * DESCRIPTION: Http server state machine. ************************************************************************/ static void fnet_http_state_machine( void *http_if_p ) { struct sockaddr foreign_addr; int len; int res; struct fnet_http_if *http = (struct fnet_http_if *)http_if_p; int iteration; char *ch; int i; struct fnet_http_session_if *session; for(i=0; i<FNET_CFG_HTTP_SESSION_MAX; i++) { session = &http->session[i]; http->session_active = session; for(iteration = 0; iteration < FNET_HTTP_ITERATION_NUMBER; iteration++) { switch(session->state) { /*---- LISTENING ------------------------------------------------*/ case FNET_HTTP_STATE_LISTENING: len = sizeof(foreign_addr); if((session->socket_foreign = accept(http->socket_listen, &foreign_addr, &len)) != SOCKET_INVALID) { #if FNET_CFG_DEBUG_HTTP { char ip_str[FNET_IP_ADDR_STR_SIZE]; fnet_inet_ntop(foreign_addr.sa_family, (char*)(foreign_addr.sa_data), ip_str, sizeof(ip_str)); FNET_DEBUG_HTTP(""); FNET_DEBUG_HTTP("HTTP: RX Request From: %s; Port: %d.", ip_str, fnet_ntohs(foreign_addr.sa_port)); } #endif /* Reset response & request parameters.*/ fnet_memset_zero(&session->response, sizeof(struct fnet_http_response)); fnet_memset_zero(&session->request, sizeof(struct fnet_http_request)); #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/ session->response.content_length = -1; /* No content length by default.*/ /* Default HTTP version response.*/ session->response.version.major = FNET_HTTP_VERSION_MAJOR; session->response.version.minor = FNET_HTTP_VERSION_MINOR; session->response.tx_data = fnet_http_tx_status_line; #endif session->state_time = fnet_timer_ticks(); /* Reset timeout. */ session->buffer_actual_size = 0; session->state = FNET_HTTP_STATE_RX_REQUEST; /* => WAITING HTTP REQUEST */ } break; /*---- RX_LINE -----------------------------------------------*/ case FNET_HTTP_STATE_RX_REQUEST: do { /* Read character by character.*/ ch = &session->buffer[session->buffer_actual_size]; if((res = recv(session->socket_foreign, ch, 1, 0) )!= SOCKET_ERROR) { if(res > 0) /* Received a data.*/ { session->state_time = fnet_timer_ticks(); /* Reset timeout.*/ session->buffer_actual_size++; if(*ch == '\r') *ch = '\0'; else if(*ch == '\n') /* Line received.*/ { char * req_buf = &session->buffer[0]; *ch = '\0'; if(session->request.method == 0) /* Parse Request line.*/ { const struct fnet_http_method **method = &fnet_http_method_list[0]; FNET_DEBUG_HTTP("HTTP: RX Request: %s", req_buf); /* Determine the method type. */ while(*method) { if ( !fnet_strcmp_splitter(req_buf, (*method)->token, ' ') ) { req_buf+=fnet_strlen((*method)->token); session->request.method = *method; break; } method++; } /* Check if the method is supported? */ if(session->request.method && session->request.method->handle) { /* Parse URI.*/ req_buf = fnet_http_uri_parse(req_buf, &session->request.uri); FNET_DEBUG_HTTP("HTTP: URI Path = %s; Query = %s", http->request.uri.path, http->request.uri.query); #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/ /* Parse HTTP/x.x version.*/ fnet_http_version_parse(++req_buf, &session->response.version); /* Check the highest supported HTTP version.*/ if(((session->response.version.major<<8)|session->response.version.minor) > ((FNET_HTTP_VERSION_MAJOR<<8)|FNET_HTTP_VERSION_MINOR)) { session->response.version.major = FNET_HTTP_VERSION_MAJOR; session->response.version.minor = FNET_HTTP_VERSION_MINOR; } if(session->response.version.major == 0) /* HTTP/0.x */ { session->state = FNET_HTTP_STATE_CLOSING; /* Client does not support HTTP/1.x*/ break; } #if FNET_CFG_HTTP_AUTHENTICATION_BASIC /* Check Authentification.*/ fnet_http_auth_validate_uri(http); #endif #endif/*FNET_CFG_HTTP_VERSION_MAJOR*/ /* Call method initial handler.*/ res = session->request.method->handle(http, &session->request.uri); #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/ if(fnet_http_status_ok(res) == FNET_OK) #else if((res == FNET_OK)) #endif { #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/ session->buffer_actual_size = 0; /* => Parse Header line.*/ #else /* HTTP/0.9 */ session->response.tx_data = session->request.method->send; /* Reset buffer pointers.*/ session->buffer_actual_size = 0; session->state = FNET_HTTP_STATE_TX; /* Send data.*/ #endif } /* Method error.*/ else /* Error.*/ { #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/ /* Default code = FNET_HTTP_STATUS_CODE_INTERNAL_SERVER_ERROR. */ if(res != FNET_ERR) session->response.status.code = (fnet_http_status_code_t)res; /* Send status line.*/ session->buffer_actual_size = 0; session->state = FNET_HTTP_STATE_TX; /* Send error.*/ #else /* HTTP/0.9 */ session->state = FNET_HTTP_STATE_CLOSING; #endif } } /* Method is not supported.*/ else /* Error.*/ { #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/ session->response.status.code = FNET_HTTP_STATUS_CODE_NOT_IMPLEMENTED; /* Send status line.*/ session->buffer_actual_size = 0; session->state = FNET_HTTP_STATE_TX; /* Send error.*/ #else /* HTTP/0.9 */ session->state = FNET_HTTP_STATE_CLOSING; #endif } } #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/ /* Parse Header line.*/ else { if(session->request.skip_line == 0) { if(*req_buf == 0) /* === Empty line => End of the request header. ===*/ { #if FNET_CFG_HTTP_AUTHENTICATION_BASIC if(session->response.auth_entry) /* Send UNAUTHORIZED error.*/ session->response.status.code = FNET_HTTP_STATUS_CODE_UNAUTHORIZED; else /* Send Data.*/ #endif session->response.status.code = FNET_HTTP_STATUS_CODE_OK; #if FNET_CFG_HTTP_POST if(session->request.content_length > 0) /* RX Entity-Body.*/ { session->buffer_actual_size = 0; session->state = FNET_HTTP_STATE_RX; } else #endif /* TX Full-Responce.*/ { /* Send status line.*/ session->buffer_actual_size = 0; session->state = FNET_HTTP_STATE_TX; } break; } else /* === Parse header fields. ===*/ { FNET_DEBUG_HTTP("HTTP: RX Header: %s", req_buf); #if FNET_CFG_HTTP_AUTHENTICATION_BASIC /* --- Authorization: ---*/ if (session->response.auth_entry && fnet_strncmp(req_buf, FNET_HTTP_HEADER_FIELD_AUTHORIZATION, sizeof(FNET_HTTP_HEADER_FIELD_AUTHORIZATION)-1) == 0) /* Authetication is required.*/ { char *auth_str = &req_buf[sizeof(FNET_HTTP_HEADER_FIELD_AUTHORIZATION)-1]; /* Validate credentials.*/ if(fnet_http_auth_validate_credentials(http, auth_str) == FNET_OK) session->response.auth_entry = 0; /* Authorization is succesful.*/ } #endif #if FNET_CFG_HTTP_POST /* --- Content-Length: ---*/ if (session->request.method->receive && fnet_strncmp(req_buf, FNET_HTTP_HEADER_FIELD_CONTENT_LENGTH, sizeof(FNET_HTTP_HEADER_FIELD_CONTENT_LENGTH)-1) == 0) { char *p; char *length_str = &req_buf[sizeof(FNET_HTTP_HEADER_FIELD_CONTENT_LENGTH)-1]; session->request.content_length = (long)fnet_strtoul(length_str,&p,10); } #endif } } /* Line is skiped.*/ else session->request.skip_line = 0; /* Reset the Skip flag.*/ session->buffer_actual_size = 0; /* => Parse Next Header line.*/ } #endif/* FNET_CFG_HTTP_VERSION_MAJOR */ } /* Not whole line received yet.*/ else if (session->buffer_actual_size == FNET_HTTP_BUF_SIZE) /* Buffer is full.*/ { #if FNET_CFG_HTTP_VERSION_MAJOR /* HTTP/1.x*/ if(session->request.method != 0) /* For header, skip the line.*/ { /* Skip line.*/ session->request.skip_line = 1; session->buffer_actual_size = 0; } else /* Error.*/ { /* Default code = FNET_HTTP_STATUS_CODE_INTERNAL_SERVER_ERROR. */ session->buffer_actual_size = 0; session->state = FNET_HTTP_STATE_TX; /* Send error.*/ } #else /* HTTP/0.9 */ session->state = FNET_HTTP_STATE_CLOSING; #endif } } /* No data.*/ else if(fnet_timer_get_interval(session->state_time, fnet_timer_ticks()) /* Time out? */ > (FNET_HTTP_WAIT_RX_MS / FNET_TIMER_PERIOD_MS)) { session->state = FNET_HTTP_STATE_CLOSING; /*=> CLOSING */ } /* else => WAITING REQUEST. */ } /* recv() error.*/ else { session->state = FNET_HTTP_STATE_CLOSING; /*=> CLOSING */ } } while ((res > 0) && (session->state == FNET_HTTP_STATE_RX_REQUEST)); /* Till receiving the request header.*/ break; #if FNET_CFG_HTTP_POST /*---- RX --------------------------------------------------*/ case FNET_HTTP_STATE_RX: /* Receive data (Entity-Body). */ if((res = recv(session->socket_foreign, &session->buffer[session->buffer_actual_size], (int)(FNET_HTTP_BUF_SIZE-session->buffer_actual_size), 0) )!= SOCKET_ERROR) { session->buffer_actual_size += res; session->request.content_length -= res; if(res > 0) /* Some Data.*/ { session->state_time = fnet_timer_ticks(); /* Reset timeout.*/ res = session->request.method->receive(http); if(fnet_http_status_ok(res) != FNET_OK) { if(res != FNET_ERR) session->response.status.code = (fnet_http_status_code_t)res; else session->response.status.code = FNET_HTTP_STATUS_CODE_INTERNAL_SERVER_ERROR; session->request.content_length = 0; } if(session->request.content_length <= 0) /* The last data.*/ { session->state = FNET_HTTP_STATE_TX; /* Send data.*/ } session->buffer_actual_size = 0; } else /* No Data.*/ { if(fnet_timer_get_interval(session->state_time, fnet_timer_ticks()) > (FNET_HTTP_WAIT_RX_MS / FNET_TIMER_PERIOD_MS)) /* Time out.*/ { session->state = FNET_HTTP_STATE_CLOSING; /*=> CLOSING */ } } } else /* Socket error.*/ { session->state = FNET_HTTP_STATE_CLOSING; /*=> CLOSING */ } break; #endif /* FNET_CFG_HTTP_POST.*/ /*---- TX --------------------------------------------------*/ case FNET_HTTP_STATE_TX: /* Send data. */ if(fnet_timer_get_interval(session->state_time, fnet_timer_ticks()) < (FNET_HTTP_WAIT_TX_MS / FNET_TIMER_PERIOD_MS)) /* Check timeout */ { int send_size; if(session->buffer_actual_size == session->response.buffer_sent) { /* Reset counters.*/ session->buffer_actual_size =0; session->response.buffer_sent = 0; if(session->response.send_eof || session->response.tx_data(http) == FNET_ERR) /* get data for sending */ { session->state = FNET_HTTP_STATE_CLOSING; /*=> CLOSING */ break; } } send_size = (int)(session->buffer_actual_size - (int)session->response.buffer_sent); if(send_size > http->send_max) send_size = (int)http->send_max; if((res = send(session->socket_foreign, session->buffer + session->response.buffer_sent, send_size, 0)) != SOCKET_ERROR) { if(res) { FNET_DEBUG_HTTP("HTTP: TX %d bytes.", res); session->state_time = fnet_timer_ticks(); /* reset timeout */ session->response.buffer_sent += res; } break; /* => SENDING */ } } session->state = FNET_HTTP_STATE_CLOSING; /*=> CLOSING */ break; /*---- CLOSING --------------------------------------------------*/ case FNET_HTTP_STATE_CLOSING: if(session->request.method && session->request.method->close) session->request.method->close(http); closesocket(session->socket_foreign); session->socket_foreign = SOCKET_INVALID; session->state = FNET_HTTP_STATE_LISTENING; /*=> LISTENING */ break; default: break; } } } /*for(sessions)*/ }
/************************************************************************ * NAME: fnet_udp_input * * DESCRIPTION: UDP input function. *************************************************************************/ static void fnet_udp_input(fnet_netif_t *netif, struct sockaddr *foreign_addr, struct sockaddr *local_addr, fnet_netbuf_t *nb, fnet_netbuf_t *ip_nb) { fnet_udp_header_t *udp_header = (fnet_udp_header_t *)nb->data_ptr; fnet_socket_if_t *sock; fnet_socket_if_t *last; fnet_size_t udp_length; fnet_netbuf_t *nb_tmp; if((netif != 0) && (nb != 0)) { /* The header must reside in contiguous area of memory.*/ if(fnet_netbuf_pullup(&nb, sizeof(fnet_udp_header_t)) == FNET_ERR) { goto BAD; } udp_length = fnet_ntohs(udp_header->length); if(nb->total_length >= udp_length) /* Check the amount of data.*/ { if(nb->total_length > udp_length) { /* Logical size and the physical size of the packet should be the same.*/ fnet_netbuf_trim(&nb, (fnet_int32_t)(udp_length - nb->total_length)); } #if FNET_CFG_UDP_CHECKSUM if((udp_header->checksum != 0u) #if FNET_CFG_CPU_ETH_HW_RX_PROTOCOL_CHECKSUM || FNET_CFG_CPU_ETH_HW_TX_PROTOCOL_CHECKSUM && ((nb->flags & FNET_NETBUF_FLAG_HW_PROTOCOL_CHECKSUM) == 0) #endif ) { fnet_uint16_t sum; sum = fnet_checksum_pseudo_start( nb, FNET_HTONS((fnet_uint16_t)FNET_IP_PROTOCOL_UDP), (fnet_uint16_t)udp_length ); sum = fnet_checksum_pseudo_end( sum, &foreign_addr->sa_data[0], &local_addr->sa_data[0], (fnet_size_t)((local_addr->sa_family == AF_INET) ? sizeof(fnet_ip4_addr_t) : sizeof(fnet_ip6_addr_t))); if(sum) { goto BAD; } } #endif fnet_udp_trace("RX", udp_header); /* Trace UDP header.*/ local_addr->sa_port = udp_header->destination_port; foreign_addr->sa_port = udp_header->source_port; fnet_netbuf_trim(&nb, (fnet_int32_t)sizeof(fnet_udp_header_t)); /* Demultiplex broadcast & multicast datagrams.*/ if((fnet_socket_addr_is_broadcast(local_addr, netif)) || (fnet_socket_addr_is_multicast(local_addr))) { last = 0; for (sock = fnet_udp_prot_if.head; sock != 0; sock = sock->next) { /* Compare local port number.*/ if(sock->local_addr.sa_port != local_addr->sa_port) { continue; /* => ignore.*/ } #if FNET_CFG_MULTICAST if(fnet_socket_addr_is_multicast(local_addr)) { fnet_index_t m; fnet_bool_t for_us = FNET_FALSE; #if FNET_CFG_IP4 if(local_addr->sa_family == AF_INET) { for(m = 0u; m < FNET_CFG_MULTICAST_SOCKET_MAX; m++) { if(sock->ip4_multicast_entry[m]) { if((sock->ip4_multicast_entry[m]->group_addr == ((struct sockaddr_in *)(local_addr))->sin_addr.s_addr) && (sock->ip4_multicast_entry[m]->netif == netif )) { for_us = FNET_TRUE; } } } } else #endif #if FNET_CFG_IP6 if(local_addr->sa_family == AF_INET6) { for(m=0u; m < FNET_CFG_MULTICAST_SOCKET_MAX; m++) { if(sock->ip6_multicast_entry[m]) { if(FNET_IP6_ADDR_EQUAL(&sock->ip6_multicast_entry[m]->group_addr, &((struct sockaddr_in6 *)(local_addr))->sin6_addr.s6_addr) && (sock->ip6_multicast_entry[m]->netif == netif)) { for_us = FNET_TRUE; } } } } else #endif {} if(for_us == FNET_FALSE) { continue; } } else #endif /* FNET_CFG_MULTICAST */ { /* Compare local address.*/ if(!fnet_socket_addr_is_unspecified(&sock->local_addr)) { if(!fnet_socket_addr_are_equal(&sock->local_addr, local_addr)) { continue; } } /* Compare foreign address and port number.*/ if(!fnet_socket_addr_is_unspecified(&sock->foreign_addr)) { if((!fnet_socket_addr_are_equal(&sock->foreign_addr, foreign_addr)) || (sock->foreign_addr.sa_port != foreign_addr->sa_port)) { continue; } } } if((last != 0) && (last->receive_buffer.is_shutdown == FNET_FALSE)) { if((nb_tmp = fnet_netbuf_copy(nb, 0u, FNET_NETBUF_COPYALL, FNET_FALSE)) != 0) { if(fnet_socket_buffer_append_address(&(last->receive_buffer), nb_tmp, foreign_addr) == FNET_ERR) { fnet_netbuf_free_chain(nb_tmp); } } } last = sock; } if(last == 0) { goto BAD; } if(last->receive_buffer.is_shutdown) /* Is shutdown.*/ { goto BAD; } if(fnet_socket_buffer_append_address(&(last->receive_buffer), nb, foreign_addr) == FNET_ERR) { goto BAD; } fnet_netbuf_free_chain(ip_nb); } else /* For unicast datagram.*/ { sock = fnet_socket_lookup(fnet_udp_prot_if.head, local_addr, foreign_addr, FNET_IP_PROTOCOL_UDP); if(sock) { if(sock->receive_buffer.is_shutdown) /* Is shutdown.*/ { goto BAD; } if(fnet_socket_buffer_append_address(&(sock->receive_buffer), nb, foreign_addr) == FNET_ERR) { goto BAD; } fnet_netbuf_free_chain(ip_nb); } else { fnet_netbuf_free_chain(nb); /* No match was found, send ICMP destination port unreachable.*/ #if FNET_CFG_IP4 if(local_addr->sa_family == AF_INET) { fnet_icmp_error(netif, FNET_ICMP_UNREACHABLE, FNET_ICMP_UNREACHABLE_PORT, ip_nb); }else #endif #if FNET_CFG_IP6 if(local_addr->sa_family == AF_INET6) { fnet_icmp6_error(netif, FNET_ICMP6_TYPE_DEST_UNREACH, FNET_ICMP6_CODE_DU_PORT_UNREACH, 0u, ip_nb ); }else #endif {} } } } else { goto BAD; } } else { BAD: fnet_netbuf_free_chain(ip_nb); fnet_netbuf_free_chain(nb); } }