/**@brief Callback handler to receive data on UDP port. * * @param[in] p_socket Socket identifier. * @param[in] p_ip_header IPv6 header containing source and destination addresses. * @param[in] p_udp_header UDP header identifying local and remote endpoints. * @param[in] process_result Result of data reception, there could be possible errors like * invalid checksum etc. * @param[in] iot_pbuffer_t Packet buffer containing the received data packet. * * @retval NRF_SUCCESS Indicates received data was handled successfully, else an error * code indicating reason for failure. */ uint32_t rx_udp_port_app_handler(const udp6_socket_t * p_socket, const ipv6_header_t * p_ip_header, const udp6_header_t * p_udp_header, uint32_t process_result, iot_pbuffer_t * p_rx_packet) { // APPL_LOG("[APPL]: Got UDP6 data on socket 0x%08lx\r\n", p_socket->socket_id); // APPL_LOG("[APPL]: Source IPv6 Address: "); // APPL_ADDR(p_ip_header->srcaddr); APP_ERROR_CHECK(process_result); // Print PORTs // APPL_LOG("[APPL]: UDP Destination port: %lx\r\n", HTONS(p_udp_header->destport)); // APPL_LOG("[APPL]: UDP Source port: %lx\r\n", HTONS(p_udp_header->srcport)); // UDP packet received from the Client node. APPL_LOG("[APPL]: Received UDP packet sequence number: %ld\r\n", \ uint32_decode(&p_rx_packet->p_payload[0])); iot_pbuffer_alloc_param_t pbuff_param; iot_pbuffer_t * p_tx_buffer; pbuff_param.flags = PBUFFER_FLAG_DEFAULT; pbuff_param.type = UDP6_PACKET_TYPE; pbuff_param.length = p_rx_packet->length; // Allocate packet buffer. uint32_t err_code = iot_pbuffer_allocate(&pbuff_param, &p_tx_buffer); APP_ERROR_CHECK(err_code); memcpy(p_tx_buffer->p_payload, p_rx_packet->p_payload, p_rx_packet->length); // Send back the received packet payload without any modification. err_code = udp6_socket_sendto(&m_udp_socket, &p_ip_header->srcaddr, HTONS(UDP_PORT), p_tx_buffer); APP_ERROR_CHECK(err_code); m_display_state = LEDS_TX_UDP_PACKET; m_udp_tx_occured = true; return NRF_SUCCESS; }
/**@brief Timer callback used for transmitting Echo Request and UDP6 packets depending on * application state. * * @param[in] p_context Pointer used for passing context. No context used in this application. */ static void tx_timeout_handler(void * p_context) { uint32_t err_code; switch (m_node_state) { case APP_STATE_IPV6_IF_DOWN: { return; } case APP_STATE_IPV6_IF_UP: { APPL_LOG("[APPL]: Ping remote node. \r\n"); iot_pbuffer_alloc_param_t pbuff_param; iot_pbuffer_t * p_buffer; pbuff_param.flags = PBUFFER_FLAG_DEFAULT; pbuff_param.type = ICMP6_PACKET_TYPE; pbuff_param.length = ICMP6_ECHO_REQUEST_PAYLOAD_OFFSET + 10; // Allocate packet buffer. err_code = iot_pbuffer_allocate(&pbuff_param, &p_buffer); APP_ERROR_CHECK(err_code); ipv6_addr_t dest_ipv6_addr; memcpy(&dest_ipv6_addr.u8[0], (uint8_t[]){SERVER_IPV6_ADDRESS}, IPV6_ADDR_SIZE); iot_interface_t * p_interface; ipv6_addr_t src_ipv6_addr; err_code = ipv6_address_find_best_match(&p_interface, &src_ipv6_addr, &dest_ipv6_addr); APP_ERROR_CHECK(err_code); memset(p_buffer->p_payload + ICMP6_ECHO_REQUEST_PAYLOAD_OFFSET, 'A', 10); // Send Echo Request to peer. err_code = icmp6_echo_request(p_interface, &src_ipv6_addr, &dest_ipv6_addr, p_buffer); APP_ERROR_CHECK(err_code); err_code = app_timer_start(m_tx_node_timer, APP_PING_INTERVAL, NULL); APP_ERROR_CHECK(err_code); break; } case APP_STATE_PEER_REACHABLE: { uint32_t ind_buff = 0; err_code = get_packet_buffer_index(&ind_buff, (uint32_t *)&m_invalid_pkt_seq_num); if (err_code == NRF_ERROR_NOT_FOUND) { // Buffer of expected packets full, checking if peer is reachable. APPL_LOG("[APPL]: %ld packets transmitted, %d packets lost. Resetting counter. \r\n", \ m_pkt_seq_num, PACKET_BUFFER_LEN); m_node_state = APP_STATE_IPV6_IF_UP; m_display_state = LEDS_TX_ECHO_REQUEST; m_pkt_seq_num = 0; memset(&m_packet_buffer[0][0], 0x00, sizeof(m_packet_buffer)); err_code = app_timer_start(m_tx_node_timer, APP_PING_INTERVAL, NULL); APP_ERROR_CHECK(err_code); return; } ++m_pkt_seq_num; if (m_pkt_seq_num == INVALID_PACKET_SEQ_NUMBER) { ++m_pkt_seq_num; } test_packet_payload_t packet; uint8_t encoded_seq_num[TEST_PACKET_NUM_LEN]; UNUSED_VARIABLE(uint32_encode(m_pkt_seq_num, &encoded_seq_num[0])); // The first 4 bytes of the payload is the packet sequence number. memcpy(&packet.packet_seq_num[0], &encoded_seq_num[0], TEST_PACKET_NUM_LEN); // The rest of the payload is random bytes. do { err_code = sd_rand_application_vector_get(&packet.packet_data[0], \ sizeof(packet.packet_data)); } while (err_code == NRF_ERROR_SOC_RAND_NOT_ENOUGH_VALUES); APP_ERROR_CHECK(err_code); iot_pbuffer_alloc_param_t pbuff_param; iot_pbuffer_t * p_buffer; pbuff_param.flags = PBUFFER_FLAG_DEFAULT; pbuff_param.type = UDP6_PACKET_TYPE; pbuff_param.length = TEST_PACKET_PAYLOAD_LEN; // Allocate packet buffer. err_code = iot_pbuffer_allocate(&pbuff_param, &p_buffer); APP_ERROR_CHECK(err_code); memcpy(p_buffer->p_payload, &packet.packet_seq_num[0], TEST_PACKET_NUM_LEN); memcpy(p_buffer->p_payload+TEST_PACKET_NUM_LEN, &packet.packet_data[0], TEST_PACKET_DATA_LEN); ipv6_addr_t dest_ipv6_addr; memset(&dest_ipv6_addr, 0x00, sizeof(ipv6_addr_t)); memcpy(&dest_ipv6_addr.u8[0], (uint8_t[]){SERVER_IPV6_ADDRESS}, IPV6_ADDR_SIZE); // Transmit UDP6 packet. err_code = udp6_socket_sendto(&m_udp_socket, &dest_ipv6_addr, HTONS(UDP_PORT), p_buffer); APP_ERROR_CHECK(err_code); APPL_LOG("[APPL]: Transmitted UDP packet sequence number: %ld\r\n", m_pkt_seq_num); // Store sent packet amongst expected packets. memcpy(&m_packet_buffer[ind_buff][0], &packet.packet_seq_num[0], TEST_PACKET_NUM_LEN); memcpy(&m_packet_buffer[ind_buff][TEST_PACKET_NUM_LEN], &packet.packet_data[0], TEST_PACKET_DATA_LEN); if (m_pkt_seq_num == 1) { err_code = app_timer_start(m_tx_node_timer, (TX_INTERVAL*5), NULL); // Slow start. APP_ERROR_CHECK(err_code); } else { err_code = app_timer_start(m_tx_node_timer, TX_INTERVAL, NULL); APP_ERROR_CHECK(err_code); } break; } default: { break; } } }