summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuxin Zhou <[email protected]>2021-07-28 07:24:24 +0000
committerYuxin Zhou <[email protected]>2021-07-28 07:24:24 +0000
commitcb2245c8d1041d8250df797dd145091d08cd194c (patch)
tree939ad587587d3169c5b3360610a95798e979fbf8
parentc187d60014b149ee7c5e79b4d84c416caddbdef7 (diff)
Release 6.1.8v6.1.8_rel
-rwxr-xr-xCMakeLists.txt10
m---------addons/azure_iot/azure-sdk-for-c0
-rw-r--r--addons/azure_iot/azure_iot_security_module/src/collectors/collector_network_activity.c36
-rw-r--r--addons/azure_iot/docs/azure_rtos_iot_hub_client.md1
-rw-r--r--addons/azure_iot/nx_azure_iot.c8
-rw-r--r--addons/azure_iot/nx_azure_iot.h12
-rw-r--r--addons/azure_iot/nx_azure_iot_hub_client.c43
-rw-r--r--addons/azure_iot/nx_azure_iot_hub_client.h20
-rw-r--r--addons/azure_iot/nx_azure_iot_json_reader.c66
-rw-r--r--addons/azure_iot/nx_azure_iot_json_reader.h4
-rw-r--r--addons/azure_iot/nx_azure_iot_json_writer.c4
-rw-r--r--addons/azure_iot/nx_azure_iot_json_writer.h1
-rw-r--r--addons/azure_iot/nx_azure_iot_provisioning_client.c9
-rw-r--r--addons/azure_iot/samples/main.c267
-rw-r--r--addons/azure_iot/samples/sample_azure_iot_embedded_sdk_pnp.c17
-rw-r--r--addons/azure_iot/samples/sample_azure_iot_embedded_sdk_with_retry.c6
-rw-r--r--addons/dhcp/nxd_dhcp_client.c273
-rw-r--r--addons/dhcp/nxd_dhcp_client.h22
-rw-r--r--addons/ftp/nxd_ftp_server.c26
-rw-r--r--addons/http/nxd_http_server.c111
-rw-r--r--addons/http/nxd_http_server.h7
-rw-r--r--addons/mqtt/nxd_mqtt_client.c49
-rw-r--r--addons/mqtt/nxd_mqtt_client.h14
-rw-r--r--addons/ppp/nx_ppp.c8
-rw-r--r--addons/snmp/nxd_snmp.c59
-rw-r--r--addons/sntp/nxd_sntp_client.c155
-rw-r--r--addons/web/nx_web_http_server.c111
-rw-r--r--addons/web/nx_web_http_server.h7
-rw-r--r--common/CMakeLists.txt4
-rw-r--r--common/inc/nx_api.h81
-rw-r--r--common/inc/nx_ipv4.h8
-rw-r--r--common/inc/nx_tcp.h13
-rw-r--r--common/inc/nx_udp.h10
-rw-r--r--common/inc/nx_user_sample.h11
-rw-r--r--common/src/nx_ip_address_set.c72
-rw-r--r--common/src/nx_ip_header_add.c10
-rw-r--r--common/src/nx_ip_interface_attach.c18
-rw-r--r--common/src/nx_ip_packet_receive.c19
-rw-r--r--common/src/nx_ip_packet_send.c41
-rw-r--r--common/src/nx_ip_thread_entry.c14
-rw-r--r--common/src/nx_ipv6_header_add.c21
-rw-r--r--common/src/nx_ipv6_packet_send.c53
-rw-r--r--common/src/nx_tcp_server_socket_driver_listen.c119
-rw-r--r--common/src/nx_tcp_server_socket_listen.c21
-rw-r--r--common/src/nx_tcp_server_socket_relisten.c18
-rw-r--r--common/src/nx_tcp_server_socket_unlisten.c93
-rw-r--r--common/src/nx_tcp_socket_disconnect.c27
-rw-r--r--common/src/nx_tcp_socket_driver_establish.c243
-rw-r--r--common/src/nx_tcp_socket_driver_packet_receive.c181
-rw-r--r--common/src/nx_tcp_socket_packet_process.c33
-rw-r--r--common/src/nx_tcp_socket_send_internal.c199
-rw-r--r--common/src/nx_tcp_socket_state_data_check.c55
-rw-r--r--common/src/nx_udp_socket_bind.c130
-rw-r--r--common/src/nx_udp_socket_driver_packet_receive.c158
-rw-r--r--common/src/nx_udp_socket_unbind.c95
-rw-r--r--common/src/nx_utility.c112
-rw-r--r--common/src/nxd_tcp_client_socket_connect.c173
-rw-r--r--common/src/nxd_udp_socket_send.c209
-rw-r--r--crypto_libraries/inc/nx_crypto_huge_number.h10
-rw-r--r--crypto_libraries/inc/nx_crypto_sha5.h11
-rw-r--r--crypto_libraries/ports/cortex_m3/ac5/inc/nx_crypto_port.h5
-rw-r--r--crypto_libraries/ports/cortex_m3/ac6/inc/nx_crypto_port.h81
-rw-r--r--crypto_libraries/ports/cortex_m3/keil/inc/nx_crypto_port.h5
-rw-r--r--crypto_libraries/ports/cortex_m4/ac5/inc/nx_crypto_port.h5
-rw-r--r--crypto_libraries/ports/cortex_m4/ac6/inc/nx_crypto_port.h81
-rw-r--r--crypto_libraries/ports/cortex_m4/keil/inc/nx_crypto_port.h5
-rw-r--r--crypto_libraries/ports/cortex_m7/ac5/inc/nx_crypto_port.h5
-rw-r--r--crypto_libraries/ports/cortex_m7/ac6/inc/nx_crypto_port.h81
-rw-r--r--nx_secure/inc/nx_secure_tls.h23
-rw-r--r--nx_secure/inc/nx_secure_user_sample.h21
-rw-r--r--nx_secure/src/nx_secure_tls_1_3_generate_keys.c31
-rw-r--r--nx_secure/src/nx_secure_tls_1_3_session_keys_set.c31
-rw-r--r--nx_secure/src/nx_secure_tls_1_3_transcript_hash_save.c16
-rw-r--r--nx_secure/src/nx_secure_tls_finished_hash_generate.c71
-rw-r--r--nx_secure/src/nx_secure_tls_process_certificate_verify.c40
-rw-r--r--nx_secure/src/nx_secure_tls_process_clienthello_extensions.c33
-rw-r--r--nx_secure/src/nx_secure_tls_process_record.c17
-rw-r--r--nx_secure/src/nx_secure_tls_record_payload_encrypt.c44
-rw-r--r--nx_secure/src/nx_secure_tls_send_certificate_verify.c41
-rw-r--r--nx_secure/src/nx_secure_tls_send_clienthello_extensions.c32
-rw-r--r--nx_secure/src/nx_secure_tls_send_record.c8
-rw-r--r--nx_secure/src/nx_secure_tls_session_keys_set.c31
-rw-r--r--nx_secure/src/nx_secure_tls_session_renegotiate.c17
-rw-r--r--nx_secure/src/nx_secure_tls_session_reset.c7
-rw-r--r--nx_secure/src/nx_secure_x509_crl_revocation_check.c7
-rw-r--r--utility/CMakeLists.txt16
-rw-r--r--utility/iperf/demo_iperf.c167
-rw-r--r--utility/iperf/nx_iperf.c2446
-rw-r--r--utility/iperf/nx_iperf.h2218
89 files changed, 8408 insertions, 785 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 68d3c8be..df3537ca 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,7 +2,6 @@ cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
# Set up the project
project(netxduo
- VERSION 6.0.0
LANGUAGES C ASM
)
@@ -39,7 +38,11 @@ endif()
set(CUSTOM_INC_DIR ${CMAKE_CURRENT_BINARY_DIR}/custom_inc)
# Pick up the port specific stuff first
-add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN})
+if(DEFINED NETXDUO_CUSTOM_PORT)
+ add_subdirectory(${NETXDUO_CUSTOM_PORT} netxduo_port)
+else()
+ add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN})
+endif()
# Then the common files
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/common)
@@ -51,6 +54,9 @@ add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/addons)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/crypto_libraries)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/nx_secure)
+# Utility components
+add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/utility)
+
# If the user provided an override, copy it to the custom directory
if (NOT NX_USER_FILE)
message(STATUS "Using default nx_user.h file")
diff --git a/addons/azure_iot/azure-sdk-for-c b/addons/azure_iot/azure-sdk-for-c
-Subproject 5e9d7b96dbd98ce7125e4beed385959a32b4c6c
+Subproject 079813f2dcd187da95b173bedef21b3c38974bc
diff --git a/addons/azure_iot/azure_iot_security_module/src/collectors/collector_network_activity.c b/addons/azure_iot/azure_iot_security_module/src/collectors/collector_network_activity.c
index bfd602f2..62d4b62d 100644
--- a/addons/azure_iot/azure_iot_security_module/src/collectors/collector_network_activity.c
+++ b/addons/azure_iot/azure_iot_security_module/src/collectors/collector_network_activity.c
@@ -89,7 +89,7 @@ static void _append_ipv6_payload_to_list(network_activity_ipv6_t *data_ptr, void
*
* @return network_activity_t*
*/
-static network_activity_ipv6_t *_ipv6_callback(VOID *ip_packet, UINT direction, byte_order_t ip_header_byte_order);
+static network_activity_ipv6_t *_ipv6_callback(struct NX_IP_STRUCT *ip_ptr, NX_PACKET *packet_ptr_st, UINT direction, byte_order_t ip_header_byte_order);
#endif /* NX_DISABLE_IPV6 */
/**
@@ -99,7 +99,7 @@ static network_activity_ipv6_t *_ipv6_callback(VOID *ip_packet, UINT direction,
* @param direction The direction of the packet (NX_IP_PACKET_IN / NX_IP_PACKET_OUT)
* @param ip_header_byte_order The byte order of the IP header
*/
-static void _collector_network_activity_ip_callback(VOID* ip_packet, UINT direction, byte_order_t ip_header_byte_order);
+static VOID _collector_network_activity_ip_callback(struct NX_IP_STRUCT *ip_ptr, NX_PACKET *packet_ptr, UINT direction, byte_order_t ip_header_byte_order);
/**
* @brief Initialize the port layer of the network activity collector.
@@ -116,7 +116,7 @@ static asc_result_t _collector_network_activity_port_init();
*
* @return NX_SUCCESS
**/
-static UINT _collector_network_activity_port_ip_callback(VOID* ip_packet, UINT direction);
+static UINT _collector_network_activity_port_ip_callback(struct NX_IP_STRUCT *ip_ptr, NX_PACKET *packet_ptr, UINT direction);
#ifdef ASC_COLLECTOR_NETWORK_ACTIVITY_CAPTURE_UNICAST_ONLY
/**
@@ -304,7 +304,7 @@ static asc_result_t _collector_network_activity_port_init()
while (created_count--)
{
- nx_ip_ptr->nx_ip_packet_filter = _collector_network_activity_port_ip_callback;
+ nx_ip_ptr->nx_ip_packet_filter_extended = _collector_network_activity_port_ip_callback;
#ifdef ASC_COLLECTOR_NETWORK_ACTIVITY_CAPTURE_UNICAST_ONLY
if (nx_ip_ptr->nx_ip_tcp_packet_receive)
@@ -334,7 +334,7 @@ cleanup:
}
-static UINT _collector_network_activity_port_ip_callback(VOID *ip_packet, UINT direction)
+static UINT _collector_network_activity_port_ip_callback(struct NX_IP_STRUCT *ip_ptr, NX_PACKET *packet_ptr, UINT direction)
{
#ifdef ASC_COLLECTOR_NETWORK_ACTIVITY_CAPTURE_UNICAST_ONLY
/* Incoming packets are captured on the transport layer */
@@ -343,8 +343,7 @@ static UINT _collector_network_activity_port_ip_callback(VOID *ip_packet, UINT d
return NX_SUCCESS;
}
#endif
-
- _collector_network_activity_ip_callback(ip_packet, direction, BYTE_ORDER_NETWORK);
+ _collector_network_activity_ip_callback(ip_ptr, packet_ptr, direction, BYTE_ORDER_NETWORK);
/* return NX_SUCCESS, otherwise NetX will drop the packet */
return NX_SUCCESS;
@@ -354,7 +353,7 @@ static UINT _collector_network_activity_port_ip_callback(VOID *ip_packet, UINT d
#ifdef ASC_COLLECTOR_NETWORK_ACTIVITY_CAPTURE_UNICAST_ONLY
static VOID _collector_network_activity_port_tcp_callback(struct NX_IP_STRUCT *ip_ptr, struct NX_PACKET_STRUCT *packet_ptr)
{
- _collector_network_activity_ip_callback(packet_ptr->nx_packet_ip_header, NX_IP_PACKET_IN, BYTE_ORDER_HOST);
+ _collector_network_activity_ip_callback(ip_ptr, packet_ptr, NX_IP_PACKET_IN, BYTE_ORDER_HOST);
if (_tcp_packet_receive_original)
{
@@ -365,7 +364,7 @@ static VOID _collector_network_activity_port_tcp_callback(struct NX_IP_STRUCT *i
static VOID _collector_network_activity_port_udp_callback(struct NX_IP_STRUCT *ip_ptr, struct NX_PACKET_STRUCT *packet_ptr)
{
- _collector_network_activity_ip_callback(packet_ptr->nx_packet_ip_header, NX_IP_PACKET_IN, BYTE_ORDER_HOST);
+ _collector_network_activity_ip_callback(ip_ptr, packet_ptr, NX_IP_PACKET_IN, BYTE_ORDER_HOST);
if (_udp_packet_receive_original)
{
@@ -376,7 +375,7 @@ static VOID _collector_network_activity_port_udp_callback(struct NX_IP_STRUCT *i
static VOID _collector_network_activity_port_icmp_callback(struct NX_IP_STRUCT *ip_ptr, struct NX_PACKET_STRUCT *packet_ptr)
{
- _collector_network_activity_ip_callback(packet_ptr->nx_packet_ip_header, NX_IP_PACKET_IN, BYTE_ORDER_HOST);
+ _collector_network_activity_ip_callback(ip_ptr, packet_ptr, NX_IP_PACKET_IN, BYTE_ORDER_HOST);
if (_icmp_packet_receive_original)
{
@@ -534,8 +533,9 @@ static void _append_ipv6_payload_to_list(network_activity_ipv6_t *data_ptr, void
}
-static network_activity_ipv6_t *_ipv6_callback(VOID *ip_packet, UINT direction, byte_order_t ip_header_byte_order)
+static network_activity_ipv6_t *_ipv6_callback(struct NX_IP_STRUCT *ip_ptr, NX_PACKET *packet_ptr_st, UINT direction, byte_order_t ip_header_byte_order)
{
+ VOID * ip_packet = packet_ptr_st->nx_packet_ip_header;
network_activity_ipv6_t *result = network_activity_ipv6_init();
if (result == NULL)
{
@@ -552,7 +552,6 @@ static network_activity_ipv6_t *_ipv6_callback(VOID *ip_packet, UINT direction,
uint16_t payload_length = (uint16_t)(ip_header_word_1 >> 16);
uint16_t header_length = 40;
packet_ptr += header_length;
-
bool found_transport_header = false;
/*
@@ -596,11 +595,17 @@ static network_activity_ipv6_t *_ipv6_callback(VOID *ip_packet, UINT direction,
}
payload_length = (uint16_t)(payload_length - header_length);
- packet_ptr += header_length;
if (!found_transport_header)
{
next_header_type = (uint8_t)(ip_header_word_0 >> 24);
}
+
+ if ((ALIGN_TYPE)(packet_ptr + header_length) >= (ALIGN_TYPE)(packet_ptr_st ->nx_packet_append_ptr))
+ {
+ network_activity_ipv6_deinit(result, NULL);
+ return NULL;
+ }
+ packet_ptr += header_length;
} while (!found_transport_header);
@@ -669,8 +674,9 @@ static network_activity_ipv6_t *_ipv6_callback(VOID *ip_packet, UINT direction,
#endif
-static void _collector_network_activity_ip_callback(VOID* ip_packet, UINT direction, byte_order_t ip_header_byte_order)
+static VOID _collector_network_activity_ip_callback(struct NX_IP_STRUCT *ip_ptr, NX_PACKET *packet_ptr, UINT direction, byte_order_t ip_header_byte_order)
{
+ VOID * ip_packet = packet_ptr->nx_packet_ip_header;
uint32_t ip_header_word_0 = (ip_header_byte_order == BYTE_ORDER_NETWORK) ? ntohl(*(uint32_t *)ip_packet) : *(uint32_t *)ip_packet;
uint8_t version = (uint8_t)(ip_header_word_0 >> 28);
@@ -685,7 +691,7 @@ static void _collector_network_activity_ip_callback(VOID* ip_packet, UINT direct
else if (version == NX_IP_VERSION_V6)
{
#ifndef NX_DISABLE_IPV6
- network_activity_ipv6_t *ipv6_object = _ipv6_callback(ip_packet, direction, ip_header_byte_order);
+ network_activity_ipv6_t *ipv6_object = _ipv6_callback(ip_ptr, packet_ptr, direction, ip_header_byte_order);
if (ipv6_object != NULL)
{
hashset_network_activity_ipv6_t_add_or_update(_current_ipv6_hashtable, ipv6_object);
diff --git a/addons/azure_iot/docs/azure_rtos_iot_hub_client.md b/addons/azure_iot/docs/azure_rtos_iot_hub_client.md
index dd12ab9e..731c23cc 100644
--- a/addons/azure_iot/docs/azure_rtos_iot_hub_client.md
+++ b/addons/azure_iot/docs/azure_rtos_iot_hub_client.md
@@ -332,6 +332,7 @@ UINT nx_azure_iot_hub_client_connection_status_callback_set(NX_AZURE_IOT_HUB_CLI
* NXD_MQTT_ERROR_SERVER_UNAVAILABLE
* NXD_MQTT_ERROR_NOT_AUTHORIZED
* NX_AZURE_IOT_DISCONNECTED
+* NX_AZURE_IOT_SAS_TOKEN_EXPIRED
**Parameters**
diff --git a/addons/azure_iot/nx_azure_iot.c b/addons/azure_iot/nx_azure_iot.c
index 632c7e71..b6936bb6 100644
--- a/addons/azure_iot/nx_azure_iot.c
+++ b/addons/azure_iot/nx_azure_iot.c
@@ -167,14 +167,6 @@ static VOID nx_azure_iot_log_listener(az_log_classification classification, az_s
VOID nx_azure_iot_log_init(VOID(*log_callback)(az_log_classification classification, UCHAR *msg, UINT msg_len))
{
-static az_log_classification const classifications[] = {AZ_LOG_IOT_AZURERTOS,
- AZ_LOG_MQTT_RECEIVED_TOPIC,
- AZ_LOG_MQTT_RECEIVED_PAYLOAD,
- AZ_LOG_IOT_RETRY,
- AZ_LOG_IOT_SAS_TOKEN,
- _az_LOG_END_OF_LIST};
-
- _az_log_set_classifications(classifications);
_nx_azure_iot_log_callback = log_callback;
az_log_set_message_callback(nx_azure_iot_log_listener);
}
diff --git a/addons/azure_iot/nx_azure_iot.h b/addons/azure_iot/nx_azure_iot.h
index 2d07aac4..1694ba4a 100644
--- a/addons/azure_iot/nx_azure_iot.h
+++ b/addons/azure_iot/nx_azure_iot.h
@@ -140,6 +140,9 @@ UINT nx_azure_iot_log(UCHAR *type_ptr, UINT type_len, UCHAR *msg_ptr, UINT msg_l
#define NX_AZURE_IOT_NO_SUBSCRIBE_ACK 0x20014
#define NX_AZURE_IOT_THROTTLED 0x20015
+#define NX_AZURE_IOT_EMPTY_JSON 0x20016
+#define NX_AZURE_IOT_SAS_TOKEN_EXPIRED 0x20017
+
/* Resource type managed by AZ_IOT. */
#define NX_AZURE_IOT_RESOURCE_IOT_HUB 0x1
#define NX_AZURE_IOT_RESOURCE_IOT_PROVISIONING 0x2
@@ -210,6 +213,15 @@ typedef struct NX_AZURE_IOT_STRUCT
UINT (*nx_azure_iot_unix_time_get)(ULONG *unix_time);
} NX_AZURE_IOT;
+typedef struct NX_AZURE_IOT_THREAD_STRUCT
+{
+ TX_THREAD *thread_ptr;
+ struct NX_AZURE_IOT_THREAD_STRUCT *thread_next;
+ UINT thread_message_type;
+ UINT thread_expected_id; /* Used by device twin. */
+ NX_PACKET *thread_received_message;
+} NX_AZURE_IOT_THREAD;
+
/**
* @brief Create the Azure IoT subsystem
*
diff --git a/addons/azure_iot/nx_azure_iot_hub_client.c b/addons/azure_iot/nx_azure_iot_hub_client.c
index 13842882..a38e2a6b 100644
--- a/addons/azure_iot/nx_azure_iot_hub_client.c
+++ b/addons/azure_iot/nx_azure_iot_hub_client.c
@@ -355,7 +355,7 @@ az_result core_result;
return(status);
}
- expiry_time_secs += NX_AZURE_IOT_HUB_CLIENT_TOKEN_EXPIRY;
+ expiry_time_secs += NX_AZURE_IOT_HUB_CLIENT_TOKEN_CONNECTION_TIMEOUT;
status = hub_client_ptr -> nx_azure_iot_hub_client_token_refresh(hub_client_ptr,
expiry_time_secs,
hub_client_ptr -> nx_azure_iot_hub_client_symmetric_key,
@@ -372,6 +372,7 @@ az_result core_result;
LogError(LogLiteralArgs("IoTHub client connect fail: Token generation failed status: %d"), status);
return(status);
}
+ hub_client_ptr -> nx_azure_iot_hub_client_sas_token_expiry_time = expiry_time_secs;
}
else
{
@@ -541,6 +542,7 @@ static VOID nx_azure_iot_hub_client_mqtt_disconnect_notify(NXD_MQTT_CLIENT *clie
NX_AZURE_IOT_RESOURCE *resource = nx_azure_iot_resource_search(client_ptr);
NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = NX_NULL;
NX_AZURE_IOT_THREAD *thread_list_ptr;
+ULONG current_time = 0;
/* This function is protected by MQTT mutex. */
@@ -548,13 +550,12 @@ NX_AZURE_IOT_THREAD *thread_list_ptr;
{
hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)resource -> resource_data_ptr;
}
- else
+
+ if (hub_client_ptr == NX_NULL)
{
return;
}
- NX_ASSERT(hub_client_ptr != NX_NULL);
-
/* Wake up all threads. */
for (thread_list_ptr = hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended;
thread_list_ptr;
@@ -571,8 +572,20 @@ NX_AZURE_IOT_THREAD *thread_list_ptr;
/* Call connection notify if it is set. */
if (hub_client_ptr && hub_client_ptr -> nx_azure_iot_hub_client_connection_status_callback)
{
- hub_client_ptr -> nx_azure_iot_hub_client_connection_status_callback(hub_client_ptr,
- NX_AZURE_IOT_DISCONNECTED);
+ if (hub_client_ptr -> nx_azure_iot_hub_client_token_refresh &&
+ (nx_azure_iot_unix_time_get(hub_client_ptr -> nx_azure_iot_ptr,
+ &current_time) == NX_AZURE_IOT_SUCCESS) &&
+ (current_time > hub_client_ptr -> nx_azure_iot_hub_client_sas_token_expiry_time))
+ {
+ hub_client_ptr -> nx_azure_iot_hub_client_connection_status_callback(hub_client_ptr,
+ NX_AZURE_IOT_SAS_TOKEN_EXPIRED);
+ }
+ else
+ {
+ hub_client_ptr -> nx_azure_iot_hub_client_connection_status_callback(hub_client_ptr,
+ NX_AZURE_IOT_DISCONNECTED);
+ }
+
}
}
}
@@ -622,6 +635,8 @@ NX_AZURE_IOT_THREAD *thread_list_ptr;
nx_azure_iot_hub_client_received_message_cleanup(&(hub_client_ptr -> nx_azure_iot_hub_client_device_twin_desired_properties_message));
nx_azure_iot_hub_client_received_message_cleanup(&(hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message));
+ hub_client_ptr -> nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_NOT_CONNECTED;
+
/* Release the mutex. */
tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
@@ -1451,9 +1466,13 @@ UINT nx_azure_iot_hub_client_report_properties_response_callback_set(NX_AZURE_IO
return(NX_AZURE_IOT_INVALID_PARAMETER);
}
+ tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
+
hub_client_ptr -> nx_azure_iot_hub_client_report_properties_response_callback = callback_ptr;
hub_client_ptr -> nx_azure_iot_hub_client_report_properties_response_callback_args = callback_args;
+ tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
+
return(NX_AZURE_IOT_SUCCESS);
}
@@ -2222,7 +2241,7 @@ NX_AZURE_IOT_THREAD *thread_list_ptr;
static UINT nx_azure_iot_hub_client_device_twin_message_type_get(az_iot_hub_client_twin_response *out_twin_response_ptr,
UINT request_id)
{
-UINT mesg_type;
+UINT message_type;
switch (out_twin_response_ptr -> response_type)
{
@@ -2234,24 +2253,24 @@ UINT mesg_type;
{
/* Odd requests are of reported properties and even of twin properties. */
- mesg_type = request_id % 2 == 0 ? NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES :
- NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE;
+ message_type = request_id % 2 == 0 ? NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES :
+ NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE;
}
break;
case AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_TYPE_DESIRED_PROPERTIES :
{
- mesg_type = NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES;
+ message_type = NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES;
}
break;
default :
{
- mesg_type = NX_AZURE_IOT_HUB_NONE;
+ message_type = NX_AZURE_IOT_HUB_NONE;
}
}
- return mesg_type;
+ return message_type;
}
static UINT nx_azure_iot_hub_client_device_twin_parse(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
diff --git a/addons/azure_iot/nx_azure_iot_hub_client.h b/addons/azure_iot/nx_azure_iot_hub_client.h
index 273d2d6f..97ceba5b 100644
--- a/addons/azure_iot/nx_azure_iot_hub_client.h
+++ b/addons/azure_iot/nx_azure_iot_hub_client.h
@@ -60,10 +60,14 @@ extern "C" {
#define NX_AZURE_IOT_HUB_CLIENT_DNS_TIMEOUT (5 * NX_IP_PERIODIC_RATE)
#endif /* NX_AZURE_IOT_HUB_CLIENT_DNS_TIMEOUT */
-/* Set the default token expiry in secs. */
-#ifndef NX_AZURE_IOT_HUB_CLIENT_TOKEN_EXPIRY
-#define NX_AZURE_IOT_HUB_CLIENT_TOKEN_EXPIRY (3600)
+/* Set the default timeout for connection with SAS token authentication in secs. */
+#ifndef NX_AZURE_IOT_HUB_CLIENT_TOKEN_CONNECTION_TIMEOUT
+#ifdef NX_AZURE_IOT_HUB_CLIENT_TOKEN_EXPIRY
+#define NX_AZURE_IOT_HUB_CLIENT_TOKEN_CONNECTION_TIMEOUT NX_AZURE_IOT_HUB_CLIENT_TOKEN_EXPIRY
+#else
+#define NX_AZURE_IOT_HUB_CLIENT_TOKEN_CONNECTION_TIMEOUT (3600)
#endif /* NX_AZURE_IOT_HUB_CLIENT_TOKEN_EXPIRY */
+#endif /* NX_AZURE_IOT_HUB_CLIENT_SAS_CONNECTION_TIMEOUT */
#ifndef NX_AZURE_IOT_HUB_CLIENT_MAX_BACKOFF_IN_SEC
#define NX_AZURE_IOT_HUB_CLIENT_MAX_BACKOFF_IN_SEC (10 * 60)
@@ -92,15 +96,6 @@ extern "C" {
#define NX_AZURE_IOT_HUB_CLIENT_TELEMETRY_QOS NX_AZURE_IOT_MQTT_QOS_1
#endif /* NX_AZURE_IOT_HUB_CLIENT_TELEMETRY_QOS */
-typedef struct NX_AZURE_IOT_THREAD_STRUCT
-{
- TX_THREAD *thread_ptr;
- struct NX_AZURE_IOT_THREAD_STRUCT *thread_next;
- UINT thread_message_type;
- UINT thread_expected_id; /* Used by device twin. */
- NX_PACKET *thread_received_message;
-} NX_AZURE_IOT_THREAD;
-
/* Forward declration*/
struct NX_AZURE_IOT_HUB_CLIENT_STRUCT;
@@ -153,6 +148,7 @@ typedef struct NX_AZURE_IOT_HUB_CLIENT_STRUCT
az_iot_hub_client iot_hub_client_core;
UINT nx_azure_iot_hub_client_throttle_count;
ULONG nx_azure_iot_hub_client_throttle_end_time;
+ ULONG nx_azure_iot_hub_client_sas_token_expiry_time;
} NX_AZURE_IOT_HUB_CLIENT;
diff --git a/addons/azure_iot/nx_azure_iot_json_reader.c b/addons/azure_iot/nx_azure_iot_json_reader.c
index cd480db3..ee7dc339 100644
--- a/addons/azure_iot/nx_azure_iot_json_reader.c
+++ b/addons/azure_iot/nx_azure_iot_json_reader.c
@@ -15,19 +15,50 @@
#include "nx_azure_iot.h"
+static UINT nx_azure_iot_json_reader_translate_error_code(NX_AZURE_IOT_JSON_READER *reader_ptr,
+ az_result core_result)
+{
+ if (az_result_failed(core_result))
+ {
+ if (core_result == AZ_ERROR_JSON_READER_DONE)
+ {
+ return(NX_AZURE_IOT_NOT_FOUND);
+ }
+
+ if (reader_ptr -> json_length == 0)
+ {
+ return(NX_AZURE_IOT_EMPTY_JSON);
+ }
+
+ return(NX_AZURE_IOT_SDK_CORE_ERROR);
+ }
+
+ return(NX_AZURE_IOT_SUCCESS);
+}
+
UINT nx_azure_iot_json_reader_with_buffer_init(NX_AZURE_IOT_JSON_READER *reader_ptr,
const UCHAR *buffer_ptr, UINT buffer_len)
{
az_span span = az_span_create((UCHAR *)buffer_ptr, (INT)buffer_len);
if ((reader_ptr == NX_NULL) ||
- (buffer_ptr == NX_NULL) || (buffer_len == 0))
+ (buffer_ptr == NX_NULL))
{
return(NX_AZURE_IOT_INVALID_PARAMETER);
}
memset(reader_ptr, 0, sizeof(NX_AZURE_IOT_JSON_READER));
+ /* Allow initializing with zero size buffer, as any futher call will fail for empty JSON */
+ if (buffer_len == 0)
+ {
+ reader_ptr -> json_reader.token.kind = AZ_JSON_TOKEN_NONE;
+
+ return(NX_AZURE_IOT_SUCCESS);
+ }
+
+ reader_ptr -> json_length = (ULONG)buffer_len;
+
if (az_result_failed(az_json_reader_init(&(reader_ptr -> json_reader),
span, NX_NULL)))
{
@@ -43,8 +74,7 @@ UINT nx_azure_iot_json_reader_init(NX_AZURE_IOT_JSON_READER *reader_ptr,
UINT count = 0;
if ((reader_ptr == NX_NULL) ||
- (packet_ptr == NX_NULL) ||
- (packet_ptr -> nx_packet_length == 0))
+ (packet_ptr == NX_NULL))
{
return(NX_AZURE_IOT_INVALID_PARAMETER);
}
@@ -53,6 +83,16 @@ UINT count = 0;
reader_ptr -> packet_ptr = packet_ptr;
+ /* Allow initializing with zero size packet, as any futher call will fail for empty JSON */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
+ reader_ptr -> json_reader.token.kind = AZ_JSON_TOKEN_NONE;
+
+ return(NX_AZURE_IOT_SUCCESS);
+ }
+
+ reader_ptr -> json_length = packet_ptr -> nx_packet_length;
+
while (packet_ptr != NX_NULL)
{
if (count >= NX_AZURE_IOT_READER_MAX_LIST)
@@ -110,32 +150,30 @@ az_span span = az_span_create(value_ptr, (INT)value_len);
UINT nx_azure_iot_json_reader_next_token(NX_AZURE_IOT_JSON_READER *reader_ptr)
{
+az_result core_result;
+
if ((reader_ptr == NX_NULL))
{
return(NX_AZURE_IOT_INVALID_PARAMETER);
}
- if (az_result_failed(az_json_reader_next_token(&(reader_ptr -> json_reader))))
- {
- return(NX_AZURE_IOT_SDK_CORE_ERROR);
- }
-
- return(NX_AZURE_IOT_SUCCESS);
+ core_result = az_json_reader_next_token(&(reader_ptr -> json_reader));
+
+ return(nx_azure_iot_json_reader_translate_error_code(reader_ptr, core_result));
}
UINT nx_azure_iot_json_reader_skip_children(NX_AZURE_IOT_JSON_READER *reader_ptr)
{
+az_result core_result;
+
if ((reader_ptr == NX_NULL))
{
return(NX_AZURE_IOT_INVALID_PARAMETER);
}
- if (az_result_failed(az_json_reader_skip_children(&(reader_ptr -> json_reader))))
- {
- return(NX_AZURE_IOT_SDK_CORE_ERROR);
- }
+ core_result = az_json_reader_skip_children(&(reader_ptr -> json_reader));
- return(NX_AZURE_IOT_SUCCESS);
+ return(nx_azure_iot_json_reader_translate_error_code(reader_ptr, core_result));
}
UINT nx_azure_iot_json_reader_token_bool_get(NX_AZURE_IOT_JSON_READER *reader_ptr,
diff --git a/addons/azure_iot/nx_azure_iot_json_reader.h b/addons/azure_iot/nx_azure_iot_json_reader.h
index 7fefa51d..adfd93a8 100644
--- a/addons/azure_iot/nx_azure_iot_json_reader.h
+++ b/addons/azure_iot/nx_azure_iot_json_reader.h
@@ -54,6 +54,7 @@ typedef struct NX_AZURE_IOT_READER_STRUCT
NX_PACKET *packet_ptr;
az_json_reader json_reader;
az_span span_list[NX_AZURE_IOT_READER_MAX_LIST];
+ ULONG json_length;
} NX_AZURE_IOT_JSON_READER;
/**
@@ -68,7 +69,6 @@ typedef struct NX_AZURE_IOT_READER_STRUCT
* @retval #NX_AZURE_IOT_SUCCESS The #NX_AZURE_IOT_JSON_READER is initialized successfully.
* @retval other Initialization failed.
*
- * @remarks The provided json buffer must not be empty, as that is invalid JSON.
*/
UINT nx_azure_iot_json_reader_with_buffer_init(NX_AZURE_IOT_JSON_READER *reader_ptr,
const UCHAR *buffer_ptr, UINT buffer_len);
@@ -83,8 +83,6 @@ UINT nx_azure_iot_json_reader_with_buffer_init(NX_AZURE_IOT_JSON_READER *reader_
* @retval #NX_AZURE_IOT_SUCCESS The #NX_AZURE_IOT_JSON_READER is initialized successfully.
* @retval other Initialization failed.
*
- * @remarks The provided json buffer must not be empty, as that is invalid JSON.
- *
* @remarks Ownership of #NX_PACKET is taken by the reader.
*/
UINT nx_azure_iot_json_reader_init(NX_AZURE_IOT_JSON_READER *reader_ptr,
diff --git a/addons/azure_iot/nx_azure_iot_json_writer.c b/addons/azure_iot/nx_azure_iot_json_writer.c
index eb4e3c43..e3bffd72 100644
--- a/addons/azure_iot/nx_azure_iot_json_writer.c
+++ b/addons/azure_iot/nx_azure_iot_json_writer.c
@@ -344,8 +344,6 @@ UINT nx_azure_iot_json_writer_append_begin_object(NX_AZURE_IOT_JSON_WRITER *json
return(NX_AZURE_IOT_SDK_CORE_ERROR);
}
- json_writer_ptr -> object_depth++;
-
nx_azure_iot_json_writer_packet_update(json_writer_ptr);
return(NX_AZURE_IOT_SUCCESS);
@@ -382,8 +380,6 @@ UINT nx_azure_iot_json_writer_append_end_object(NX_AZURE_IOT_JSON_WRITER *json_w
return(NX_AZURE_IOT_SDK_CORE_ERROR);
}
- json_writer_ptr -> object_depth--;
-
nx_azure_iot_json_writer_packet_update(json_writer_ptr);
return(NX_AZURE_IOT_SUCCESS);
diff --git a/addons/azure_iot/nx_azure_iot_json_writer.h b/addons/azure_iot/nx_azure_iot_json_writer.h
index e40b999f..6a6a3622 100644
--- a/addons/azure_iot/nx_azure_iot_json_writer.h
+++ b/addons/azure_iot/nx_azure_iot_json_writer.h
@@ -38,7 +38,6 @@ typedef struct NX_AZURE_IOT_JSON_WRITER_STRUCT
{
NX_PACKET *packet_ptr;
az_json_writer json_writer;
- UINT object_depth;
UINT wait_option;
ULONG nx_tail_packet_offset;
ULONG nx_packet_init_length;
diff --git a/addons/azure_iot/nx_azure_iot_provisioning_client.c b/addons/azure_iot/nx_azure_iot_provisioning_client.c
index b3e87619..daffb350 100644
--- a/addons/azure_iot/nx_azure_iot_provisioning_client.c
+++ b/addons/azure_iot/nx_azure_iot_provisioning_client.c
@@ -33,11 +33,6 @@
#define NX_AZURE_IOT_PROVISIONING_CLIENT_PAYLOAD_END "}"
#define NX_AZURE_IOT_PROVISIONING_CLIENT_POLICY_NAME "registration"
-/* Set the default timeout for connecting on cloud thread. */
-#ifndef NX_AZURE_IOT_PROVISIONING_CLIENT_CONNECT_TIMEOUT
-#define NX_AZURE_IOT_PROVISIONING_CLIENT_CONNECT_TIMEOUT (20 * NX_IP_PERIODIC_RATE)
-#endif /* NX_AZURE_IOT_PROVISIONING_CLIENT_CONNECT_TIMEOUT */
-
/* Set the default retry to Provisioning service. */
#ifndef NX_AZURE_IOT_PROVISIONING_CLIENT_DEFAULT_RETRY
#define NX_AZURE_IOT_PROVISIONING_CLIENT_DEFAULT_RETRY (3)
@@ -97,7 +92,7 @@ UINT status;
&response -> register_response);
if (az_result_failed(core_result))
{
- LogError(LogLiteralArgs("IoTProvisioning client failed to parse packet, error status: "), core_result);
+ LogError(LogLiteralArgs("IoTProvisioning client failed to parse packet, error status: %d"), core_result);
return(NX_AZURE_IOT_SDK_CORE_ERROR);
}
@@ -465,7 +460,7 @@ UINT status;
{
/* Start new operation. */
- status = nx_azure_iot_provisioning_client_send_req(context, NULL, NX_AZURE_IOT_PROVISIONING_CLIENT_CONNECT_TIMEOUT);
+ status = nx_azure_iot_provisioning_client_send_req(context, NULL, NX_NO_WAIT);
}
if (status)
diff --git a/addons/azure_iot/samples/main.c b/addons/azure_iot/samples/main.c
index e0d417f8..a65884a0 100644
--- a/addons/azure_iot/samples/main.c
+++ b/addons/azure_iot/samples/main.c
@@ -9,13 +9,12 @@
/* */
/**************************************************************************/
-#include <time.h>
-
#include "nx_api.h"
#ifndef SAMPLE_DHCP_DISABLE
#include "nxd_dhcp_client.h"
#endif /* SAMPLE_DHCP_DISABLE */
#include "nxd_dns.h"
+#include "nxd_sntp_client.h"
#include "nx_secure_tls_api.h"
/* Include the sample. */
@@ -78,6 +77,25 @@ extern VOID sample_entry(NX_IP* ip_ptr, NX_PACKET_POOL* pool_ptr, NX_DNS* dns_pt
#define SAMPLE_IPV4_MASK IP_ADDRESS(0, 0, 0, 0)
#endif /* SAMPLE_DHCP_DISABLE */
+#ifndef SAMPLE_SNTP_SYNC_MAX
+#define SAMPLE_SNTP_SYNC_MAX 30
+#endif /* SAMPLE_SNTP_SYNC_MAX */
+
+#ifndef SAMPLE_SNTP_UPDATE_MAX
+#define SAMPLE_SNTP_UPDATE_MAX 10
+#endif /* SAMPLE_SNTP_UPDATE_MAX */
+
+#ifndef SAMPLE_SNTP_UPDATE_INTERVAL
+#define SAMPLE_SNTP_UPDATE_INTERVAL (NX_IP_PERIODIC_RATE / 2)
+#endif /* SAMPLE_SNTP_UPDATE_INTERVAL */
+
+/* Default time. GMT: Friday, Jan 1, 2022 12:00:00 AM. Epoch timestamp: 1640995200. */
+#ifndef SAMPLE_SYSTEM_TIME
+#define SAMPLE_SYSTEM_TIME 1640995200
+#endif /* SAMPLE_SYSTEM_TIME */
+
+/* Seconds between Unix Epoch (1/1/1970) and NTP Epoch (1/1/1999) */
+#define SAMPLE_UNIX_TO_NTP_EPOCH_SECOND 0x83AA7E80
static TX_THREAD sample_helper_thread;
static NX_PACKET_POOL pool_0;
@@ -86,7 +104,10 @@ static NX_DNS dns_0;
#ifndef SAMPLE_DHCP_DISABLE
static NX_DHCP dhcp_0;
#endif /* SAMPLE_DHCP_DISABLE */
+static NX_SNTP_CLIENT sntp_client;
+/* System clock time for UTC. */
+static ULONG unix_time_base;
/* Define the stack/cache for ThreadX. */
static ULONG sample_ip_stack[SAMPLE_IP_STACK_SIZE / sizeof(ULONG)];
@@ -100,6 +121,15 @@ extern ULONG sample_pool_stack_size;
static ULONG sample_arp_cache_area[SAMPLE_ARP_CACHE_SIZE / sizeof(ULONG)];
static ULONG sample_helper_thread_stack[SAMPLE_HELPER_STACK_SIZE / sizeof(ULONG)];
+static const CHAR *sntp_servers[] =
+{
+ "0.pool.ntp.org",
+ "1.pool.ntp.org",
+ "2.pool.ntp.org",
+ "3.pool.ntp.org",
+};
+static UINT sntp_server_index;
+
/* Define the prototypes for sample thread. */
static void sample_helper_thread_entry(ULONG parameter);
@@ -109,15 +139,28 @@ static void dhcp_wait();
static UINT dns_create();
+static UINT sntp_time_sync();
static UINT unix_time_get(ULONG *unix_time);
+#ifndef SAMPLE_NETWORK_DRIVER
+#define SAMPLE_NETWORK_DRIVER _nx_ram_network_driver
+#endif /* SAMPLE_NETWORK_DRIVER */
+
/* Include the platform IP driver. */
-void _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT *driver_req);
+void SAMPLE_NETWORK_DRIVER(struct NX_IP_DRIVER_STRUCT *driver_req);
+
+#ifdef SAMPLE_BOARD_SETUP
+void SAMPLE_BOARD_SETUP();
+#endif /* SAMPLE_BOARD_SETUP */
/* Define main entry point. */
int main(void)
{
+#ifdef SAMPLE_BOARD_SETUP
+ SAMPLE_BOARD_SETUP();
+#endif /* SAMPLE_BOARD_SETUP */
+
/* Enter the ThreadX kernel. */
tx_kernel_enter();
}
@@ -128,7 +171,6 @@ void tx_application_define(void *first_unused_memory)
UINT status;
-
NX_PARAMETER_NOT_USED(first_unused_memory);
/* Initialize the NetX system. */
@@ -148,7 +190,7 @@ UINT status;
/* Create an IP instance. */
status = nx_ip_create(&ip_0, "NetX IP Instance 0",
SAMPLE_IPV4_ADDRESS, SAMPLE_IPV4_MASK,
- &pool_0, _nx_ram_network_driver,
+ &pool_0, SAMPLE_NETWORK_DRIVER,
(UCHAR*)sample_ip_stack, sizeof(sample_ip_stack),
SAMPLE_IP_THREAD_PRIORITY);
@@ -202,7 +244,7 @@ UINT status;
/* Initialize TLS. */
nx_secure_tls_initialize();
- /* Create sample helper thread. */
+ /* Create sample helper thread. */
status = tx_thread_create(&sample_helper_thread, "Demo Thread",
sample_helper_thread_entry, 0,
sample_helper_thread_stack, SAMPLE_HELPER_STACK_SIZE,
@@ -220,11 +262,12 @@ UINT status;
/* Define sample helper thread entry. */
void sample_helper_thread_entry(ULONG parameter)
{
+
UINT status;
ULONG ip_address = 0;
ULONG network_mask = 0;
ULONG gateway_address = 0;
-
+UINT unix_time;
NX_PARAMETER_NOT_USED(parameter);
@@ -234,11 +277,11 @@ ULONG gateway_address = 0;
nx_ip_gateway_address_set(&ip_0, SAMPLE_GATEWAY_ADDRESS);
#endif /* SAMPLE_DHCP_DISABLE */
- /* Get IP address and gateway address. */
+ /* Get IP address and gateway address. */
nx_ip_address_get(&ip_0, &ip_address, &network_mask);
nx_ip_gateway_address_get(&ip_0, &gateway_address);
- /* Output IP address and gateway address. */
+ /* Output IP address and gateway address. */
printf("IP address: %lu.%lu.%lu.%lu\r\n",
(ip_address >> 24),
(ip_address >> 16 & 0xFF),
@@ -265,8 +308,23 @@ ULONG gateway_address = 0;
return;
}
- /* Use time to init the seed. FIXME: use real rand on device. */
- srand((unsigned int)time(NULL));
+ /* Sync up time by SNTP at start up. */
+ status = sntp_time_sync();
+
+ /* Check status. */
+ if (status)
+ {
+ printf("SNTP Time Sync failed.\r\n");
+ printf("Set Time to default value: SAMPLE_SYSTEM_TIME.");
+ unix_time_base = SAMPLE_SYSTEM_TIME;
+ }
+ else
+ {
+ printf("SNTP Time Sync successfully.\r\n");
+ }
+
+ unix_time_get((ULONG *)&unix_time);
+ srand(unix_time);
/* Start sample. */
sample_entry(&ip_0, &pool_0, &dns_0, unix_time_get);
@@ -282,35 +340,37 @@ ULONG actual_status;
/* Create the DHCP instance. */
nx_dhcp_create(&dhcp_0, &ip_0, "DHCP Client");
+ /* Request NTP server. */
+ nx_dhcp_user_option_request(&dhcp_0, NX_DHCP_OPTION_NTP_SVR);
+
/* Start the DHCP Client. */
nx_dhcp_start(&dhcp_0);
- /* Wait util address is solved. */
+ /* Wait util address is solved. */
nx_ip_status_check(&ip_0, NX_IP_ADDRESS_RESOLVED, &actual_status, NX_WAIT_FOREVER);
}
#endif /* SAMPLE_DHCP_DISABLE */
static UINT dns_create()
{
-
UINT status;
ULONG dns_server_address[3];
-UINT dns_server_address_size = 12;
+UINT dns_server_address_size = sizeof(dns_server_address);
/* Create a DNS instance for the Client. Note this function will create
the DNS Client packet pool for creating DNS message packets intended
- for querying its DNS server. */
+ for querying its DNS server. */
status = nx_dns_create(&dns_0, &ip_0, (UCHAR *)"DNS Client");
if (status)
{
return(status);
}
- /* Is the DNS client configured for the host application to create the packet pool? */
+ /* Is the DNS client configured for the host application to create the packet pool? */
#ifdef NX_DNS_CLIENT_USER_CREATE_PACKET_POOL
/* Yes, use the packet pool created above which has appropriate payload size
- for DNS messages. */
+ for DNS messages. */
status = nx_dns_packet_pool_set(&dns_0, ip_0.nx_ip_default_packet_pool);
if (status)
{
@@ -327,7 +387,7 @@ UINT dns_server_address_size = 12;
dns_server_address[0] = SAMPLE_DNS_SERVER_ADDRESS;
#endif /* SAMPLE_DHCP_DISABLE */
- /* Add an IPv4 server address to the Client list. */
+ /* Add an IPv4 server address to the Client list. */
status = nx_dns_server_add(&dns_0, dns_server_address[0]);
if (status)
{
@@ -345,12 +405,177 @@ UINT dns_server_address_size = 12;
return(NX_SUCCESS);
}
+/* Sync up the local time. */
+static UINT sntp_time_sync_internal(ULONG sntp_server_address)
+{
+UINT status;
+UINT server_status;
+UINT i;
+
+ /* Create the SNTP Client to run in broadcast mode.. */
+ status = nx_sntp_client_create(&sntp_client, &ip_0, 0, &pool_0,
+ NX_NULL,
+ NX_NULL,
+ NX_NULL /* no random_number_generator callback */);
+
+ /* Check status. */
+ if (status)
+ {
+ return(status);
+ }
+
+ /* Use the IPv4 service to initialize the Client and set the IPv4 SNTP server. */
+ status = nx_sntp_client_initialize_unicast(&sntp_client, sntp_server_address);
+
+ /* Check status. */
+ if (status)
+ {
+ nx_sntp_client_delete(&sntp_client);
+ return(status);
+ }
+
+ /* Set local time to 0 */
+ status = nx_sntp_client_set_local_time(&sntp_client, 0, 0);
+
+ /* Check status. */
+ if (status)
+ {
+ nx_sntp_client_delete(&sntp_client);
+ return(status);
+ }
+
+ /* Run Unicast client */
+ status = nx_sntp_client_run_unicast(&sntp_client);
+
+ /* Check status. */
+ if (status)
+ {
+ nx_sntp_client_stop(&sntp_client);
+ nx_sntp_client_delete(&sntp_client);
+ return(status);
+ }
+
+ /* Wait till updates are received */
+ for (i = 0; i < SAMPLE_SNTP_UPDATE_MAX; i++)
+ {
+
+ /* First verify we have a valid SNTP service running. */
+ status = nx_sntp_client_receiving_updates(&sntp_client, &server_status);
+
+ /* Check status. */
+ if ((status == NX_SUCCESS) && (server_status == NX_TRUE))
+ {
+
+ /* Server status is good. Now get the Client local time. */
+ ULONG sntp_seconds, sntp_fraction;
+ ULONG system_time_in_second;
+
+ /* Get the local time. */
+ status = nx_sntp_client_get_local_time(&sntp_client, &sntp_seconds, &sntp_fraction, NX_NULL);
+
+ /* Check status. */
+ if (status != NX_SUCCESS)
+ {
+ continue;
+ }
+
+ /* Get the system time in second. */
+ system_time_in_second = tx_time_get() / TX_TIMER_TICKS_PER_SECOND;
+
+ /* Convert to Unix epoch and minus the current system time. */
+ unix_time_base = (sntp_seconds - (system_time_in_second + SAMPLE_UNIX_TO_NTP_EPOCH_SECOND));
+
+ /* Time sync successfully. */
+
+ /* Stop and delete SNTP. */
+ nx_sntp_client_stop(&sntp_client);
+ nx_sntp_client_delete(&sntp_client);
+
+ return(NX_SUCCESS);
+ }
+
+ /* Sleep. */
+ tx_thread_sleep(SAMPLE_SNTP_UPDATE_INTERVAL);
+ }
+
+ /* Time sync failed. */
+
+ /* Stop and delete SNTP. */
+ nx_sntp_client_stop(&sntp_client);
+ nx_sntp_client_delete(&sntp_client);
+
+ /* Return success. */
+ return(NX_NOT_SUCCESSFUL);
+}
+
+static UINT sntp_time_sync()
+{
+UINT status;
+ULONG sntp_server_address[3];
+UINT sntp_server_address_size = sizeof(sntp_server_address);
+
+#ifndef SAMPLE_DHCP_DISABLE
+ /* Retrieve NTP server address. */
+ status = nx_dhcp_interface_user_option_retrieve(&dhcp_0, 0, NX_DHCP_OPTION_NTP_SVR, (UCHAR *)(sntp_server_address),
+ &sntp_server_address_size);
+
+ /* Check status. */
+ if (status == NX_SUCCESS)
+ {
+ for (UINT i = 0; (i * 4) < sntp_server_address_size; i++)
+ {
+ printf("SNTP Time Sync...%lu.%lu.%lu.%lu (DHCP)\r\n",
+ (sntp_server_address[i] >> 24),
+ (sntp_server_address[i] >> 16 & 0xFF),
+ (sntp_server_address[i] >> 8 & 0xFF),
+ (sntp_server_address[i] & 0xFF));
+
+ /* Start SNTP to sync the local time. */
+ status = sntp_time_sync_internal(sntp_server_address[i]);
+
+ /* Check status. */
+ if(status == NX_SUCCESS)
+ {
+ return(NX_SUCCESS);
+ }
+ }
+ }
+#endif /* SAMPLE_DHCP_DISABLE */
+
+ /* Sync time by NTP server array. */
+ for (UINT i = 0; i < SAMPLE_SNTP_SYNC_MAX; i++)
+ {
+ printf("SNTP Time Sync...%s\r\n", sntp_servers[sntp_server_index]);
+
+ /* Look up SNTP Server address. */
+ status = nx_dns_host_by_name_get(&dns_0, (UCHAR *)sntp_servers[sntp_server_index], &sntp_server_address[0], 5 * NX_IP_PERIODIC_RATE);
+
+ /* Check status. */
+ if (status == NX_SUCCESS)
+ {
+
+ /* Start SNTP to sync the local time. */
+ status = sntp_time_sync_internal(sntp_server_address[0]);
+
+ /* Check status. */
+ if(status == NX_SUCCESS)
+ {
+ return(NX_SUCCESS);
+ }
+ }
+
+ /* Switch SNTP server every time. */
+ sntp_server_index = (sntp_server_index + 1) % (sizeof(sntp_servers) / sizeof(sntp_servers[0]));
+ }
+
+ return(NX_NOT_SUCCESSFUL);
+}
+
static UINT unix_time_get(ULONG *unix_time)
{
- /* Using time() to get unix time on x86.
- Note: User needs to implement own time function to get the real time on device, such as: SNTP. */
- *unix_time = (ULONG)time(NULL);
+ /* Return number of seconds since Unix Epoch (1/1/1970 00:00:00). */
+ *unix_time = unix_time_base + (tx_time_get() / TX_TIMER_TICKS_PER_SECOND);
return(NX_SUCCESS);
}
diff --git a/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_pnp.c b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_pnp.c
index 226e134b..0f8b10b7 100644
--- a/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_pnp.c
+++ b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_pnp.c
@@ -300,6 +300,7 @@ static UINT sample_parse_desired_temp_property(SAMPLE_CONTEXT *context,
double parsed_value;
UINT version;
NX_AZURE_IOT_JSON_READER copy_json_reader;
+UINT status;
if (nx_azure_iot_json_reader_next_token(json_reader_ptr))
{
@@ -325,12 +326,12 @@ NX_AZURE_IOT_JSON_READER copy_json_reader;
return(NX_NOT_SUCCESSFUL);
}
- if (sample_json_child_token_move(json_reader_ptr,
- (UCHAR *)desired_temp_property_name,
- sizeof(desired_temp_property_name) - 1) ||
- nx_azure_iot_json_reader_token_double_get(json_reader_ptr, &parsed_value))
+ if ((status = sample_json_child_token_move(json_reader_ptr,
+ (UCHAR *)desired_temp_property_name,
+ sizeof(desired_temp_property_name) - 1)) ||
+ (status = nx_azure_iot_json_reader_token_double_get(json_reader_ptr, &parsed_value)))
{
- return(NX_NOT_SUCCESSFUL);
+ return(status);
}
current_device_temp = parsed_value;
@@ -920,7 +921,8 @@ NX_AZURE_IOT_JSON_READER json_reader;
return;
}
- if (sample_parse_desired_temp_property(context, &json_reader, NX_TRUE) != NX_AZURE_IOT_SUCCESS)
+ status = sample_parse_desired_temp_property(context, &json_reader, NX_TRUE);
+ if (status && (status != NX_AZURE_IOT_NOT_FOUND))
{
printf("Failed to parse value\r\n");
}
@@ -1014,7 +1016,8 @@ NX_AZURE_IOT_JSON_READER json_reader;
return;
}
- if (sample_parse_desired_temp_property(context, &json_reader, NX_FALSE) != NX_AZURE_IOT_SUCCESS)
+ status = sample_parse_desired_temp_property(context, &json_reader, NX_FALSE);
+ if (status && (status != NX_AZURE_IOT_NOT_FOUND))
{
printf("Failed to parse value\r\n");
}
diff --git a/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_with_retry.c b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_with_retry.c
index 2ecde8b7..8080d903 100644
--- a/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_with_retry.c
+++ b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_with_retry.c
@@ -224,6 +224,12 @@ UINT status;
}
break;
+ case NX_AZURE_IOT_SAS_TOKEN_EXPIRED:
+ {
+ printf("SAS token expired\r\n");
+ }
+ /* fallthrough */
+
default :
{
printf("reconnecting iothub, after backoff\r\n");
diff --git a/addons/dhcp/nxd_dhcp_client.c b/addons/dhcp/nxd_dhcp_client.c
index 4944b179..1699b143 100644
--- a/addons/dhcp/nxd_dhcp_client.c
+++ b/addons/dhcp/nxd_dhcp_client.c
@@ -46,6 +46,7 @@ static UINT _nx_dhcp_extract_information(NX_DHCP *dhcp_ptr, NX_DHCP_INTER
static UINT _nx_dhcp_get_option_value(UCHAR *bootp_message, UINT option, ULONG *value, UINT length);
static UINT _nx_dhcp_add_option_value(UCHAR *bootp_message, UINT option, UINT size, ULONG value, UINT *index);
static UINT _nx_dhcp_add_option_string(UCHAR *bootp_message, UINT option, UINT size, UCHAR *value, UINT *index);
+static UINT _nx_dhcp_add_option_parameter_request(NX_DHCP *dhcp_ptr, UCHAR *bootp_message, UINT *index);
static ULONG _nx_dhcp_update_timeout(ULONG timeout);
static ULONG _nx_dhcp_update_renewal_timeout(ULONG timeout);
static UCHAR *_nx_dhcp_search_buffer(UCHAR *option_message, UINT option, UINT length);
@@ -69,8 +70,8 @@ static VOID _nx_dhcp_ip_conflict(NX_IP *ip_ptr, UINT interface_index, ULO
/* Define the Request string that specifies which options are to be added
- to the DHCP Client discover request to the server. Additional options
- (found in nx_dhcp.h) may be added after the last option. */
+ to the DHCP Client discover request to the server. Additional options
+ (found in nx_dhcp.h) may be added by calling nx_dhcp_user_option_request(). */
UCHAR _nx_dhcp_request_parameters[] = { NX_DHCP_OPTION_SUBNET_MASK,
NX_DHCP_OPTION_GATEWAYS,
@@ -153,7 +154,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* _nx_dhcp_create PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -203,6 +204,9 @@ UINT status;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* improved the code, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_dhcp_create(NX_DHCP *dhcp_ptr, NX_IP *ip_ptr, CHAR *name_ptr)
@@ -384,7 +388,7 @@ UINT label_length = 0;
NX_TIMER_EXTENSION_PTR_SET(&(dhcp_ptr -> nx_dhcp_timer), dhcp_ptr)
/* Determine if the semaphore creation was successful. */
- if (status != NX_SUCCESS)
+ if (status != TX_SUCCESS)
{
/* Delete the UDP socket. */
@@ -403,7 +407,7 @@ UINT label_length = 0;
status = tx_mutex_create(&(dhcp_ptr -> nx_dhcp_mutex), "NetX DHCP Client", TX_NO_INHERIT);
/* Determine if the semaphore creation was successful. */
- if (status != NX_SUCCESS)
+ if (status != TX_SUCCESS)
{
/* Delete the UDP socket. */
@@ -429,7 +433,7 @@ UINT label_length = 0;
NX_THREAD_EXTENSION_PTR_SET(&(dhcp_ptr -> nx_dhcp_thread), dhcp_ptr)
/* Determine if the thread creation was successful. */
- if (status != NX_SUCCESS)
+ if (status != TX_SUCCESS)
{
/* Delete the mutex. */
@@ -4317,6 +4321,153 @@ UINT status;
/* */
/* FUNCTION RELEASE */
/* */
+/* _nxe_dhcp_user_option_request PORTABLE C */
+/* 6.1.8 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in the DHCP user option function */
+/* call. */
+/* */
+/* INPUT */
+/* */
+/* dhcp_ptr Pointer to DHCP instance */
+/* option_code Option code */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* NX_PTR_ERROR Invalid pointer input */
+/* */
+/* CALLS */
+/* */
+/* _nx_dhcp_user_option_request Actual DHCP user option */
+/* request function call */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */
+/* */
+/**************************************************************************/
+UINT _nxe_dhcp_user_option_request(NX_DHCP *dhcp_ptr, UINT option_code)
+{
+
+UINT status;
+
+
+ /* Check for invalid input pointer. */
+ if ((dhcp_ptr == NX_NULL) || (dhcp_ptr -> nx_dhcp_id != NX_DHCP_ID))
+ return(NX_PTR_ERROR);
+
+ /* Check for appropriate caller. */
+ NX_THREADS_ONLY_CALLER_CHECKING
+
+ /* Call actual DHCP interface user option request service. */
+ status = _nx_dhcp_user_option_request(dhcp_ptr, option_code);
+
+ /* Return status. */
+ return(status);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_dhcp_user_option_request PORTABLE C */
+/* 6.1.8 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function requests the additional user option. */
+/* */
+/* INPUT */
+/* */
+/* dhcp_ptr Pointer to DHCP instance */
+/* option_code Option code */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* tx_mutex_get Get the DHCP mutex */
+/* tx_mutex_put Release the DHCP mutex */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */
+/* */
+/**************************************************************************/
+UINT _nx_dhcp_user_option_request(NX_DHCP *dhcp_ptr, UINT option_code)
+{
+UINT i;
+
+
+ /* Obtain DHCP Client protection mutex. */
+ tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER);
+
+ /* Check if the default option array already has it. */
+ for (i = 0; i < NX_DHCP_REQUEST_PARAMETER_SIZE; i++)
+ {
+ if (_nx_dhcp_request_parameters[i] == option_code)
+ {
+ tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
+ return(NX_DUPLICATED_ENTRY);
+ }
+ }
+
+ /* Check if the user option array already has it. */
+ for (i = 0; i < dhcp_ptr -> nx_dhcp_user_request_parameter_size; i++)
+ {
+ if (dhcp_ptr -> nx_dhcp_user_request_parameter[i] == option_code)
+ {
+ tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
+ return(NX_DUPLICATED_ENTRY);
+ }
+ }
+
+ /* Check if there is space to add option. */
+ if (dhcp_ptr -> nx_dhcp_user_request_parameter_size >= NX_DHCP_CLIENT_MAX_USER_REQUEST_PARAMETER)
+ {
+ tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
+ return(NX_NO_MORE_ENTRIES);
+ }
+
+ /* Add the option. */
+ dhcp_ptr -> nx_dhcp_user_request_parameter[dhcp_ptr -> nx_dhcp_user_request_parameter_size++] = (UCHAR)option_code;
+
+ /* Release the DHCP mutex. */
+ tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex));
+
+ /* Return success. */
+ return(NX_SUCCESS);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
/* _nxe_dhcp_interface_user_option_retrieve PORTABLE C */
/* 6.1 */
/* AUTHOR */
@@ -6400,7 +6551,7 @@ NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
/* FUNCTION RELEASE */
/* */
/* _nx_dhcp_send_request_internal PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -6430,6 +6581,7 @@ NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
/* _nx_dhcp_add_option_value Add an option to the request */
/* _nx_dhcp_add_option_string Add an option string to the */
/* request */
+/* _nx_dhcp_add_option_parameter_request Add a parameter request option*/
/* nx_udp_socket_interface_send Send packet out on interface */
/* _nx_dhcp_client_send_with_zero_source_address */
/* Send broadcast packet with */
@@ -6455,6 +6607,10 @@ NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), supported*/
+/* adding additional request */
+/* option in parameter request,*/
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
static UINT _nx_dhcp_send_request_internal(NX_DHCP *dhcp_ptr, NX_DHCP_INTERFACE_RECORD *interface_record, UINT dhcp_message_type)
@@ -6619,8 +6775,8 @@ UINT name_length;
(UCHAR *) dhcp_ptr -> nx_dhcp_name, &index);
}
- /* Add an option request for DHCP parameters (gateway, subnet mask, etc.). */
- _nx_dhcp_add_option_string(buffer, NX_DHCP_OPTION_DHCP_PARAMETERS, NX_DHCP_REQUEST_PARAMETER_SIZE, _nx_dhcp_request_parameters, &index);
+ /* Add parameter request option. */
+ _nx_dhcp_add_option_parameter_request(dhcp_ptr, buffer, &index);
#ifdef NX_DHCP_CLIENT_SEND_MAX_DHCP_MESSAGE_OPTION
@@ -6690,9 +6846,9 @@ UINT name_length;
_nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_CLIENT_IP, 4, interface_record -> nx_dhcp_ip_address);
}
- /* Add the request for the DHCP parameters (gateway, subnet mask, etc.) if not renewing. */
- _nx_dhcp_add_option_string(buffer, NX_DHCP_OPTION_DHCP_PARAMETERS, NX_DHCP_REQUEST_PARAMETER_SIZE, _nx_dhcp_request_parameters, &index);
-
+ /* Add parameter request option. */
+ _nx_dhcp_add_option_parameter_request(dhcp_ptr, buffer, &index);
+
#ifdef NX_DHCP_CLIENT_SEND_MAX_DHCP_MESSAGE_OPTION
/* Add an option to specify the maximum length DHCP message that DHCP Client is willing to accept.
@@ -6751,8 +6907,8 @@ UINT name_length;
_nx_dhcp_add_option_string(buffer, NX_DHCP_OPTION_HOST_NAME, name_length, (UCHAR *) dhcp_ptr -> nx_dhcp_name, &index);
}
- /* Add an option request for DHCP parameters (gateway, subnet mask, etc.). */
- _nx_dhcp_add_option_string(buffer, NX_DHCP_OPTION_DHCP_PARAMETERS, 1, &(interface_record -> nx_dhcp_user_option), &index);
+ /* Add parameter request option. */
+ _nx_dhcp_add_option_parameter_request(dhcp_ptr, buffer, &index);
/* Increment the number of Inform messages sent. */
interface_record -> nx_dhcp_informs_sent++;
@@ -6858,7 +7014,7 @@ UINT name_length;
/* FUNCTION RELEASE */
/* */
/* _nx_dhcp_client_send_with_zero_source_address PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -6893,6 +7049,9 @@ UINT name_length;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported new ip filter, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
static UINT _nx_dhcp_client_send_with_zero_source_address(NX_DHCP *dhcp_ptr, UINT iface_index, NX_PACKET *packet_ptr)
@@ -7097,6 +7256,22 @@ NX_IP_DRIVER driver_request;
return(NX_NOT_SUCCESSFUL);
}
}
+
+ /* Check if the IP packet filter extended is set. */
+ if (ip_ptr -> nx_ip_packet_filter_extended)
+ {
+
+ /* Yes, call the IP packet filter extended routine. */
+ if (ip_ptr -> nx_ip_packet_filter_extended(ip_ptr, packet_ptr, NX_IP_PACKET_OUT) != NX_SUCCESS)
+ {
+
+ /* Release mutex protection. */
+ tx_mutex_put(&(ip_ptr -> nx_ip_protection));
+
+ /* Return a not successful status. */
+ return(NX_NOT_SUCCESSFUL);
+ }
+ }
#endif /* NX_ENABLE_IP_PACKET_FILTER */
/* Build the driver request. */
@@ -7690,6 +7865,74 @@ static UINT _nx_dhcp_add_option_string(UCHAR *bootp_message, UINT option, UINT
/* */
/* FUNCTION RELEASE */
/* */
+/* _nx_dhcp_add_option_parameter_request PORTABLE C */
+/* 6.1.8 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This routine adds a DHCP parameter request option to the BootP */
+/* message in supplied buffer. Adding the option includes adding the */
+/* option code, length and option value. */
+/* */
+/* INPUT */
+/* */
+/* dhcp_ptr Pointer to DHCP instance */
+/* bootp_message Pointer to message buffer */
+/* index Index to write data */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_dhcp_move_string Store option string */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_dhcp_send_request_internal Internal DHCP message send */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */
+/* */
+/**************************************************************************/
+static UINT _nx_dhcp_add_option_parameter_request(NX_DHCP *dhcp_ptr, UCHAR *bootp_message, UINT *index)
+{
+
+ /* Store the option. */
+ *(bootp_message + (*index)) = NX_DHCP_OPTION_DHCP_PARAMETERS;
+ (*index) ++;
+
+ /* Store the option size. */
+ *(bootp_message + (*index)) = (UCHAR)(NX_DHCP_REQUEST_PARAMETER_SIZE + dhcp_ptr -> nx_dhcp_user_request_parameter_size);
+ (*index) ++;
+
+ /* Store the option value. */
+ _nx_dhcp_move_string(bootp_message + (*index), _nx_dhcp_request_parameters, NX_DHCP_REQUEST_PARAMETER_SIZE);
+ (*index) += (UINT)NX_DHCP_REQUEST_PARAMETER_SIZE;
+
+ /* Check if there are additional user options. */
+ if (dhcp_ptr -> nx_dhcp_user_request_parameter_size)
+ {
+ _nx_dhcp_move_string(bootp_message + (*index), dhcp_ptr -> nx_dhcp_user_request_parameter, dhcp_ptr -> nx_dhcp_user_request_parameter_size);
+ (*index) += (UCHAR)dhcp_ptr -> nx_dhcp_user_request_parameter_size;
+ }
+
+ /* Return a successful completion. */
+ return(NX_SUCCESS);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
/* _nx_dhcp_add_randomize PORTABLE C */
/* 6.1 */
/* AUTHOR */
diff --git a/addons/dhcp/nxd_dhcp_client.h b/addons/dhcp/nxd_dhcp_client.h
index 8ace0784..0104b319 100644
--- a/addons/dhcp/nxd_dhcp_client.h
+++ b/addons/dhcp/nxd_dhcp_client.h
@@ -26,7 +26,7 @@
/* APPLICATION INTERFACE DEFINITION RELEASE */
/* */
/* nxd_dhcp_client.h PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -45,6 +45,10 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), supported*/
+/* adding additional request */
+/* option in parameter request,*/
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
@@ -129,6 +133,13 @@ extern "C" {
#endif
+/* Define the max number of user request parameter.
+ Subnet mask, gateway and dns server options are added in _nx_dhcp_request_parameters arrary by default. */
+#ifndef NX_DHCP_CLIENT_MAX_USER_REQUEST_PARAMETER
+#define NX_DHCP_CLIENT_MAX_USER_REQUEST_PARAMETER 4
+#endif /* NX_DHCP_CLIENT_MAX_USER_REQUEST_PARAMETER */
+
+
/* Define the size of DHCP options buffer. */
/* A DHCP client must be prepared to receive DHCP messages with an 'options' field of
at least length 312 octets. RFC 2131; Section 2. Protocol Summary. */
@@ -466,6 +477,10 @@ typedef struct NX_DHCP_STRUCT
NX_DHCP_INTERFACE_RECORD
nx_dhcp_interface_record[NX_DHCP_CLIENT_MAX_RECORDS];
/* Record of DHCP Client state on specific interface */
+ UCHAR nx_dhcp_user_request_parameter[NX_DHCP_CLIENT_MAX_USER_REQUEST_PARAMETER];
+ /* User request parameter */
+ UINT nx_dhcp_user_request_parameter_size;
+ /* User request parameter size */
#ifdef NX_DHCP_CLIENT_SEND_MAX_DHCP_MESSAGE_OPTION
ULONG nx_dhcp_max_dhcp_message_size;
@@ -525,6 +540,7 @@ typedef struct NX_DHCP_STRUCT
#define nx_dhcp_stop _nx_dhcp_stop
#define nx_dhcp_server_address_get _nx_dhcp_server_address_get
#define nx_dhcp_state_change_notify _nx_dhcp_state_change_notify
+#define nx_dhcp_user_option_request _nx_dhcp_user_option_request
#define nx_dhcp_user_option_retrieve _nx_dhcp_user_option_retrieve
#define nx_dhcp_user_option_convert _nx_dhcp_user_option_convert
#define nx_dhcp_user_option_add_callback_set _nx_dhcp_user_option_add_callback_set
@@ -572,6 +588,7 @@ typedef struct NX_DHCP_STRUCT
#define nx_dhcp_stop _nxe_dhcp_stop
#define nx_dhcp_server_address_get _nxe_dhcp_server_address_get
#define nx_dhcp_state_change_notify _nxe_dhcp_state_change_notify
+#define nx_dhcp_user_option_request _nxe_dhcp_user_option_request
#define nx_dhcp_user_option_retrieve _nxe_dhcp_user_option_retrieve
#define nx_dhcp_user_option_convert _nxe_dhcp_user_option_convert
#define nx_dhcp_user_option_add_callback_set _nxe_dhcp_user_option_add_callback_set
@@ -619,6 +636,7 @@ UINT nx_dhcp_start(NX_DHCP *dhcp_ptr);
UINT nx_dhcp_stop(NX_DHCP *dhcp_ptr);
UINT nx_dhcp_server_address_get(NX_DHCP *dhcp_ptr, ULONG *server_address);
UINT nx_dhcp_state_change_notify(NX_DHCP *dhcp_ptr, VOID (*dhcp_state_change_notify)(NX_DHCP *dhcp_ptr, UCHAR new_state));
+UINT nx_dhcp_user_option_request(NX_DHCP *dhcp_ptr, UINT option_code);
UINT nx_dhcp_user_option_retrieve(NX_DHCP *dhcp_ptr, UINT request_option, UCHAR *destination_ptr, UINT *destination_size);
ULONG nx_dhcp_user_option_convert(UCHAR *source_ptr);
UINT nx_dhcp_user_option_add_callback_set(NX_DHCP *dhcp_ptr, UINT (*dhcp_user_option_add)(NX_DHCP *dhcp_ptr, UINT iface_index, UINT message_type, UCHAR *user_option_ptr, UINT *user_option_length));
@@ -678,6 +696,8 @@ UINT _nxe_dhcp_server_address_get(NX_DHCP *dhcp_ptr, ULONG *server_addres
UINT _nx_dhcp_server_address_get(NX_DHCP *dhcp_ptr, ULONG *server_address);
UINT _nxe_dhcp_state_change_notify(NX_DHCP *dhcp_ptr, VOID (*dhcp_state_change_notify)(NX_DHCP *dhcp_ptr, UCHAR new_state));
UINT _nx_dhcp_state_change_notify(NX_DHCP *dhcp_ptr, VOID (*dhcp_state_change_notify)(NX_DHCP *dhcp_ptr, UCHAR new_state));
+UINT _nxe_dhcp_user_option_request(NX_DHCP *dhcp_ptr, UINT option_code);
+UINT _nx_dhcp_user_option_request(NX_DHCP *dhcp_ptr, UINT option_code);
UINT _nxe_dhcp_user_option_retrieve(NX_DHCP *dhcp_ptr, UINT request_option, UCHAR *destination_ptr, UINT *destination_size);
UINT _nx_dhcp_user_option_retrieve(NX_DHCP *dhcp_ptr, UINT request_option, UCHAR *destination_ptr, UINT *destination_size);
ULONG _nxe_dhcp_user_option_convert(UCHAR *source_ptr);
diff --git a/addons/ftp/nxd_ftp_server.c b/addons/ftp/nxd_ftp_server.c
index ad4d1d3d..c5db8ab9 100644
--- a/addons/ftp/nxd_ftp_server.c
+++ b/addons/ftp/nxd_ftp_server.c
@@ -80,7 +80,7 @@ NX_CALLER_CHECKING_EXTERNS
#define NX_FTP_CODE_NO_SPACE "552" /* Requested file action aborted, no space. */
#define NX_FTP_CODE_BAD_NAME "553" /* Requested action not taken, File name not allowed. */
-static VOID _nx_ftp_server_number_to_ascii(UCHAR *buffer_ptr, UINT buffer_size, UINT number);
+static VOID _nx_ftp_server_number_to_ascii(UCHAR *buffer_ptr, UINT buffer_size, UINT number, UCHAR pad);
/**************************************************************************/
/* */
@@ -1523,7 +1523,7 @@ ULONG events;
/* FUNCTION RELEASE */
/* */
/* _nx_ftp_server_command_process PORTABLE C */
-/* 6.1.3 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -1598,6 +1598,9 @@ ULONG events;
/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
/* packet length verification, */
/* resulting in version 6.1.3 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), */
+/* corrected the pad character,*/
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
VOID _nx_ftp_server_command_process(NX_FTP_SERVER *ftp_server_ptr)
@@ -3582,17 +3585,17 @@ ULONG block_size;
memcpy(&buffer_ptr[1], "rw-rw-rw-", 9); /* Use case of memcpy is verified. */
}
memcpy(&buffer_ptr[10], " 1 owner group ", 16); /* Use case of memcpy is verified. */
- _nx_ftp_server_number_to_ascii(&buffer_ptr[26], 10, size);
+ _nx_ftp_server_number_to_ascii(&buffer_ptr[26], 10, size, ' ');
buffer_ptr[36] = ' ';
buffer_ptr[37] = (UCHAR)months[month - 1][0];
buffer_ptr[38] = (UCHAR)months[month - 1][1];
buffer_ptr[39] = (UCHAR)months[month - 1][2];
buffer_ptr[40] = ' ';
- _nx_ftp_server_number_to_ascii(&buffer_ptr[41], 2, day);
+ _nx_ftp_server_number_to_ascii(&buffer_ptr[41], 2, day, '0');
buffer_ptr[43] = ' ';
- _nx_ftp_server_number_to_ascii(&buffer_ptr[44], 2, hour);
+ _nx_ftp_server_number_to_ascii(&buffer_ptr[44], 2, hour, '0');
buffer_ptr[46] = ':';
- _nx_ftp_server_number_to_ascii(&buffer_ptr[47], 2, minute);
+ _nx_ftp_server_number_to_ascii(&buffer_ptr[47], 2, minute, '0');
buffer_ptr[49] = ' ';
memcpy(&buffer_ptr[50], filename, length); /* Use case of memcpy is verified. */
length += 50;
@@ -6866,7 +6869,7 @@ NX_PACKET *last_packet;
/* FUNCTION RELEASE */
/* */
/* _nx_ftp_server_number_to_ascii PORTABLE C */
-/* 6.1.7 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -6905,9 +6908,12 @@ NX_PACKET *last_packet;
/* 06-02-2021 Yuxin Zhou Modified comment(s), and */
/* corrected the size check, */
/* resulting in version 6.1.7 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), */
+/* corrected the pad character,*/
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
-static VOID _nx_ftp_server_number_to_ascii(UCHAR *buffer_ptr, UINT buffer_size, UINT number)
+static VOID _nx_ftp_server_number_to_ascii(UCHAR *buffer_ptr, UINT buffer_size, UINT number, UCHAR pad)
{
UINT digit;
UINT size;
@@ -6915,8 +6921,8 @@ UINT size;
/* Initialize counters. */
size = 1;
- /* Initialize buffer with spaces. */
- memset(buffer_ptr, ' ', buffer_size);
+ /* Initialize buffer with pad character. */
+ memset(buffer_ptr, pad, buffer_size);
/* Loop to convert the number to ASCII. */
while (size <= buffer_size)
diff --git a/addons/http/nxd_http_server.c b/addons/http/nxd_http_server.c
index d886abd2..50c75ed6 100644
--- a/addons/http/nxd_http_server.c
+++ b/addons/http/nxd_http_server.c
@@ -5364,105 +5364,6 @@ CHAR *buffer_ptr;
/* */
/* FUNCTION RELEASE */
/* */
-/* _nx_http_server_number_convert PORTABLE C */
-/* 6.1 */
-/* AUTHOR */
-/* */
-/* Yuxin Zhou, Microsoft Corporation */
-/* */
-/* DESCRIPTION */
-/* */
-/* This function converts a number into an ASCII string. */
-/* */
-/* INPUT */
-/* */
-/* number Unsigned integer number */
-/* string Destination string */
-/* */
-/* OUTPUT */
-/* */
-/* Size Number of bytes in string */
-/* (0 implies an error) */
-/* */
-/* CALLS */
-/* */
-/* None */
-/* */
-/* CALLED BY */
-/* */
-/* _nx_http_server_get_process Process GET request */
-/* _nx_http_server_response_send Send response to client */
-/* */
-/* RELEASE HISTORY */
-/* */
-/* DATE NAME DESCRIPTION */
-/* */
-/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
-/* 09-30-2020 Yuxin Zhou Modified comment(s), */
-/* resulting in version 6.1 */
-/* */
-/**************************************************************************/
-UINT _nx_http_server_number_convert(UINT number, CHAR *string)
-{
-
-UINT j;
-UINT digit;
-UINT size;
-
-
- /* Initialize counters. */
- size = 0;
-
- /* Loop to convert the number to ASCII. */
- while (size < 10)
- {
-
- /* Shift the current digits over one. */
- for (j = size; j != 0; j--)
- {
-
- /* Move each digit over one place. */
- string[j] = string[j-1];
- }
-
- /* Compute the next decimal digit. */
- digit = number % 10;
-
- /* Update the input number. */
- number = number / 10;
-
- /* Store the new digit in ASCII form. */
- string[0] = (CHAR) (digit + 0x30);
-
- /* Increment the size. */
- size++;
-
- /* Determine if the number is now zero. */
- if (number == 0)
- break;
- }
-
- /* Make the string NULL terminated. */
- string[size] = (CHAR) NX_NULL;
-
- /* Determine if there is an overflow error. */
- if (number)
- {
-
- /* Error, return bad values to user. */
- size = 0;
- string[0] = '0';
- }
-
- /* Return size to caller. */
- return(size);
-}
-
-
-/**************************************************************************/
-/* */
-/* FUNCTION RELEASE */
-/* */
/* _nxe_http_server_type_get PORTABLE C */
/* 6.1 */
/* AUTHOR */
@@ -7789,7 +7690,7 @@ UCHAR ch;
/* FUNCTION RELEASE */
/* */
/* _nx_http_server_generate_response_header PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -7824,7 +7725,7 @@ UCHAR ch;
/* nx_packet_data_append */
/* memcmp */
/* _nx_utility_string_length_check */
-/* _nx_http_server_number_convert */
+/* _nx_utility_uint_to_string */
/* _nx_http_server_date_to_string */
/* nx_packet_release */
/* */
@@ -7843,6 +7744,10 @@ UCHAR ch;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), */
+/* improved the logic of */
+/* converting number to string,*/
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_http_server_generate_response_header(NX_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr, CHAR *status_code,
@@ -7926,7 +7831,7 @@ CHAR status_code_not_modified;
{
/* Convert the content_length to ASCII representation. */
- temp = _nx_http_server_number_convert(content_length, temp_string);
+ temp = _nx_utility_uint_to_string(content_length, 10, temp_string, sizeof(temp_string));
/* Place the "Content-Length" field in the header. */
status += nx_packet_data_append(packet_ptr, "Content-Length: ", 16,
@@ -7990,7 +7895,7 @@ CHAR status_code_not_modified;
server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
/* Convert the max-age to ASCII representation. */
- temp = _nx_http_server_number_convert(max_age, temp_string);
+ temp = _nx_utility_uint_to_string(max_age, 10, temp_string, sizeof(temp_string));
status += nx_packet_data_append(packet_ptr, temp_string, temp,
server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
diff --git a/addons/http/nxd_http_server.h b/addons/http/nxd_http_server.h
index 01a5c327..ffa237b6 100644
--- a/addons/http/nxd_http_server.h
+++ b/addons/http/nxd_http_server.h
@@ -26,7 +26,7 @@
/* APPLICATION INTERFACE DEFINITION RELEASE */
/* */
/* nxd_http_server.h PORTABLE C */
-/* 6.1.6 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -49,6 +49,10 @@
/* improved the logic of */
/* parsing base64, */
/* resulting in version 6.1.6 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* improved the logic of */
+/* converting number to string,*/
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
@@ -577,7 +581,6 @@ UINT _nx_http_server_basic_authenticate(NX_HTTP_SERVER *server_ptr, NX_PA
UINT _nx_http_server_retrieve_basic_authorization(NX_PACKET *packet_ptr, CHAR *authorization_request_ptr);
UINT _nx_http_server_retrieve_resource(NX_PACKET *packet_ptr, CHAR *destination, UINT max_size);
UINT _nx_http_server_calculate_content_offset(NX_PACKET *packet_ptr);
-UINT _nx_http_server_number_convert(UINT number, CHAR *string);
UINT _nx_http_server_type_get(NX_HTTP_SERVER *server_ptr, CHAR *name, CHAR *http_type_string);
UINT _nx_http_server_type_get_extended(NX_HTTP_SERVER *server_ptr, CHAR *name, UINT name_length, CHAR *http_type_string, UINT http_type_string_max_size);
diff --git a/addons/mqtt/nxd_mqtt_client.c b/addons/mqtt/nxd_mqtt_client.c
index 5915e7a1..fd296441 100644
--- a/addons/mqtt/nxd_mqtt_client.c
+++ b/addons/mqtt/nxd_mqtt_client.c
@@ -705,7 +705,7 @@ NXD_MQTT_CLIENT *client_ptr;
/* FUNCTION RELEASE */
/* */
/* _nxd_mqtt_copy_transmit_packet PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -749,6 +749,10 @@ NXD_MQTT_CLIENT *client_ptr;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), */
+/* supported maximum transmit */
+/* queue depth, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
static UINT _nxd_mqtt_copy_transmit_packet(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr, NX_PACKET **new_packet_ptr,
@@ -756,6 +760,15 @@ static UINT _nxd_mqtt_copy_transmit_packet(NXD_MQTT_CLIENT *client_ptr, NX_PACKE
{
UINT status;
+#ifdef NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH
+ if (client_ptr -> message_transmit_queue_depth >= NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH)
+ {
+
+ /* Hit the transmit queue depeth. No more packets should be queued. */
+ return(NX_TX_QUEUE_DEPTH);
+ }
+#endif /* NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH */
+
/* Copy current packet. */
status = nx_packet_copy(packet_ptr, new_packet_ptr, client_ptr -> nxd_mqtt_client_packet_pool_ptr, wait_option);
if (status)
@@ -775,6 +788,11 @@ UINT status;
*((*new_packet_ptr) -> nx_packet_prepend_ptr) = (*((*new_packet_ptr) -> nx_packet_prepend_ptr)) | MQTT_PUBLISH_DUP_FLAG;
}
+#ifdef NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH
+ /* Increase the transmit queue depth. */
+ client_ptr -> message_transmit_queue_depth++;
+#endif /* NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH */
+
return(NXD_MQTT_SUCCESS);
}
@@ -783,7 +801,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* _nxd_mqtt_release_transmit_packet PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -824,6 +842,10 @@ UINT status;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), */
+/* supported maximum transmit */
+/* queue depth, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
static VOID _nxd_mqtt_release_transmit_packet(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr, NX_PACKET *previous_packet_ptr)
@@ -843,6 +865,10 @@ static VOID _nxd_mqtt_release_transmit_packet(NXD_MQTT_CLIENT *client_ptr, NX_PA
client_ptr -> message_transmit_queue_tail = previous_packet_ptr;
}
nx_packet_release(packet_ptr);
+
+#ifdef NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH
+ client_ptr -> message_transmit_queue_depth--;
+#endif /* NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH */
}
/**************************************************************************/
@@ -3675,7 +3701,7 @@ UCHAR fixed_header;
/* FUNCTION RELEASE */
/* */
/* _nxd_mqtt_client_connect PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -3738,6 +3764,10 @@ UCHAR fixed_header;
/* is set in CONNACK, corrected*/
/* mqtt client state, */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* corrected the logic for */
+/* non-blocking mode, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nxd_mqtt_client_connect(NXD_MQTT_CLIENT *client_ptr, NXD_ADDRESS *server_ip, UINT server_port,
@@ -3916,7 +3946,7 @@ UINT old_priority;
}
/* Just return for non-blocking mode. */
- if (status == NX_IN_PROGRESS)
+ if ((status == NX_IN_PROGRESS) || (wait_option == 0))
{
return(NX_IN_PROGRESS);
}
@@ -4430,7 +4460,7 @@ UINT _nxd_mqtt_client_delete(NXD_MQTT_CLIENT *client_ptr)
/* FUNCTION RELEASE */
/* */
/* _nxd_mqtt_client_publish_packet_send PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -4472,6 +4502,10 @@ UINT _nxd_mqtt_client_delete(NXD_MQTT_CLIENT *client_ptr)
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), */
+/* supported maximum transmit */
+/* queue depth, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nxd_mqtt_client_publish_packet_send(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr,
@@ -4499,6 +4533,11 @@ UINT ret = NXD_MQTT_SUCCESS;
if (status != TX_SUCCESS)
{
nx_packet_release(transmit_packet_ptr);
+
+#ifdef NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH
+ /* Decrease the transmit queue depth. */
+ client_ptr -> message_transmit_queue_depth--;
+#endif /* NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH */
return(NXD_MQTT_MUTEX_FAILURE);
}
diff --git a/addons/mqtt/nxd_mqtt_client.h b/addons/mqtt/nxd_mqtt_client.h
index 92433689..89635132 100644
--- a/addons/mqtt/nxd_mqtt_client.h
+++ b/addons/mqtt/nxd_mqtt_client.h
@@ -26,7 +26,7 @@
/* APPLICATION INTERFACE DEFINITION RELEASE */
/* */
/* nxd_mqtt_client.h PORTABLE C */
-/* 6.1.2 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -48,6 +48,10 @@
/* 11-09-2020 Yuxin Zhou Modified comment(s), and */
/* added packet id parameter, */
/* resulting in version 6.1.2 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported maximum transmit */
+/* queue depth, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
@@ -78,6 +82,11 @@ extern "C" {
#endif /* NX_SECURE_ENABLE */
#endif /* NXD_MQTT_REQUIRE_TLS */
+/* Defined, MQTT transmit queue depth is enabled. It must be positive integer. */
+/*
+#define NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH 20
+*/
+
/* Define memcpy, memset and memcmp functions used internal. */
#ifndef NXD_MQTT_SECURE_MEMCPY
#define NXD_MQTT_SECURE_MEMCPY memcpy
@@ -331,6 +340,9 @@ typedef struct NXD_MQTT_CLIENT_STRUCT
NX_PACKET *nxd_mqtt_client_processing_packet;
NX_PACKET *message_transmit_queue_head;
NX_PACKET *message_transmit_queue_tail;
+#ifdef NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH
+ UINT message_transmit_queue_depth;
+#endif /* NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH */
NX_PACKET *message_receive_queue_head;
NX_PACKET *message_receive_queue_tail;
UINT message_receive_queue_depth;
diff --git a/addons/ppp/nx_ppp.c b/addons/ppp/nx_ppp.c
index 47410a20..6c214e58 100644
--- a/addons/ppp/nx_ppp.c
+++ b/addons/ppp/nx_ppp.c
@@ -2210,7 +2210,7 @@ NX_PACKET *packet_ptr;
/* FUNCTION RELEASE */
/* */
/* _nx_ppp_lcp_state_machine_update PORTABLE C */
-/* 6.1.2 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -2257,6 +2257,9 @@ NX_PACKET *packet_ptr;
/* improved packet length */
/* verification, */
/* resulting in version 6.1.2 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), fixed */
+/* the logic of retransmission,*/
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
void _nx_ppp_lcp_state_machine_update(NX_PPP *ppp_ptr, NX_PACKET *packet_ptr)
@@ -2801,9 +2804,6 @@ UINT status;
/* Yes, the peer can accept larger messages than the default. */
(ppp_ptr -> nx_ppp_interface_ptr) -> nx_interface_ip_mtu_size = ppp_ptr -> nx_ppp_mru;
}
-
- /* Disable the LCP timeout. */
- ppp_ptr -> nx_ppp_timeout = 0;
}
/* Send configuration reply. */
diff --git a/addons/snmp/nxd_snmp.c b/addons/snmp/nxd_snmp.c
index 42dd7f72..63b0ab08 100644
--- a/addons/snmp/nxd_snmp.c
+++ b/addons/snmp/nxd_snmp.c
@@ -14094,7 +14094,7 @@ UINT _nx_snmp_utility_error_info_set(UCHAR *buffer_ptr, UINT error_code, UINT e
/* FUNCTION RELEASE */
/* */
/* _nx_snmp_utility_object_id_get PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -14117,7 +14117,7 @@ UINT _nx_snmp_utility_error_info_set(UCHAR *buffer_ptr, UINT error_code, UINT e
/* */
/* CALLS */
/* */
-/* None */
+/* _nx_utility_uint_to_string Convert number to ASCII */
/* */
/* CALLED BY */
/* */
@@ -14133,6 +14133,10 @@ UINT _nx_snmp_utility_error_info_set(UCHAR *buffer_ptr, UINT error_code, UINT e
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), */
+/* improved the logic of */
+/* converting number to string,*/
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_snmp_utility_object_id_get(UCHAR *buffer_ptr, UCHAR *object_string, INT buffer_length)
@@ -14404,48 +14408,23 @@ UINT string_length;
value = value + temp;
}
- /* Loop to convert value into ASCII. */
- size = 0;
- do
- {
-
- /* Shift the current digits over one. */
- for (i = size; i != 0; i--)
- {
-
- /* Move each digit over one place. */
- object_string[i] = object_string[i-1];
- }
-
- /* Compute the next decimal digit. */
- byte = (UCHAR) (value % 10);
-
- /* Update the input number. */
- value = value / 10;
-
- /* Store the new digit in ASCII form. */
- object_string[0] = (UCHAR)(byte + 0x30);
-
- /* Increment the size. */
- size++;
-
- /* Increment the string length. */
- string_length++;
+ /* Convert value into ASCII. */
+ size = _nx_utility_uint_to_string(value, 10, (CHAR *)object_string, NX_SNMP_MAX_OCTET_STRING + 1 - string_length);
- /* Determine if the length is too long. */
- if (string_length >= NX_SNMP_MAX_OCTET_STRING)
- {
+ if (size == 0)
+ {
- /* String is too long. */
+ /* String is too long. */
- /* Null-terminate the string. */
- *object_string = NX_NULL;
+ /* Null-terminate the string. */
+ *object_string = NX_NULL;
- /* Return the length. */
- return(length);
- }
-
- } while ((size < 10) && (value));
+ /* Return the length. */
+ return(length);
+ }
+
+ /* Adjust the object string length. */
+ string_length += size;
/* Adjust the object string. */
object_string = object_string + size;
diff --git a/addons/sntp/nxd_sntp_client.c b/addons/sntp/nxd_sntp_client.c
index b6f5fe55..c876c1fc 100644
--- a/addons/sntp/nxd_sntp_client.c
+++ b/addons/sntp/nxd_sntp_client.c
@@ -72,8 +72,6 @@ extern volatile ULONG _tx_thread_system_state;
TX_EVENT_FLAGS_GROUP nx_sntp_client_events;
-static UINT _nx_sntp_client_number_to_ascii(CHAR *buffer_ptr, UINT buffer_size, UINT number);
-
/* Define internal time variables for offsets between
receipt of SNTP packet and application to
SNTP Client local time. */
@@ -4154,7 +4152,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* _nx_sntp_client_get_local_time_extended PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -4180,8 +4178,8 @@ UINT status;
/* CALLS */
/* */
/* _nx_sntp_client_utility_fraction_to_usecs */
-/* Convert NTP fraction to usecs */
-/* _nx_sntp_client_number_to_ascii Converts number to ascii text */
+/* Convert NTP fraction to usecs */
+/* _nx_utility_uint_to_string Converts number to ascii text */
/* */
/* CALLED BY */
/* */
@@ -4195,6 +4193,10 @@ UINT status;
/* 09-30-2020 Yuxin Zhou Modified comment(s), and */
/* verified memmove use cases, */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), */
+/* improved the logic of */
+/* converting number to string,*/
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_sntp_client_get_local_time_extended(NX_SNTP_CLIENT *client_ptr, ULONG *seconds, ULONG *fraction, CHAR *buffer, UINT buffer_size)
@@ -4228,8 +4230,8 @@ UINT length = 0;
buffer[offset++] = 'e';
buffer[offset++] = ':';
buffer[offset++] = ' ';
- length = _nx_sntp_client_number_to_ascii(&buffer[offset], buffer_size - offset,
- client_ptr->nx_sntp_client_local_ntp_time.seconds);
+ length = _nx_utility_uint_to_string(client_ptr -> nx_sntp_client_local_ntp_time.seconds,
+ 10, &buffer[offset], buffer_size - offset);
if (length == 0)
{
return(NX_SIZE_ERROR);
@@ -4240,7 +4242,7 @@ UINT length = 0;
return(NX_SIZE_ERROR);
}
buffer[offset++] = '.';
- length = _nx_sntp_client_number_to_ascii(&buffer[offset], 6, usecs);
+ length = _nx_utility_uint_to_string(usecs, 10, &buffer[offset], buffer_size - offset);
if (length == 0)
{
return(NX_SIZE_ERROR);
@@ -4253,6 +4255,8 @@ UINT length = 0;
memmove(&buffer[offset + (6 - length)], &buffer[offset], length); /* Use case of memmove is verified. */
memset(&buffer[offset], '0', (6 - length));
}
+
+ offset += 6;
buffer[offset++] = ' ';
buffer[offset++] = 's';
buffer[offset++] = 'e';
@@ -4840,7 +4844,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* _nx_sntp_client_utility_display_date_time PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -4869,8 +4873,8 @@ UINT status;
/* */
/* CALLS */
/* _nx_sntp_client_utility_convert_seconds_to_date */
-/* Converts seconds to year, month */
-/* _nx_sntp_client_number_to_ascii Converts number to ascii text */
+/* Converts seconds to year, month */
+/* _nx_utility_uint_to_string Converts number to ascii text */
/* */
/* CALLED BY */
/* */
@@ -4883,6 +4887,10 @@ UINT status;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), */
+/* improved the logic of */
+/* converting number to string,*/
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_sntp_client_utility_display_date_time(NX_SNTP_CLIENT *client_ptr, CHAR *buffer, UINT length)
@@ -4935,48 +4943,48 @@ const CHAR *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
offset = 4;
/* Write in the rest of the data as numeric from the Date Time objext. */
- return_length = _nx_sntp_client_number_to_ascii(&buffer[offset], length - offset, DisplayTime.day);
+ return_length = _nx_utility_uint_to_string(DisplayTime.day, 10, &buffer[offset], length - offset);
+ offset += return_length;
if ((return_length == 0) || ((length - offset) < 2))
{
return NX_SNTP_ERROR_CONVERTING_DATETIME;
}
- offset += return_length;
buffer[offset++] = ',';
buffer[offset++] = ' ';
- return_length = _nx_sntp_client_number_to_ascii(&buffer[offset], length - offset, DisplayTime.year);
+ return_length = _nx_utility_uint_to_string(DisplayTime.year, 10, &buffer[offset], length - offset);
+ offset += return_length;
if ((return_length == 0) || ((length - offset) < 1))
{
return NX_SNTP_ERROR_CONVERTING_DATETIME;
}
- offset += return_length;
buffer[offset++] = ' ';
- return_length = _nx_sntp_client_number_to_ascii(&buffer[offset], length - offset, DisplayTime.hour);
+ return_length = _nx_utility_uint_to_string(DisplayTime.hour, 10, &buffer[offset], length - offset);
+ offset += return_length;
if ((return_length == 0) || ((length - offset) < 1))
{
return NX_SNTP_ERROR_CONVERTING_DATETIME;
}
- offset += return_length;
buffer[offset++] = ':';
- return_length = _nx_sntp_client_number_to_ascii(&buffer[offset], length - offset, DisplayTime.minute);
+ return_length = _nx_utility_uint_to_string(DisplayTime.minute, 10, &buffer[offset], length - offset);
+ offset += return_length;
if ((return_length == 0) || ((length - offset) < 1))
{
return NX_SNTP_ERROR_CONVERTING_DATETIME;
}
- offset += return_length;
buffer[offset++] = ':';
- return_length = _nx_sntp_client_number_to_ascii(&buffer[offset], length - offset, DisplayTime.second);
+ return_length = _nx_utility_uint_to_string(DisplayTime.second, 10, &buffer[offset], length - offset);
+ offset += return_length;
if ((return_length == 0) || ((length - offset) < 1))
{
return NX_SNTP_ERROR_CONVERTING_DATETIME;
}
- offset += return_length;
buffer[offset++] = '.';
- return_length = _nx_sntp_client_number_to_ascii(&buffer[offset], length - offset, DisplayTime.millisecond);
+ return_length = _nx_utility_uint_to_string(DisplayTime.millisecond, 10, &buffer[offset], length - offset);
+ offset += return_length;
if ((return_length == 0) || ((length - offset) < 5))
{
return NX_SNTP_ERROR_CONVERTING_DATETIME;
}
- offset += return_length;
buffer[offset++] = ' ';
buffer[offset++] = 'U';
buffer[offset++] = 'T';
@@ -6404,105 +6412,4 @@ UINT carry;
/* Ok to add operands!*/
return NX_SUCCESS;
-}
-
-
-/**************************************************************************/
-/* */
-/* FUNCTION RELEASE */
-/* */
-/* _nx_sntp_client_number_to_ascii PORTABLE C */
-/* 6.1 */
-/* AUTHOR */
-/* */
-/* Yuxin Zhou, Microsoft Corporation */
-/* */
-/* DESCRIPTION */
-/* */
-/* This function converts a number to ascii text. */
-/* */
-/* INPUT */
-/* */
-/* buffer_ptr Pointer to output string buffer */
-/* buffer_size Size of output buffer */
-/* number Number to convert to ASCII */
-/* */
-/* OUTPUT */
-/* */
-/* size Size of converted string */
-/* */
-/* CALLS */
-/* */
-/* None */
-/* */
-/* CALLED BY */
-/* */
-/* _nx_sntp_client_utility_display_date_time */
-/* Convert an NTP time */
-/* */
-/* RELEASE HISTORY */
-/* */
-/* DATE NAME DESCRIPTION */
-/* */
-/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
-/* 09-30-2020 Yuxin Zhou Modified comment(s), */
-/* resulting in version 6.1 */
-/* */
-/**************************************************************************/
-static UINT _nx_sntp_client_number_to_ascii(CHAR *buffer_ptr, UINT buffer_size, UINT number)
-{
-
-UINT i;
-UINT digit;
-UINT size;
-
- /* Initialize counters. */
- size = 0;
-
- /* Loop to convert the number to ASCII. */
- while (size < buffer_size)
- {
-
- /* Shift the current digits over one. */
- for (i = size; i != 0; i--)
- {
-
- /* Move each digit over one place. */
- buffer_ptr[i] = buffer_ptr[i - 1];
- }
-
- /* Compute the next decimal digit. */
- digit = (number % 10);
-
- /* Update the input number. */
- number = (number / 10);
-
- /* Store the new digit in ASCII form. */
- if (digit < 10)
- {
- buffer_ptr[0] = (CHAR)(digit + '0');
- }
- else
- {
- buffer_ptr[0] = (CHAR)((digit - 10) + 'a');
- }
-
- /* Increment the size. */
- size++;
-
- /* Determine if the number is now zero. */
- if (number == 0)
- break;
- }
-
- /* Determine if there is an overflow error. */
- if (number)
- {
-
- /* Error, return bad values to user. */
- return(0);
- }
-
- /* Return size to caller. */
- return(size);
} \ No newline at end of file
diff --git a/addons/web/nx_web_http_server.c b/addons/web/nx_web_http_server.c
index f9db8487..0d18a9e1 100644
--- a/addons/web/nx_web_http_server.c
+++ b/addons/web/nx_web_http_server.c
@@ -5769,105 +5769,6 @@ UINT crlf_found = 0;
/* */
/* FUNCTION RELEASE */
/* */
-/* _nx_web_http_server_number_convert PORTABLE C */
-/* 6.1 */
-/* AUTHOR */
-/* */
-/* Yuxin Zhou, Microsoft Corporation */
-/* */
-/* DESCRIPTION */
-/* */
-/* This function converts a number into an ASCII string. */
-/* */
-/* INPUT */
-/* */
-/* number Unsigned integer number */
-/* string Destination string */
-/* */
-/* OUTPUT */
-/* */
-/* Size Number of bytes in string */
-/* (0 implies an error) */
-/* */
-/* CALLS */
-/* */
-/* None */
-/* */
-/* CALLED BY */
-/* */
-/* _nx_web_http_server_get_process Process GET request */
-/* _nx_web_http_server_response_send Send response to client */
-/* */
-/* RELEASE HISTORY */
-/* */
-/* DATE NAME DESCRIPTION */
-/* */
-/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
-/* 09-30-2020 Yuxin Zhou Modified comment(s), */
-/* resulting in version 6.1 */
-/* */
-/**************************************************************************/
-UINT _nx_web_http_server_number_convert(UINT number, CHAR *string)
-{
-
-UINT j;
-UINT digit;
-UINT size;
-
-
- /* Initialize counters. */
- size = 0;
-
- /* Loop to convert the number to ASCII. */
- while (size < 10)
- {
-
- /* Shift the current digits over one. */
- for (j = size; j != 0; j--)
- {
-
- /* Move each digit over one place. */
- string[j] = string[j-1];
- }
-
- /* Compute the next decimal digit. */
- digit = number % 10;
-
- /* Update the input number. */
- number = number / 10;
-
- /* Store the new digit in ASCII form. */
- string[0] = (CHAR) (digit + 0x30);
-
- /* Increment the size. */
- size++;
-
- /* Determine if the number is now zero. */
- if (number == 0)
- break;
- }
-
- /* Make the string NULL terminated. */
- string[size] = (CHAR) NX_NULL;
-
- /* Determine if there is an overflow error. */
- if (number)
- {
-
- /* Error, return bad values to user. */
- size = 0;
- string[0] = '0';
- }
-
- /* Return size to caller. */
- return(size);
-}
-
-
-/**************************************************************************/
-/* */
-/* FUNCTION RELEASE */
-/* */
/* _nxe_web_http_server_type_get PORTABLE C */
/* 6.1 */
/* AUTHOR */
@@ -8268,7 +8169,7 @@ UCHAR ch;
/* FUNCTION RELEASE */
/* */
/* _nx_web_http_server_generate_response_header PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -8299,7 +8200,7 @@ UCHAR ch;
/* Allocate response packet */
/* nx_packet_data_append Append packet data */
/* memcmp Compare string */
-/* _nx_web_http_server_number_convert Convert number to ASCII */
+/* _nx_utility_uint_to_string Convert number to ASCII */
/* _nx_web_http_server_date_to_string Convert data to string */
/* nx_packet_release Release packet */
/* */
@@ -8318,6 +8219,10 @@ UCHAR ch;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), */
+/* improved the logic of */
+/* converting number to string,*/
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_web_http_server_generate_response_header(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr,
@@ -8417,7 +8322,7 @@ CHAR status_code_not_modified;
{
/* Convert the content_length to ASCII representation. */
- temp = _nx_web_http_server_number_convert(content_length, temp_string);
+ temp = _nx_utility_uint_to_string(content_length, 10, temp_string, sizeof(temp_string));
/* Place the "Content-Length" field in the header. */
status += nx_packet_data_append(packet_ptr, "Content-Length: ", 16,
@@ -8485,7 +8390,7 @@ CHAR status_code_not_modified;
server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
/* Convert the max-age to ASCII representation. */
- temp = _nx_web_http_server_number_convert(max_age, temp_string);
+ temp = _nx_utility_uint_to_string(max_age, 10, temp_string, sizeof(temp_string));
status += nx_packet_data_append(packet_ptr, temp_string, temp,
server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
diff --git a/addons/web/nx_web_http_server.h b/addons/web/nx_web_http_server.h
index f55f7015..5603487f 100644
--- a/addons/web/nx_web_http_server.h
+++ b/addons/web/nx_web_http_server.h
@@ -27,7 +27,7 @@
/* APPLICATION INTERFACE DEFINITION RELEASE */
/* */
/* nx_web_http_server.h PORTABLE C */
-/* 6.1.6 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -50,6 +50,10 @@
/* improved the logic of */
/* parsing base64, */
/* resulting in version 6.1.6 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* improved the logic of */
+/* converting number to string,*/
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
@@ -557,7 +561,6 @@ UINT _nx_web_http_server_basic_authenticate(NX_WEB_HTTP_SERVER *server_pt
UINT _nx_web_http_server_retrieve_basic_authorization(NX_PACKET *packet_ptr, CHAR *authorization_request_ptr);
UINT _nx_web_http_server_retrieve_resource(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, CHAR *destination, UINT max_size);
UINT _nx_web_http_server_calculate_content_offset(NX_PACKET *packet_ptr);
-UINT _nx_web_http_server_number_convert(UINT number, CHAR *string);
UINT _nx_web_http_server_type_get(NX_WEB_HTTP_SERVER *server_ptr, CHAR *name, CHAR *http_type_string, UINT *string_size);
UINT _nx_web_http_server_type_get_extended(NX_WEB_HTTP_SERVER *server_ptr, CHAR *name, UINT name_length,
CHAR *http_type_string, UINT http_type_string_max_size, UINT *string_size);
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index 8351a24f..6c27f223 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -226,6 +226,7 @@ target_sources(${PROJECT_NAME}
${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_receive_cleanup.c
${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_server_socket_accept.c
${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_server_socket_listen.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_server_socket_driver_listen.c
${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_server_socket_relisten.c
${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_server_socket_unaccept.c
${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_server_socket_unlisten.c
@@ -236,6 +237,8 @@ target_sources(${PROJECT_NAME}
${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_socket_delete.c
${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_socket_disconnect.c
${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_socket_disconnect_complete_notify.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_socket_driver_establish.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_socket_driver_packet_receive.c
${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_socket_establish_notify.c
${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_socket_info_get.c
${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_socket_mss_get.c
@@ -287,6 +290,7 @@ target_sources(${PROJECT_NAME}
${CMAKE_CURRENT_LIST_DIR}/src/nx_udp_socket_checksum_enable.c
${CMAKE_CURRENT_LIST_DIR}/src/nx_udp_socket_create.c
${CMAKE_CURRENT_LIST_DIR}/src/nx_udp_socket_delete.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/nx_udp_socket_driver_packet_receive.c
${CMAKE_CURRENT_LIST_DIR}/src/nx_udp_socket_info_get.c
${CMAKE_CURRENT_LIST_DIR}/src/nx_udp_socket_port_get.c
${CMAKE_CURRENT_LIST_DIR}/src/nx_udp_socket_receive.c
diff --git a/common/inc/nx_api.h b/common/inc/nx_api.h
index 824d9655..4412ef12 100644
--- a/common/inc/nx_api.h
+++ b/common/inc/nx_api.h
@@ -26,7 +26,7 @@
/* APPLICATION INTERFACE DEFINITION RELEASE */
/* */
/* nx_api.h PORTABLE C */
-/* 6.1.7 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -70,6 +70,12 @@
/* 06-02-2021 Yuxin Zhou Modified comment(s), and */
/* updated product constants, */
/* resulting in version 6.1.7 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* added new ip filter, */
+/* added function to convert */
+/* unsigned integer to string, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
@@ -115,6 +121,12 @@ extern "C" {
#include "tx_trace.h"
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+#ifndef NX_ENABLE_INTERFACE_CAPABILITY
+#error "NX_ENABLE_INTERFACE_CAPABILITY must be defined to enable TCP/IP offload"
+#endif /* NX_ENABLE_INTERFACE_CAPABILITY */
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
/* Define symbols for compatibility before and after ThreadX 5.8. */
#if (((THREADX_MAJOR_VERSION << 8) | THREADX_MINOR_VERSION) >= 0x0508)
#define NX_CLEANUP_PARAMETER , ULONG suspension_sequence
@@ -477,7 +489,7 @@ VOID _nx_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, ULONG
#define AZURE_RTOS_NETXDUO
#define NETXDUO_MAJOR_VERSION 6
#define NETXDUO_MINOR_VERSION 1
-#define NETXDUO_PATCH_VERSION 7
+#define NETXDUO_PATCH_VERSION 8
/* Define the following symbols for backward compatibility */
#define EL_PRODUCT_NETXDUO
@@ -1271,6 +1283,7 @@ typedef struct NX_IPV6_DEFAULT_ROUTER_ENTRY_STRUCT
#define NX_PACKET_OFFSET_ERROR 0x53
#define NX_OPTION_HEADER_ERROR 0x54
#define NX_CONTINUE 0x55
+#define NX_TCPIP_OFFLOAD_ERROR 0x56
/* Define Link Driver constants. */
@@ -1305,6 +1318,19 @@ typedef struct NX_IPV6_DEFAULT_ROUTER_ENTRY_STRUCT
#define NX_LINK_USER_COMMAND 50 /* Values after this value are reserved for application. */
+
+/* Define operations for TCP/IP offload callback functions. */
+#define NX_TCPIP_OFFLOAD_TCP_CLIENT_SOCKET_CONNECT 0
+#define NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_LISTEN 1
+#define NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_ACCEPT 2
+#define NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_UNLISTEN 3
+#define NX_TCPIP_OFFLOAD_TCP_SOCKET_DISCONNECT 4
+#define NX_TCPIP_OFFLOAD_TCP_SOCKET_SEND 5
+#define NX_TCPIP_OFFLOAD_UDP_SOCKET_BIND 6
+#define NX_TCPIP_OFFLOAD_UDP_SOCKET_UNBIND 7
+#define NX_TCPIP_OFFLOAD_UDP_SOCKET_SEND 8
+
+
/* Define Link Driver Capability Flags. */
#ifdef NX_ENABLE_INTERFACE_CAPABILITY
#define NX_INTERFACE_CAPABILITY_IPV4_TX_CHECKSUM 0x00000001
@@ -1320,6 +1346,19 @@ typedef struct NX_IPV6_DEFAULT_ROUTER_ENTRY_STRUCT
#define NX_INTERFACE_CAPABILITY_IGMP_TX_CHECKSUM 0x00000400
#define NX_INTERFACE_CAPABILITY_IGMP_RX_CHECKSUM 0x00000800
#define NX_INTERFACE_CAPABILITY_PTP_TIMESTAMP 0x00001000
+#define NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD 0x00002000
+#define NX_INTERFACE_CAPABILITY_CHECKSUM_ALL (NX_INTERFACE_CAPABILITY_IPV4_TX_CHECKSUM | \
+ NX_INTERFACE_CAPABILITY_IPV4_RX_CHECKSUM | \
+ NX_INTERFACE_CAPABILITY_TCP_TX_CHECKSUM | \
+ NX_INTERFACE_CAPABILITY_TCP_RX_CHECKSUM | \
+ NX_INTERFACE_CAPABILITY_UDP_TX_CHECKSUM | \
+ NX_INTERFACE_CAPABILITY_UDP_RX_CHECKSUM | \
+ NX_INTERFACE_CAPABILITY_ICMPV4_TX_CHECKSUM | \
+ NX_INTERFACE_CAPABILITY_ICMPV4_RX_CHECKSUM | \
+ NX_INTERFACE_CAPABILITY_ICMPV6_RX_CHECKSUM | \
+ NX_INTERFACE_CAPABILITY_ICMPV6_TX_CHECKSUM | \
+ NX_INTERFACE_CAPABILITY_IGMP_TX_CHECKSUM | \
+ NX_INTERFACE_CAPABILITY_IGMP_RX_CHECKSUM)
#endif /* NX_ENABLE_INTERFACE_CAPABILITY */
#define NX_IP_VERSION_V4 0x4
@@ -1764,7 +1803,12 @@ typedef struct NX_UDP_SOCKET_STRUCT
/* This pointer is reserved for application specific use. */
/*lint -esym(768,NX_UDP_SOCKET_STRUCT::nx_udp_socket_reserved_ptr) suppress member not referenced. It is reserved for future use. */
void *nx_udp_socket_reserved_ptr;
-
+
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ /* Store a pointer to TCP/IP offload context. */
+ VOID *nx_udp_socket_tcpip_offload_context;
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
/* Define the port extension in the UDP socket control block. This
is typically defined to whitespace in nx_port.h. */
NX_UDP_SOCKET_MODULE_EXTENSION
@@ -2040,6 +2084,11 @@ typedef struct NX_TCP_SOCKET_STRUCT
#endif /* NX_IPSEC_ENABLE */
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ /* Store a pointer to TCP/IP offload context. */
+ VOID *nx_tcp_socket_tcpip_offload_context;
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
/* Define the port extension in the TCP socket control block. This
is typically defined to whitespace in nx_port.h. */
NX_TCP_SOCKET_MODULE_EXTENSION
@@ -2244,6 +2293,15 @@ typedef struct NX_INTERFACE_STRUCT
ARP packet that matches that of nx_interface_ip_probe_address. */
VOID (*nx_interface_ip_conflict_notify_handler)(struct NX_IP_STRUCT *, UINT, ULONG, ULONG, ULONG);
#endif /* !NX_DISABLE_IPV4 */
+
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ /* Define the TCP/IP offload handler. */
+ UINT (*nx_interface_tcpip_offload_handler)(struct NX_IP_STRUCT *ip_ptr,
+ struct NX_INTERFACE_STRUCT *interface_ptr,
+ VOID *socket_ptr, UINT operation, NX_PACKET *packet_ptr,
+ NXD_ADDRESS *local_ip, NXD_ADDRESS *remote_ip,
+ UINT local_port, UINT *remote_port, UINT wait_option);
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
} NX_INTERFACE;
/* Define the static IPv4 routing table entry structure. */
@@ -2913,6 +2971,10 @@ typedef struct NX_IP_STRUCT
#ifdef NX_ENABLE_IP_PACKET_FILTER
/* Define the IP packet filter routine. */
UINT (*nx_ip_packet_filter)(VOID *, UINT);
+
+ /* Define the IP packet filter extended routine. */
+ /* Note: Developers are encouraged to use nx_ip_packet_filter_extended since nx_ip_packet_filter will be deprecated.*/
+ UINT (*nx_ip_packet_filter_extended)(struct NX_IP_STRUCT *ip_ptr, NX_PACKET *packet_ptr, UINT direction);
#endif /* NX_ENABLE_IP_PACKET_FILTER */
/* Define the port extension in the IP control block. This
@@ -3746,6 +3808,18 @@ VOID _nx_ip_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
processing in the driver's receive ISR. */
VOID _nx_ip_driver_link_status_event(NX_IP *ip_ptr, UINT interface_index);
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+/* Define the direct TCP packet receive processing. This is used with TCP/IP offload feature. */
+VOID _nx_tcp_socket_driver_packet_receive(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr);
+
+/* Define the direct TCP established processing. This is used with TCP/IP offload feature. */
+UINT _nx_tcp_socket_driver_establish(NX_TCP_SOCKET *socket_ptr, NX_INTERFACE *interface_ptr, UINT remote_port);
+
+/* Define the direct UDP packet receive processing. This is used with TCP/IP offload feature. */
+VOID _nx_udp_socket_driver_packet_receive(NX_UDP_SOCKET *socket_ptr, NX_PACKET *packet_ptr,
+ NXD_ADDRESS *local_ip, NXD_ADDRESS *remote_ip, UINT remote_port);
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
#endif
#ifdef FEATURE_NX_IPV6
@@ -3823,6 +3897,7 @@ VOID _nx_ip_driver_link_status_event(NX_IP *ip_ptr, UINT interface_index);
/* Utility functions. */
UINT _nx_utility_string_length_check(CHAR *input_string, UINT *string_length, UINT max_string_length);
UINT _nx_utility_string_to_uint(CHAR *input_string, UINT string_length, UINT *number);
+UINT _nx_utility_uint_to_string(UINT number, UINT base, CHAR *string_buffer, UINT string_buffer_size);
UINT _nx_utility_base64_encode(UCHAR *name, UINT name_size, UCHAR *base64name, UINT base64name_size, UINT *bytes_copied);
UINT _nx_utility_base64_decode(UCHAR *base64name, UINT base64name_size, UCHAR *name, UINT name_size, UINT *bytes_copied);
diff --git a/common/inc/nx_ipv4.h b/common/inc/nx_ipv4.h
index 7f19e18a..2a929d9e 100644
--- a/common/inc/nx_ipv4.h
+++ b/common/inc/nx_ipv4.h
@@ -26,7 +26,7 @@
/* COMPONENT DEFINITION RELEASE */
/* */
/* nx_ipv4.h PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -44,6 +44,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
@@ -151,7 +154,8 @@ typedef struct NX_IPV4_HEADER_STRUCT
VOID _nx_ip_forward_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
VOID _nx_ip_fragment_forward_packet(NX_IP *ip_ptr, NX_PACKET *packet_ptr, ULONG destination_ip, ULONG fragment, ULONG next_hop_address);
void _nx_ip_packet_send(NX_IP *ip_ptr, NX_PACKET *packet_ptr, ULONG destination_ip, ULONG type_of_service, ULONG time_to_live, ULONG protocol, ULONG fragment, ULONG next_hop_address);
-UINT _nx_ip_header_add(NX_IP *ip_ptr, NX_PACKET *packet_ptr, ULONG destination_ip, ULONG type_of_service, ULONG time_to_live, ULONG protocol, ULONG fragment);
+UINT _nx_ip_header_add(NX_IP *ip_ptr, NX_PACKET *packet_ptr, ULONG source_ip, ULONG destination_ip,
+ ULONG type_of_service, ULONG time_to_live, ULONG protocol, ULONG fragment);
VOID _nx_ip_driver_packet_send(NX_IP *ip_ptr, NX_PACKET *packet_ptr, ULONG destination_ip, ULONG fragment, ULONG next_hop_address);
ULONG _nx_ip_route_find(NX_IP *ip_ptr, ULONG destination_address, NX_INTERFACE **nx_ip_interface, ULONG *next_hop_address);
VOID _nx_ipv4_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
diff --git a/common/inc/nx_tcp.h b/common/inc/nx_tcp.h
index ad83972f..3834d7d7 100644
--- a/common/inc/nx_tcp.h
+++ b/common/inc/nx_tcp.h
@@ -26,7 +26,7 @@
/* COMPONENT DEFINITION RELEASE */
/* */
/* nx_tcp.h PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -44,6 +44,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
@@ -278,6 +281,14 @@ UINT _nx_tcp_socket_establish_notify(NX_TCP_SOCKET *socket_ptr, VOID (*tcp_estab
UINT _nx_tcp_socket_disconnect_complete_notify(NX_TCP_SOCKET *socket_ptr, VOID (*tcp_disconnect_complete_notify)(NX_TCP_SOCKET *socket_ptr));
UINT _nx_tcp_socket_timed_wait_callback(NX_TCP_SOCKET *socket_ptr, VOID (*tcp_timed_wait_callback)(NX_TCP_SOCKET *socket_ptr));
UINT _nx_tcp_socket_receive_queue_max_set(NX_TCP_SOCKET *socket_ptr, UINT receive_queue_maximum);
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+/* Define the direct TCP packet receive processing. This is used with TCP/IP offload feature. */
+VOID _nx_tcp_socket_driver_packet_receive(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr);
+
+/* Define the direct TCP established processing. This is used with TCP/IP offload feature. */
+UINT _nx_tcp_socket_driver_establish(NX_TCP_SOCKET *socket_ptr, NX_INTERFACE *interface_ptr, UINT remote_port);
+UINT _nx_tcp_server_socket_driver_listen(NX_IP *ip_ptr, UINT port, NX_TCP_SOCKET *socket_ptr);
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
/* Define TCP component internal function prototypes. */
VOID _nx_tcp_cleanup_deferred(TX_THREAD *thread_ptr NX_CLEANUP_PARAMETER);
diff --git a/common/inc/nx_udp.h b/common/inc/nx_udp.h
index 599af6b2..ca884f39 100644
--- a/common/inc/nx_udp.h
+++ b/common/inc/nx_udp.h
@@ -26,7 +26,7 @@
/* COMPONENT DEFINITION RELEASE */
/* */
/* nx_udp.h PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -44,6 +44,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
@@ -116,6 +119,11 @@ UINT _nx_udp_socket_unbind(NX_UDP_SOCKET *socket_ptr);
UINT _nx_udp_source_extract(NX_PACKET *packet_ptr, ULONG *ip_address, UINT *port);
UINT _nx_udp_packet_info_extract(NX_PACKET *packet_ptr, ULONG *ip_address, UINT *protocol, UINT *port, UINT *interface_index);
UINT _nxd_udp_source_extract(NX_PACKET *packet_ptr, NXD_ADDRESS *ip_address, UINT *port);
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+/* Define the direct UDP packet receive processing. This is used with TCP/IP offload feature. */
+VOID _nx_udp_socket_driver_packet_receive(NX_UDP_SOCKET *socket_ptr, NX_PACKET *packet_ptr,
+ NXD_ADDRESS *local_ip, NXD_ADDRESS *remote_ip, UINT remote_port);
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
/* Define error checking shells for API services. These are only referenced by the
application. */
diff --git a/common/inc/nx_user_sample.h b/common/inc/nx_user_sample.h
index 978c2956..da4dd574 100644
--- a/common/inc/nx_user_sample.h
+++ b/common/inc/nx_user_sample.h
@@ -26,7 +26,7 @@
/* PORT SPECIFIC C INFORMATION RELEASE */
/* */
/* nx_user.h PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* */
/* AUTHOR */
/* */
@@ -47,6 +47,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
@@ -752,5 +755,11 @@
#define NX_MAX_STRING_LENGTH 1024
*/
+/* Defined, the TCP/IP offload feature is enabled.
+ NX_ENABLE_INTERFACE_CAPABILITY must be defined to enable this feature. */
+/*
+#define NX_ENABLE_TCPIP_OFFLOAD
+*/
+
#endif
diff --git a/common/src/nx_ip_address_set.c b/common/src/nx_ip_address_set.c
index 71a2081a..24a0e281 100644
--- a/common/src/nx_ip_address_set.c
+++ b/common/src/nx_ip_address_set.c
@@ -34,7 +34,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_ip_address_set PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -70,75 +70,13 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), */
+/* merged duplicated functions,*/
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_ip_address_set(NX_IP *ip_ptr, ULONG ip_address, ULONG network_mask)
{
-
-#ifndef NX_DISABLE_IPV4
-TX_INTERRUPT_SAVE_AREA
-
-VOID (*address_change_notify)(NX_IP *, VOID *);
-VOID *additional_info;
-ULONG previous_ip_address;
-ULONG previous_network_mask;
-
-
- /* If trace is enabled, insert this event into the trace buffer. */
- NX_TRACE_IN_LINE_INSERT(NX_TRACE_IP_ADDRESS_SET, ip_ptr, ip_address, network_mask, 0, NX_TRACE_IP_EVENTS, 0, 0);
-
- /* Get mutex protection. */
- tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
-
-
- /* Disable interrupts. */
- TX_DISABLE
-
- /* Save previous IP address and network mask. This service assumes the
- operations on the primary interface. */
- previous_ip_address = ip_ptr -> nx_ip_interface[0].nx_interface_ip_address;
- previous_network_mask = ip_ptr -> nx_ip_interface[0].nx_interface_ip_network_mask;
-
- /* Pickup the current notification callback and additional information pointers. */
- address_change_notify = ip_ptr -> nx_ip_address_change_notify;
- additional_info = ip_ptr -> nx_ip_address_change_notify_additional_info;
-
- /* Setup the IP address and the network mask. */
- ip_ptr -> nx_ip_interface[0].nx_interface_ip_address = ip_address;
- ip_ptr -> nx_ip_interface[0].nx_interface_ip_network_mask = network_mask;
- ip_ptr -> nx_ip_interface[0].nx_interface_ip_network = ip_address & network_mask;
-
- /* Ensure the RARP function is disabled. */
- ip_ptr -> nx_ip_rarp_periodic_update = NX_NULL;
- ip_ptr -> nx_ip_rarp_queue_process = NX_NULL;
-
- /* Restore interrupts. */
- TX_RESTORE
-
- /* Release mutex protection. */
- tx_mutex_put(&(ip_ptr -> nx_ip_protection));
-
- /* Determine if the application should be notified of the IP address and/or
- network mask change. */
- if ((address_change_notify) &&
- ((ip_address != previous_ip_address) || (network_mask != previous_network_mask)))
- {
-
- /* Yes, call the application's IP address change notify function. */
- (address_change_notify)(ip_ptr, additional_info);
- }
-
- /* Initialize the ARP defend timeout. */
- ip_ptr -> nx_ip_interface[0].nx_interface_arp_defend_timeout = 0;
-
- /* Return completion status. */
- return(NX_SUCCESS);
-#else /* NX_DISABLE_IPV4 */
- NX_PARAMETER_NOT_USED(ip_ptr);
- NX_PARAMETER_NOT_USED(ip_address);
- NX_PARAMETER_NOT_USED(network_mask);
-
- return(NX_NOT_SUPPORTED);
-#endif /* !NX_DISABLE_IPV4 */
+ return(_nx_ip_interface_address_set(ip_ptr, 0, ip_address, network_mask));
}
diff --git a/common/src/nx_ip_header_add.c b/common/src/nx_ip_header_add.c
index 46758a0e..a638aac8 100644
--- a/common/src/nx_ip_header_add.c
+++ b/common/src/nx_ip_header_add.c
@@ -39,7 +39,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_ip_header_add PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -52,6 +52,7 @@
/* */
/* ip_ptr Pointer to IP control block */
/* packet_ptr Pointer to packet to send */
+/* source_ip Source IP address */
/* destination_ip Destination IP address */
/* type_of_service Type of service for packet */
/* time_to_live Time to live value for packet */
@@ -79,9 +80,12 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
-UINT _nx_ip_header_add(NX_IP *ip_ptr, NX_PACKET *packet_ptr, ULONG destination_ip,
+UINT _nx_ip_header_add(NX_IP *ip_ptr, NX_PACKET *packet_ptr, ULONG source_ip, ULONG destination_ip,
ULONG type_of_service, ULONG time_to_live, ULONG protocol, ULONG fragment)
{
ULONG router_alert = 0;
@@ -154,7 +158,7 @@ ULONG val;
ip_header_ptr -> nx_ip_header_word_2 = ((time_to_live << NX_IP_TIME_TO_LIVE_SHIFT) | protocol);
/* Place the source IP address in the IP header. */
- ip_header_ptr -> nx_ip_header_source_ip = packet_ptr -> nx_packet_ip_interface -> nx_interface_ip_address;
+ ip_header_ptr -> nx_ip_header_source_ip = source_ip;
/* Place the destination IP address in the IP header. */
ip_header_ptr -> nx_ip_header_destination_ip = destination_ip;
diff --git a/common/src/nx_ip_interface_attach.c b/common/src/nx_ip_interface_attach.c
index 23d20e76..5c62d951 100644
--- a/common/src/nx_ip_interface_attach.c
+++ b/common/src/nx_ip_interface_attach.c
@@ -38,7 +38,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_ip_interface_attach PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -88,6 +88,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_ip_interface_attach(NX_IP *ip_ptr, CHAR *interface_name, ULONG ip_address, ULONG network_mask, VOID (*ip_link_driver)(struct NX_IP_DRIVER_STRUCT *))
@@ -159,12 +162,25 @@ ULONG address[4];
if (ip_ptr -> nx_ip_initialize_done == NX_TRUE)
{
+#ifdef NX_ENABLE_INTERFACE_CAPABILITY
+ /* Clear capability flag. */
+ ip_ptr -> nx_ip_interface[i].nx_interface_capability_flag = 0;
+#endif /* NX_ENABLE_INTERFACE_CAPABILITY */
+
/* First attach the interface to the device. */
driver_request.nx_ip_driver_ptr = ip_ptr;
driver_request.nx_ip_driver_command = NX_LINK_INTERFACE_ATTACH;
driver_request.nx_ip_driver_interface = &(ip_ptr -> nx_ip_interface[i]);
(ip_ptr -> nx_ip_interface[i].nx_interface_link_driver_entry)(&driver_request);
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ if (ip_ptr -> nx_ip_interface[i].nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD)
+ {
+
+ /* Set checksum capability for TCP/IP offload interface. */
+ ip_ptr -> nx_ip_interface[i].nx_interface_capability_flag |= NX_INTERFACE_CAPABILITY_CHECKSUM_ALL;
+ }
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
/* Call the link driver to initialize the hardware. Among other
responsibilities, the driver is required to provide the
diff --git a/common/src/nx_ip_packet_receive.c b/common/src/nx_ip_packet_receive.c
index b9044e56..270ca7a5 100644
--- a/common/src/nx_ip_packet_receive.c
+++ b/common/src/nx_ip_packet_receive.c
@@ -35,7 +35,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_ip_packet_receive PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -74,6 +74,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* added new ip filter, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
VOID _nx_ip_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
@@ -124,6 +127,20 @@ UCHAR version_byte;
return;
}
}
+
+ /* Check if the IP packet filter extended is set. */
+ if (ip_ptr -> nx_ip_packet_filter_extended)
+ {
+
+ /* Yes, call the IP packet filter extended routine. */
+ if (ip_ptr -> nx_ip_packet_filter_extended(ip_ptr, packet_ptr, NX_IP_PACKET_IN) != NX_SUCCESS)
+ {
+
+ /* Drop the packet. */
+ _nx_packet_release(packet_ptr);
+ return;
+ }
+ }
#endif /* NX_ENABLE_IP_PACKET_FILTER */
#ifndef NX_DISABLE_IPV4
diff --git a/common/src/nx_ip_packet_send.c b/common/src/nx_ip_packet_send.c
index 7847dbcd..7b258baf 100644
--- a/common/src/nx_ip_packet_send.c
+++ b/common/src/nx_ip_packet_send.c
@@ -39,7 +39,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_ip_packet_send PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -83,6 +83,10 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* added new ip filter, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
VOID _nx_ip_packet_send(NX_IP *ip_ptr, NX_PACKET *packet_ptr,
@@ -133,6 +137,24 @@ ULONG val;
return;
}
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ if (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_capability_flag &
+ NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD)
+ {
+#ifndef NX_DISABLE_IP_INFO
+
+ /* Increment the IP invalid packet error. */
+ ip_ptr -> nx_ip_invalid_transmit_packets++;
+#endif
+
+ /* Ignore sending all packets for TCP/IP offload. Release the packet. */
+ _nx_packet_transmit_release(packet_ptr);
+
+ /* Return... nothing more can be done! */
+ return;
+ }
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
#ifdef NX_IPSEC_ENABLE
/* Check if this packet is continued after HW crypto engine. */
if (packet_ptr -> nx_packet_ipsec_sa_ptr &&
@@ -191,7 +213,8 @@ ULONG val;
{
/* Add the IP Header to the packet. */
- _nx_ip_header_add(ip_ptr, packet_ptr, destination_ip, type_of_service, time_to_live, protocol, fragment);
+ _nx_ip_header_add(ip_ptr, packet_ptr, packet_ptr -> nx_packet_ip_interface -> nx_interface_ip_address,
+ destination_ip, type_of_service, time_to_live, protocol, fragment);
#ifdef NX_ENABLE_IP_PACKET_FILTER
/* Check if the IP packet filter is set. */
@@ -208,6 +231,20 @@ ULONG val;
return;
}
}
+
+ /* Check if the IP packet filter extended is set. */
+ if (ip_ptr -> nx_ip_packet_filter_extended)
+ {
+
+ /* Yes, call the IP packet filter extended routine. */
+ if (ip_ptr -> nx_ip_packet_filter_extended(ip_ptr, packet_ptr, NX_IP_PACKET_OUT) != NX_SUCCESS)
+ {
+
+ /* Drop the packet. */
+ _nx_packet_transmit_release(packet_ptr);
+ return;
+ }
+ }
#endif /* NX_ENABLE_IP_PACKET_FILTER */
}
diff --git a/common/src/nx_ip_thread_entry.c b/common/src/nx_ip_thread_entry.c
index 69409683..9fab67d3 100644
--- a/common/src/nx_ip_thread_entry.c
+++ b/common/src/nx_ip_thread_entry.c
@@ -43,7 +43,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_ip_thread_entry PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -114,6 +114,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
VOID _nx_ip_thread_entry(ULONG ip_ptr_value)
@@ -164,6 +167,15 @@ NXD_IPV6_ADDRESS *interface_ipv6_address;
driver_request.nx_ip_driver_interface = &(ip_ptr -> nx_ip_interface[i]);
(ip_ptr -> nx_ip_interface[i].nx_interface_link_driver_entry)(&driver_request);
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ if (ip_ptr -> nx_ip_interface[i].nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD)
+ {
+
+ /* Set checksum capability for TCP/IP offload interface. */
+ ip_ptr -> nx_ip_interface[i].nx_interface_capability_flag |= NX_INTERFACE_CAPABILITY_CHECKSUM_ALL;
+ }
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
/* Call the link driver to initialize the hardware. Among other
responsibilities, the driver is required to provide the
Maximum Transfer Unit (MTU) for the physical layer. The MTU
diff --git a/common/src/nx_ipv6_header_add.c b/common/src/nx_ipv6_header_add.c
index 3dcc2693..602ec001 100644
--- a/common/src/nx_ipv6_header_add.c
+++ b/common/src/nx_ipv6_header_add.c
@@ -43,7 +43,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_ipv6_header_add PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -84,6 +84,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_ipv6_header_add(NX_IP *ip_ptr, NX_PACKET **packet_pptr,
@@ -251,22 +254,6 @@ USHORT short_val;
NX_IPV6_ADDRESS_CHANGE_ENDIAN(ip_header_ptr -> nx_ip_header_destination_ip);
NX_IPV6_ADDRESS_CHANGE_ENDIAN(ip_header_ptr -> nx_ip_header_source_ip);
-#ifdef NX_ENABLE_IP_PACKET_FILTER
- /* Check if the IP packet filter is set. */
- if (ip_ptr -> nx_ip_packet_filter)
- {
-
- /* Yes, call the IP packet filter routine. */
- if (ip_ptr -> nx_ip_packet_filter((VOID *)(packet_ptr -> nx_packet_prepend_ptr),
- NX_IP_PACKET_OUT) != NX_SUCCESS)
- {
-
- /* Drop the packet. */
- _nx_packet_transmit_release(packet_ptr);
- return(NX_INVALID_PACKET);
- }
- }
-#endif /* NX_ENABLE_IP_PACKET_FILTER */
#ifdef NX_IPSEC_ENABLE
}
else
diff --git a/common/src/nx_ipv6_packet_send.c b/common/src/nx_ipv6_packet_send.c
index 8d03c1a6..2c17a67b 100644
--- a/common/src/nx_ipv6_packet_send.c
+++ b/common/src/nx_ipv6_packet_send.c
@@ -39,7 +39,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_ipv6_packet_send PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -93,6 +93,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
VOID _nx_ipv6_packet_send(NX_IP *ip_ptr, NX_PACKET *packet_ptr,
@@ -120,6 +123,23 @@ NX_IPV6_DESTINATION_ENTRY *dest_entry_ptr;
/* Interface can not be NULL. */
NX_ASSERT(if_ptr != NX_NULL);
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ if (if_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD)
+ {
+#ifndef NX_DISABLE_IP_INFO
+
+ /* Increment the IP invalid packet error. */
+ ip_ptr -> nx_ip_invalid_transmit_packets++;
+#endif
+
+ /* Ignore sending all packets for TCP/IP offload. Release the packet. */
+ _nx_packet_transmit_release(packet_ptr);
+
+ /* Return... nothing more can be done! */
+ return;
+ }
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
/* Add IPv6 header. */
if (_nx_ipv6_header_add(ip_ptr, &packet_ptr, protocol, payload_size,
hop_limit, src_address, dest_address, &fragment) != NX_SUCCESS)
@@ -129,6 +149,37 @@ NX_IPV6_DESTINATION_ENTRY *dest_entry_ptr;
return;
}
+#ifdef NX_ENABLE_IP_PACKET_FILTER
+ /* Check if the IP packet filter is set. */
+ if (ip_ptr -> nx_ip_packet_filter)
+ {
+
+ /* Yes, call the IP packet filter routine. */
+ if (ip_ptr -> nx_ip_packet_filter((VOID *)(packet_ptr -> nx_packet_prepend_ptr),
+ NX_IP_PACKET_OUT) != NX_SUCCESS)
+ {
+
+ /* Drop the packet. */
+ _nx_packet_transmit_release(packet_ptr);
+ return;
+ }
+ }
+
+ /* Check if the IP packet filter extended is set. */
+ if (ip_ptr -> nx_ip_packet_filter_extended)
+ {
+
+ /* Yes, call the IP packet filter extended routine. */
+ if (ip_ptr -> nx_ip_packet_filter_extended(ip_ptr, packet_ptr, NX_IP_PACKET_OUT) != NX_SUCCESS)
+ {
+
+ /* Drop the packet. */
+ _nx_packet_transmit_release(packet_ptr);
+ return;
+ }
+ }
+#endif /* NX_ENABLE_IP_PACKET_FILTER */
+
next_hop_mtu = if_ptr -> nx_interface_ip_mtu_size;
packet_ptr -> nx_packet_ip_header = packet_ptr -> nx_packet_prepend_ptr;
diff --git a/common/src/nx_tcp_server_socket_driver_listen.c b/common/src/nx_tcp_server_socket_driver_listen.c
new file mode 100644
index 00000000..f0c68cd7
--- /dev/null
+++ b/common/src/nx_tcp_server_socket_driver_listen.c
@@ -0,0 +1,119 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX Component */
+/** */
+/** Transmission Control Protocol (TCP) */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define NX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "nx_api.h"
+#include "nx_tcp.h"
+
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_tcp_server_socket_driver_listen PORTABLE C */
+/* 6.1.8 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function registers a listen request to all TCP/IP offload */
+/* interfaces. */
+/* */
+/* INPUT */
+/* */
+/* ip_ptr Pointer to IP instance */
+/* port TCP port number */
+/* socket_ptr Server socket pointer */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_tcp_server_socket_listen Register a listen request */
+/* _nx_tcp_server_socket_relisten Register a listen request */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */
+/* */
+/**************************************************************************/
+UINT _nx_tcp_server_socket_driver_listen(NX_IP *ip_ptr, UINT port, NX_TCP_SOCKET *socket_ptr)
+{
+UINT status;
+UINT i;
+NX_INTERFACE *interface_ptr;
+
+ /* Loop all interfaces to listen to ones support TCP/IP offload. */
+ for (i = 0; i < NX_MAX_IP_INTERFACES; i++)
+ {
+
+ /* Use a local variable for convenience. */
+ interface_ptr = &(ip_ptr -> nx_ip_interface[i]);
+
+ /* Check for valid interfaces. */
+ if ((interface_ptr -> nx_interface_valid == NX_FALSE) ||
+ (interface_ptr -> nx_interface_link_up == NX_FALSE))
+ {
+
+ /* Skip interface not valid. */
+ continue;
+ }
+
+ /* Check for TCP/IP offload feature. */
+ if (((interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) == 0) ||
+ (interface_ptr -> nx_interface_tcpip_offload_handler == NX_NULL))
+ {
+
+ /* Skip interface not support TCP/IP offload. */
+ continue;
+ }
+
+ /* Let TCP/IP offload interface listen to port. */
+ status = interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr,
+ NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_LISTEN,
+ NX_NULL, NX_NULL, NX_NULL,
+ port, NX_NULL, NX_NO_WAIT);
+ if (status)
+ {
+
+ /* Return an already bound error code. */
+ return(NX_TCPIP_OFFLOAD_ERROR);
+ }
+ }
+
+ return(NX_SUCCESS);
+}
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */ \ No newline at end of file
diff --git a/common/src/nx_tcp_server_socket_listen.c b/common/src/nx_tcp_server_socket_listen.c
index 3a5162c2..52b6d6f3 100644
--- a/common/src/nx_tcp_server_socket_listen.c
+++ b/common/src/nx_tcp_server_socket_listen.c
@@ -34,7 +34,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_tcp_server_socket_listen PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -74,6 +74,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_tcp_server_socket_listen(NX_IP *ip_ptr, UINT port, NX_TCP_SOCKET *socket_ptr, UINT listen_queue_size,
@@ -232,6 +235,22 @@ UINT bound;
listen_ptr -> nx_tcp_listen_next = listen_ptr;
}
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ /* Listen to TCP/IP offload interfaces. */
+ if (_nx_tcp_server_socket_driver_listen(ip_ptr, port, socket_ptr))
+ {
+
+ /* At least one of the interface fails to listen to port. */
+ _nx_tcp_server_socket_unlisten(ip_ptr, port);
+
+ /* Listen request failure, release the protection. */
+ tx_mutex_put(&(ip_ptr -> nx_ip_protection));
+
+ /* Return an already bound error code. */
+ return(NX_TCPIP_OFFLOAD_ERROR);
+ }
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
/* Successful listen request, release the protection. */
tx_mutex_put(&(ip_ptr -> nx_ip_protection));
diff --git a/common/src/nx_tcp_server_socket_relisten.c b/common/src/nx_tcp_server_socket_relisten.c
index 5bb5896c..b868eb6d 100644
--- a/common/src/nx_tcp_server_socket_relisten.c
+++ b/common/src/nx_tcp_server_socket_relisten.c
@@ -38,7 +38,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_tcp_server_socket_relisten PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -80,6 +80,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_tcp_server_socket_relisten(NX_IP *ip_ptr, UINT port, NX_TCP_SOCKET *socket_ptr)
@@ -150,6 +153,19 @@ VOID (*listen_callback)(NX_TCP_SOCKET *socket_ptr, UINT
/* Yes, a listen request was found for this port, with an empty
socket designation. */
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ /* Listen to TCP/IP offload interfaces. */
+ if (_nx_tcp_server_socket_driver_listen(ip_ptr, port, socket_ptr))
+ {
+
+ /* Listen request failure, release the protection. */
+ tx_mutex_put(&(ip_ptr -> nx_ip_protection));
+
+ /* Return an already bound error code. */
+ return(NX_TCPIP_OFFLOAD_ERROR);
+ }
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
/* Determine if there are any connection requests queued up. */
if (!listen_ptr -> nx_tcp_listen_queue_current)
{
diff --git a/common/src/nx_tcp_server_socket_unlisten.c b/common/src/nx_tcp_server_socket_unlisten.c
index c56191e6..7b5053d2 100644
--- a/common/src/nx_tcp_server_socket_unlisten.c
+++ b/common/src/nx_tcp_server_socket_unlisten.c
@@ -30,12 +30,96 @@
#include "nx_packet.h"
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_tcp_server_socket_driver_unlisten PORTABLE C */
+/* 6.1.8 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function handles the TCP server unlisten for TCP/IP offload */
+/* interface. */
+/* */
+/* INPUT */
+/* */
+/* ip_ptr Pointer to IP instance */
+/* socket_ptr Pointer to TCP socket */
+/* port TCP port number */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* tx_mutex_get Obtain protection */
+/* tx_mutex_put Release protection */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_tcp_server_socket_unlisten */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */
+/* */
+/**************************************************************************/
+static UINT _nx_tcp_server_socket_driver_unlisten(NX_IP *ip_ptr, NX_TCP_SOCKET *socket_ptr, UINT port)
+{
+UINT i;
+NX_INTERFACE *interface_ptr;
+
+ /* Loop all interfaces to unlisten to ones support TCP/IP offload. */
+ for (i = 0; i < NX_MAX_IP_INTERFACES; i++)
+ {
+
+ /* Use a local variable for convenience. */
+ interface_ptr = &(ip_ptr -> nx_ip_interface[i]);
+
+ /* Check for valid interfaces. */
+ if (interface_ptr -> nx_interface_valid == NX_FALSE)
+ {
+
+ /* Skip interface not valid. */
+ continue;
+ }
+
+ /* Check for TCP/IP offload feature. */
+ if (((interface_ptr -> nx_interface_capability_flag &
+ NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) == 0) ||
+ (interface_ptr -> nx_interface_tcpip_offload_handler == NX_NULL))
+ {
+
+ /* Skip interface not support TCP/IP offload. */
+ continue;
+ }
+
+ /* Let TCP/IP offload interface unlisten to port. */
+ interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr,
+ NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_UNLISTEN,
+ NX_NULL, NX_NULL, NX_NULL,
+ port, NX_NULL, NX_NO_WAIT);
+ }
+
+ return(NX_SUCCESS);
+}
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
+
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_tcp_server_socket_unlisten PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -71,6 +155,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_tcp_server_socket_unlisten(NX_IP *ip_ptr, UINT port)
@@ -192,6 +279,10 @@ struct NX_TCP_LISTEN_STRUCT *listen_ptr;
listen_ptr -> nx_tcp_listen_next = ip_ptr -> nx_ip_tcp_available_listen_requests;
ip_ptr -> nx_ip_tcp_available_listen_requests = listen_ptr;
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ _nx_tcp_server_socket_driver_unlisten(ip_ptr, socket_ptr, port);
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
/* Release the protection. */
tx_mutex_put(&(ip_ptr -> nx_ip_protection));
diff --git a/common/src/nx_tcp_socket_disconnect.c b/common/src/nx_tcp_socket_disconnect.c
index e04f4f09..bd49d3a3 100644
--- a/common/src/nx_tcp_socket_disconnect.c
+++ b/common/src/nx_tcp_socket_disconnect.c
@@ -36,7 +36,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_tcp_socket_disconnect PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -80,6 +80,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_tcp_socket_disconnect(NX_TCP_SOCKET *socket_ptr, ULONG wait_option)
@@ -88,6 +91,9 @@ UINT _nx_tcp_socket_disconnect(NX_TCP_SOCKET *socket_ptr, ULONG wait_option)
#ifndef NX_DISABLE_RESET_DISCONNECT
NX_TCP_HEADER tcp_header;
#endif
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+NX_INTERFACE *interface_ptr;
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
UINT status;
NX_IP *ip_ptr;
@@ -129,6 +135,25 @@ NX_IP *ip_ptr;
socket_ptr -> nx_tcp_socket_keepalive_retries = 0;
#endif
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ interface_ptr = socket_ptr -> nx_tcp_socket_connect_interface;
+ if (interface_ptr &&
+ (interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) &&
+ (interface_ptr -> nx_interface_tcpip_offload_handler))
+ {
+
+ /* Let TCP/IP offload interface close the connection. */
+ interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr,
+ NX_TCPIP_OFFLOAD_TCP_SOCKET_DISCONNECT,
+ NX_NULL, NX_NULL, NX_NULL, 0, NX_NULL,
+ wait_option);
+
+ /* Reset socket state. */
+ socket_ptr -> nx_tcp_socket_state = NX_TCP_CLOSED;
+ }
+ else
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
/* Determine if the connection wasn't fully completed. */
if ((socket_ptr -> nx_tcp_socket_state == NX_TCP_SYN_SENT) ||
(socket_ptr -> nx_tcp_socket_state == NX_TCP_SYN_RECEIVED))
diff --git a/common/src/nx_tcp_socket_driver_establish.c b/common/src/nx_tcp_socket_driver_establish.c
new file mode 100644
index 00000000..2be2a994
--- /dev/null
+++ b/common/src/nx_tcp_socket_driver_establish.c
@@ -0,0 +1,243 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX Component */
+/** */
+/** Transmission Control Protocol (TCP) */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define NX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "nx_api.h"
+#include "nx_tcp.h"
+#include "nx_packet.h"
+#include "tx_thread.h"
+#include "nx_ip.h"
+#ifdef FEATURE_NX_IPV6
+#include "nx_ipv6.h"
+#endif /* FEATURE_NX_IPV6 */
+
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_tcp_socket_driver_establish PORTABLE C */
+/* 6.1.8 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is invoked when a TCP connection is established. */
+/* */
+/* INPUT */
+/* */
+/* socket_ptr Pointer to owning socket */
+/* interface_ptr Pointer to IP interface */
+/* remote_port Pointer to remote UDP port */
+/* */
+/* OUTPUT */
+/* */
+/* Status */
+/* */
+/* CALLS */
+/* */
+/* tx_mutex_get Obtain protection mutex */
+/* tx_mutex_put Release protection mutex */
+/* _nx_ip_packet_deferred_receive Defer IP packet receive */
+/* */
+/* CALLED BY */
+/* */
+/* Driver */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */
+/* */
+/**************************************************************************/
+UINT _nx_tcp_socket_driver_establish(NX_TCP_SOCKET *socket_ptr, NX_INTERFACE *interface_ptr, UINT remote_port)
+{
+NX_IP *ip_ptr;
+NXD_ADDRESS ip_address;
+UINT status;
+UINT index;
+UINT port;
+struct NX_TCP_LISTEN_STRUCT *listen_ptr;
+
+ /* Setup the IP pointer. */
+ ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr;
+
+ /* Obtain the IP internal mutex before processing the IP event. */
+ tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
+
+ /* Check socket state first. */
+ if ((socket_ptr -> nx_tcp_socket_state != NX_TCP_SYN_SENT) &&
+ (socket_ptr -> nx_tcp_socket_state != NX_TCP_LISTEN_STATE)&&
+ (socket_ptr -> nx_tcp_socket_state != NX_TCP_SYN_RECEIVED))
+ {
+
+ /* Just ignore socket not in connecting state. */
+ /* Release the IP internal mutex. */
+ tx_mutex_put(&(ip_ptr -> nx_ip_protection));
+ return(NX_NOT_SUCCESSFUL);
+ }
+
+ if (socket_ptr -> nx_tcp_socket_client_type == NX_FALSE)
+ {
+ if (socket_ptr -> nx_tcp_socket_bound_next)
+ {
+
+ /* TCP socket is connecting on other interface. */
+ /* Release the IP internal mutex. */
+ tx_mutex_put(&(ip_ptr -> nx_ip_protection));
+ return(NX_NOT_SUCCESSFUL);
+ }
+
+ /* For TCP server socket, the connection is not established yet. */
+ port = socket_ptr -> nx_tcp_socket_port;
+ status = interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr,
+ NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_ACCEPT,
+ NX_NULL, NX_NULL, &ip_address, port,
+ &remote_port, NX_NO_WAIT);
+
+ if (status)
+ {
+
+ /* This should not happen as a connection is pendding. */
+ /* Release the IP internal mutex. */
+ tx_mutex_put(&(ip_ptr -> nx_ip_protection));
+ return(NX_TCPIP_OFFLOAD_ERROR);
+ }
+
+ /* Setup connection parameters. */
+ socket_ptr -> nx_tcp_socket_connect_interface = interface_ptr;
+
+ /* Save the server port and server IP address. */
+ socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version = ip_address.nxd_ip_version;
+#ifndef NX_DISABLE_IPV4
+ if (ip_address.nxd_ip_version == NX_IP_VERSION_V4)
+ {
+ socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v4 = ip_address.nxd_ip_address.v4;
+ socket_ptr -> nx_tcp_socket_mss =
+ (ULONG)((interface_ptr -> nx_interface_ip_mtu_size - sizeof(NX_IPV4_HEADER)) - sizeof(NX_TCP_HEADER));
+ }
+#endif /* !NX_DISABLE_IPV4 */
+
+#ifdef FEATURE_NX_IPV6
+ if (ip_address.nxd_ip_version == NX_IP_VERSION_V6)
+ {
+ COPY_IPV6_ADDRESS(ip_address.nxd_ip_address.v6,
+ socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v6);
+ socket_ptr -> nx_tcp_socket_mss =
+ (ULONG)((interface_ptr -> nx_interface_ip_mtu_size - sizeof(NX_IPV6_HEADER)) - sizeof(NX_TCP_HEADER));
+ }
+#endif /* FEATURE_NX_IPV6 */
+
+ socket_ptr -> nx_tcp_socket_connect_port = remote_port;
+
+ /* Find listen callback function. */
+ listen_ptr = ip_ptr -> nx_ip_tcp_active_listen_requests;
+ if (listen_ptr)
+ {
+ do
+ {
+ if (listen_ptr -> nx_tcp_listen_port == port)
+ {
+ if (listen_ptr -> nx_tcp_listen_callback)
+ {
+
+ /* Clear the server socket pointer in the listen request. If the
+ application wishes to honor more server connections on this port,
+ the application must call relisten with a new server socket
+ pointer. */
+ listen_ptr->nx_tcp_listen_socket_ptr = NX_NULL;
+
+ /* Call the user's listen callback function. */
+ (listen_ptr ->nx_tcp_listen_callback)(socket_ptr, listen_ptr -> nx_tcp_listen_port);
+ break;
+ }
+ }
+
+ /* Move to the next listen request. */
+ listen_ptr = listen_ptr -> nx_tcp_listen_next;
+ } while (listen_ptr != ip_ptr -> nx_ip_tcp_active_listen_requests);
+ }
+
+ /* Calculate the hash index in the TCP port array of the associated IP instance. */
+ index = (UINT)((port + (port >> 8)) & NX_TCP_PORT_TABLE_MASK);
+
+ /* Determine if the list is NULL. */
+ if (ip_ptr -> nx_ip_tcp_port_table[index])
+ {
+
+ /* There are already sockets on this list... just add this one
+ to the end. */
+ socket_ptr -> nx_tcp_socket_bound_next =
+ ip_ptr -> nx_ip_tcp_port_table[index];
+ socket_ptr -> nx_tcp_socket_bound_previous =
+ (ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous;
+ ((ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous) -> nx_tcp_socket_bound_next =
+ socket_ptr;
+ (ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous = socket_ptr;
+ }
+ else
+ {
+
+ /* Nothing is on the TCP port list. Add this TCP socket to an
+ empty list. */
+ socket_ptr -> nx_tcp_socket_bound_next = socket_ptr;
+ socket_ptr -> nx_tcp_socket_bound_previous = socket_ptr;
+ ip_ptr -> nx_ip_tcp_port_table[index] = socket_ptr;
+ }
+ }
+
+ /* Update socket state. */
+ socket_ptr -> nx_tcp_socket_state = NX_TCP_ESTABLISHED;
+
+#ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
+
+ /* Is a connection completion callback registered with the TCP socket? */
+ if (socket_ptr -> nx_tcp_establish_notify)
+ {
+
+ /* Call the application's establish callback function. */
+ (socket_ptr -> nx_tcp_establish_notify)(socket_ptr);
+ }
+#endif
+
+ /* Determine if we need to wake a thread suspended on the connection. */
+ if (socket_ptr -> nx_tcp_socket_connect_suspended_thread)
+ {
+
+ /* Resume the suspended thread. */
+ _nx_tcp_socket_thread_resume(&(socket_ptr -> nx_tcp_socket_connect_suspended_thread), NX_SUCCESS);
+ }
+
+ /* Release the IP internal mutex. */
+ tx_mutex_put(&(ip_ptr -> nx_ip_protection));
+
+ return(NX_SUCCESS);
+}
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
diff --git a/common/src/nx_tcp_socket_driver_packet_receive.c b/common/src/nx_tcp_socket_driver_packet_receive.c
new file mode 100644
index 00000000..5c800215
--- /dev/null
+++ b/common/src/nx_tcp_socket_driver_packet_receive.c
@@ -0,0 +1,181 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX Component */
+/** */
+/** Transmission Control Protocol (TCP) */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define NX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "nx_api.h"
+#include "nx_tcp.h"
+#include "nx_packet.h"
+#include "tx_thread.h"
+#include "nx_ip.h"
+#ifdef FEATURE_NX_IPV6
+#include "nx_ipv6.h"
+#endif /* FEATURE_NX_IPV6 */
+
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_tcp_socket_driver_packet_receive PORTABLE C */
+/* 6.1.8 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function receives a TCP packet from the TCP/IP driver and add */
+/* fake TCP/IP header. Then pass the packet to IP deferred receive */
+/* routine. */
+/* */
+/* INPUT */
+/* */
+/* socket_ptr Pointer to owning socket */
+/* packet_ptr Pointer to packet to process */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* tx_mutex_get Obtain protection mutex */
+/* tx_mutex_put Release protection mutex */
+/* _nx_ip_packet_deferred_receive Defer IP packet receive */
+/* */
+/* CALLED BY */
+/* */
+/* Driver */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */
+/* */
+/**************************************************************************/
+VOID _nx_tcp_socket_driver_packet_receive(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr)
+{
+NX_IP *ip_ptr;
+NX_TCP_HEADER *header_ptr;
+
+ /* Setup the IP pointer. */
+ ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr;
+
+ /* Obtain the IP internal mutex before processing the IP event. */
+ tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
+
+ if (packet_ptr == NX_NULL)
+ {
+
+ /* Connection closed. */
+ if (socket_ptr -> nx_tcp_socket_state == NX_TCP_ESTABLISHED)
+ {
+ socket_ptr -> nx_tcp_socket_state = NX_TCP_CLOSE_WAIT;
+
+ /* Loop to release all threads suspended while trying to receive on the socket. */
+ while (socket_ptr -> nx_tcp_socket_receive_suspension_list)
+ {
+
+ /* Release the head of the receive suspension list. */
+ _nx_tcp_receive_cleanup(socket_ptr -> nx_tcp_socket_receive_suspension_list NX_CLEANUP_ARGUMENT);
+ }
+
+ /* If given, call the application's disconnect callback function
+ for disconnect. */
+ if (socket_ptr -> nx_tcp_disconnect_callback)
+ {
+
+ /* Call the application's disconnect handling function. It is
+ responsible for calling the socket disconnect function. */
+ (socket_ptr -> nx_tcp_disconnect_callback)(socket_ptr);
+ }
+ }
+
+ /* Release the IP internal mutex. */
+ tx_mutex_put(&(ip_ptr -> nx_ip_protection));
+ return;
+ }
+
+ /* Fake TCP and IP header. */
+ /* Prepend the TCP header to the packet. First, make room for the TCP header. */
+ packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_TCP_HEADER);
+
+ /* Add the length of the TCP header. */
+ packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + (ULONG)sizeof(NX_TCP_HEADER);
+
+ /* Pickup the pointer to the head of the TCP packet. */
+ /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
+ header_ptr = (NX_TCP_HEADER *)packet_ptr -> nx_packet_prepend_ptr;
+
+ /* Build the output request in the TCP header. */
+ header_ptr -> nx_tcp_header_word_0 = (((ULONG)(socket_ptr -> nx_tcp_socket_connect_port)) << NX_SHIFT_BY_16) |
+ (ULONG)socket_ptr -> nx_tcp_socket_port;
+ NX_CHANGE_ULONG_ENDIAN(header_ptr -> nx_tcp_header_word_0);
+ header_ptr -> nx_tcp_acknowledgment_number = 0;
+ header_ptr -> nx_tcp_sequence_number = 0;
+ header_ptr -> nx_tcp_header_word_3 = NX_TCP_HEADER_SIZE | NX_TCP_ACK_BIT | NX_TCP_PSH_BIT;
+ NX_CHANGE_ULONG_ENDIAN(header_ptr -> nx_tcp_header_word_3);
+ header_ptr -> nx_tcp_header_word_4 = 0;
+
+#ifndef NX_DISABLE_IPV4
+ if (socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V4)
+ {
+ _nx_ip_header_add(ip_ptr, packet_ptr, socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v4,
+ packet_ptr -> nx_packet_ip_interface -> nx_interface_ip_address,
+ socket_ptr -> nx_tcp_socket_type_of_service,
+ socket_ptr -> nx_tcp_socket_time_to_live,
+ NX_IP_TCP,
+ socket_ptr -> nx_tcp_socket_fragment_enable);
+ }
+#endif /* !NX_DISABLE_IPV4 */
+
+#ifdef FEATURE_NX_IPV6
+ if (socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
+ {
+ if (_nx_ipv6_header_add(ip_ptr, &packet_ptr,
+ NX_PROTOCOL_TCP,
+ packet_ptr -> nx_packet_length,
+ ip_ptr -> nx_ipv6_hop_limit,
+ socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v6,
+ socket_ptr -> nx_tcp_socket_ipv6_addr -> nxd_ipv6_address,
+ NX_NULL))
+ {
+
+ /* Release the IP internal mutex. */
+ tx_mutex_put(&(ip_ptr -> nx_ip_protection));
+ return;
+ }
+ }
+#endif /* FEATURE_NX_IPV6 */
+
+ /* Release the IP internal mutex. */
+ tx_mutex_put(&(ip_ptr -> nx_ip_protection));
+
+ _nx_ip_packet_deferred_receive(ip_ptr, packet_ptr);
+}
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
diff --git a/common/src/nx_tcp_socket_packet_process.c b/common/src/nx_tcp_socket_packet_process.c
index 085d8b47..878ff945 100644
--- a/common/src/nx_tcp_socket_packet_process.c
+++ b/common/src/nx_tcp_socket_packet_process.c
@@ -35,7 +35,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_tcp_socket_packet_process PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -83,6 +83,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
VOID _nx_tcp_socket_packet_process(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr)
@@ -98,6 +101,12 @@ ULONG rx_sequence;
ULONG rx_window;
UINT outside_of_window;
ULONG mss = 0;
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ULONG tcpip_offload;
+
+ tcpip_offload = socket_ptr -> nx_tcp_socket_connect_interface -> nx_interface_capability_flag &
+ NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD;
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
/* Add debug information. */
NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
@@ -112,7 +121,11 @@ ULONG mss = 0;
header_length = (tcp_header_copy.nx_tcp_header_word_3 >> NX_TCP_HEADER_SHIFT) * (ULONG)sizeof(ULONG);
/* Process the segment if socket state is equal or greater than NX_TCP_SYN_RECEIVED. According to RFC 793, Section 3.9, Page 69. */
- if (socket_ptr -> nx_tcp_socket_state >= NX_TCP_SYN_RECEIVED)
+ if ((socket_ptr -> nx_tcp_socket_state >= NX_TCP_SYN_RECEIVED)
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ && (!tcpip_offload)
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+ )
{
/* Step1: Check sequence number. According to RFC 793, Section 3.9, Page 69. */
@@ -366,12 +379,18 @@ ULONG mss = 0;
/* Check for data in the current packet. */
packet_queued = _nx_tcp_socket_state_data_check(socket_ptr, packet_ptr);
- /* Call the ESTABLISHED state handling function to process any state
- changes caused by this new packet. */
- _nx_tcp_socket_state_established(socket_ptr);
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ if (!tcpip_offload)
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+ {
- /* Determine if any transmit suspension can be lifted. */
- _nx_tcp_socket_state_transmit_check(socket_ptr);
+ /* Call the ESTABLISHED state handling function to process any state
+ changes caused by this new packet. */
+ _nx_tcp_socket_state_established(socket_ptr);
+
+ /* Determine if any transmit suspension can be lifted. */
+ _nx_tcp_socket_state_transmit_check(socket_ptr);
+ }
/* State processing is complete. */
break;
diff --git a/common/src/nx_tcp_socket_send_internal.c b/common/src/nx_tcp_socket_send_internal.c
index 4d176c6f..2d466857 100644
--- a/common/src/nx_tcp_socket_send_internal.c
+++ b/common/src/nx_tcp_socket_send_internal.c
@@ -38,12 +38,176 @@
#endif /* NX_IPSEC_ENABLE */
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_tcp_socket_driver_send PORTABLE C */
+/* 6.1.8 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sends a TCP packet through TCP/IP offload interface. */
+/* */
+/* INPUT */
+/* */
+/* socket_ptr Pointer to socket */
+/* packet_ptr Pointer to packet to send */
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_ip_packet_send Packet send function */
+/* _nx_ipv6_packet_send Packet send function */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_tcp_socket_send_internal */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */
+/* */
+/**************************************************************************/
+static UINT _nx_tcp_socket_driver_send(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr, ULONG wait_option)
+{
+UINT status;
+NX_IP *ip_ptr;
+NX_INTERFACE *interface_ptr = socket_ptr -> nx_tcp_socket_connect_interface;
+#ifdef NX_ENABLE_IP_PACKET_FILTER
+UCHAR *original_ptr = packet_ptr -> nx_packet_prepend_ptr;
+ULONG original_length = packet_ptr -> nx_packet_length;
+NX_TCP_HEADER *header_ptr;
+#endif /* NX_ENABLE_IP_PACKET_FILTER */
+
+ /* Setup the pointer to the associated IP instance. */
+ ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr;
+
+#ifdef NX_ENABLE_IP_PACKET_FILTER
+ /* Check if the IP packet filter is set. */
+ if (ip_ptr -> nx_ip_packet_filter || ip_ptr -> nx_ip_packet_filter_extended)
+ {
+
+ /* Yes, add the TCP and IP Header to trigger filtering. */
+ /* Prepend the TCP header to the packet. First, make room for the TCP header. */
+ packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_TCP_HEADER);
+
+ /* Add the length of the TCP header. */
+ packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + (ULONG)sizeof(NX_TCP_HEADER);
+
+ /* Pickup the pointer to the head of the TCP packet. */
+ /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
+ header_ptr = (NX_TCP_HEADER *)packet_ptr -> nx_packet_prepend_ptr;
+
+ /* Build the output request in the TCP header. */
+ header_ptr -> nx_tcp_header_word_0 = (((ULONG)(socket_ptr -> nx_tcp_socket_port)) << NX_SHIFT_BY_16) |
+ (ULONG)socket_ptr -> nx_tcp_socket_connect_port;
+ header_ptr -> nx_tcp_acknowledgment_number = 0;
+ header_ptr -> nx_tcp_sequence_number = 0;
+ header_ptr -> nx_tcp_header_word_3 = NX_TCP_HEADER_SIZE | NX_TCP_ACK_BIT | NX_TCP_PSH_BIT;
+ header_ptr -> nx_tcp_header_word_4 = 0;
+
+ /* Endian swapping logic. If NX_LITTLE_ENDIAN is specified, these macros will
+ swap the endian of the TCP header. */
+ NX_CHANGE_ULONG_ENDIAN(header_ptr -> nx_tcp_header_word_0);
+ NX_CHANGE_ULONG_ENDIAN(header_ptr -> nx_tcp_header_word_3);
+
+#ifndef NX_DISABLE_IPV4
+ if (socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V4)
+ {
+ _nx_ip_header_add(ip_ptr, packet_ptr,
+ socket_ptr -> nx_tcp_socket_connect_interface -> nx_interface_ip_address,
+ socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v4,
+ socket_ptr -> nx_tcp_socket_type_of_service,
+ socket_ptr -> nx_tcp_socket_time_to_live,
+ NX_IP_TCP,
+ socket_ptr -> nx_tcp_socket_fragment_enable);
+ }
+#endif /* !NX_DISABLE_IPV4 */
+
+#ifdef FEATURE_NX_IPV6
+ if (socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
+ {
+ if (_nx_ipv6_header_add(ip_ptr, &packet_ptr,
+ NX_PROTOCOL_TCP,
+ packet_ptr -> nx_packet_length,
+ ip_ptr -> nx_ipv6_hop_limit,
+ socket_ptr -> nx_tcp_socket_ipv6_addr -> nxd_ipv6_address,
+ socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v6,
+ NX_NULL))
+ {
+
+ /* Invalid interface address. Just return success. */
+ return(NX_SUCCESS);
+ }
+ }
+#endif /* FEATURE_NX_IPV6 */
+
+ if (ip_ptr -> nx_ip_packet_filter)
+ {
+ if (ip_ptr -> nx_ip_packet_filter((VOID *)(packet_ptr -> nx_packet_prepend_ptr),
+ NX_IP_PACKET_OUT) != NX_SUCCESS)
+ {
+
+ /* Packet consumed by IP filter. Just return success. */
+ _nx_packet_transmit_release(packet_ptr);
+ return(NX_SUCCESS);
+ }
+ }
+
+ /* Check if the IP packet filter extended is set. */
+ if (ip_ptr -> nx_ip_packet_filter_extended)
+ {
+
+ /* Yes, call the IP packet filter extended routine. */
+ if (ip_ptr -> nx_ip_packet_filter_extended(ip_ptr, packet_ptr, NX_IP_PACKET_OUT) != NX_SUCCESS)
+ {
+
+ /* Packet consumed by IP filter. Just return success. */
+ _nx_packet_transmit_release(packet_ptr);
+ return(NX_SUCCESS);
+ }
+ }
+
+ /* Reset UDP and IP header. */
+ packet_ptr -> nx_packet_prepend_ptr = original_ptr;
+ packet_ptr -> nx_packet_length = original_length;
+ }
+#endif /* NX_ENABLE_IP_PACKET_FILTER */
+
+ /* Let TCP/IP offload interface send the packet. */
+ status = interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr,
+ NX_TCPIP_OFFLOAD_TCP_SOCKET_SEND,
+ packet_ptr, NX_NULL, NX_NULL, 0, NX_NULL,
+ wait_option);
+
+ if (status)
+ {
+ return(NX_TCPIP_OFFLOAD_ERROR);
+ }
+ else
+ {
+ return(NX_SUCCESS);
+ }
+}
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_tcp_socket_send_internal PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -70,6 +234,7 @@
/* _nx_tcp_socket_thread_suspend Suspend calling thread */
/* tx_mutex_get Get protection mutex */
/* tx_mutex_put Put protection mutex */
+/* _nx_tcp_socket_driver_send TCP/IP offload send function */
/* */
/* CALLED BY */
/* */
@@ -88,6 +253,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_tcp_socket_send_internal(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr, ULONG wait_option)
@@ -116,6 +284,10 @@ UCHAR preempted = NX_FALSE;
UCHAR adjust_packet;
UINT old_threshold = 0;
ULONG window_size;
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+UINT status;
+NX_INTERFACE *interface_ptr;
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
#if defined(NX_DISABLE_TCP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) || defined(NX_IPSEC_ENABLE)
UINT compute_checksum = 1;
#endif /* defined(NX_DISABLE_TCP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) || defined(NX_IPSEC_ENABLE) */
@@ -183,7 +355,7 @@ UINT compute_checksum = 1;
/* Set the source address. */
source_ip = &socket_ptr -> nx_tcp_socket_connect_interface -> nx_interface_ip_address;
- /* Set the destinatino address. */
+ /* Set the destination address. */
dest_ip = &socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v4;
/* The outgoing interface should have been stored in the socket structure. */
@@ -210,7 +382,7 @@ UINT compute_checksum = 1;
/* Set the source address. */
source_ip = socket_ptr -> nx_tcp_socket_ipv6_addr -> nxd_ipv6_address;
- /* Set the destinatino address. */
+ /* Set the destination address. */
dest_ip = socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v6;
/* The outgoing address should have been stored in the socket structure. */
@@ -221,6 +393,24 @@ UINT compute_checksum = 1;
}
#endif /* FEATURE_NX_IPV6 */
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ interface_ptr = socket_ptr -> nx_tcp_socket_connect_interface;
+ if ((interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) &&
+ (interface_ptr -> nx_interface_tcpip_offload_handler))
+ {
+
+ /* This interface supports TCP/IP offload. */
+ tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
+
+ status = _nx_tcp_socket_driver_send(socket_ptr, packet_ptr, wait_option);
+
+ /* Release the IP protection. */
+ tx_mutex_put(&(ip_ptr -> nx_ip_protection));
+
+ return(status);
+ }
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
#ifdef NX_IPSEC_ENABLE
/* Increase the data offset when IPsec is enabled. */
data_offset += socket_ptr -> nx_tcp_socket_egress_sa_data_offset;
@@ -907,5 +1097,4 @@ UINT compute_checksum = 1;
}
}
}
-}
-
+} \ No newline at end of file
diff --git a/common/src/nx_tcp_socket_state_data_check.c b/common/src/nx_tcp_socket_state_data_check.c
index 1f6475d1..d23b6c21 100644
--- a/common/src/nx_tcp_socket_state_data_check.c
+++ b/common/src/nx_tcp_socket_state_data_check.c
@@ -276,7 +276,7 @@ ULONG work_length;
/* FUNCTION RELEASE */
/* */
/* _nx_tcp_socket_state_data_check PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -317,6 +317,9 @@ ULONG work_length;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_tcp_socket_state_data_check(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr)
@@ -339,6 +342,9 @@ ULONG trim_data_length;
TX_THREAD *thread_ptr;
ULONG acked_packets = 0;
UINT need_ack = NX_FALSE;
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ULONG tcpip_offload;
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
#ifdef NX_ENABLE_LOW_WATERMARK
UCHAR drop_packet = NX_FALSE;
#endif /* NX_ENABLE_LOW_WATERMARK */
@@ -349,6 +355,10 @@ NX_IP *ip_ptr;
ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr;
#endif
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ tcpip_offload = socket_ptr -> nx_tcp_socket_connect_interface -> nx_interface_capability_flag &
+ NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD;
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
/* Pickup the pointer to the head of the TCP packet. */
/*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
@@ -370,7 +380,11 @@ NX_IP *ip_ptr;
packet_end_sequence = tcp_header_ptr -> nx_tcp_sequence_number + packet_data_length;
/* Trim the data that out of the receive window, make sure all data are in receive window. */
- if (packet_data_length)
+ if (packet_data_length
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ && (!tcpip_offload)
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+ )
{
/* Step1. trim the data on the left side of the receive window. */
@@ -480,13 +494,17 @@ NX_IP *ip_ptr;
search_end_sequence = socket_ptr -> nx_tcp_socket_rx_sequence;
}
-#ifdef NX_ENABLE_LOW_WATERMARK
/* Does the number of queued packets exceed the maximum rx queue length, or the number of
* available packets in the default packet pool reaches low watermark? */
- if ((socket_ptr -> nx_tcp_socket_receive_queue_count >=
- socket_ptr -> nx_tcp_socket_receive_queue_maximum) ||
- (packet_ptr -> nx_packet_pool_owner -> nx_packet_pool_available <
- packet_ptr -> nx_packet_pool_owner -> nx_packet_pool_low_watermark))
+#ifdef NX_ENABLE_LOW_WATERMARK
+ if (((socket_ptr -> nx_tcp_socket_receive_queue_count >=
+ socket_ptr -> nx_tcp_socket_receive_queue_maximum) ||
+ (packet_ptr -> nx_packet_pool_owner -> nx_packet_pool_available <
+ packet_ptr -> nx_packet_pool_owner -> nx_packet_pool_low_watermark))
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ && (!tcpip_offload)
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+ )
{
/* Yes it is. The last packet in queue should be dropped. */
@@ -497,8 +515,12 @@ NX_IP *ip_ptr;
/* Determine if we have a simple case of TCP data coming in the correct order. This means
the socket's sequence number matches the incoming packet sequence number and the last packet's
data on the socket's receive queue (if any) matches the current sequence number. */
- if ((tcp_header_ptr -> nx_tcp_sequence_number == socket_ptr -> nx_tcp_socket_rx_sequence) &&
- (search_end_sequence == socket_ptr -> nx_tcp_socket_rx_sequence))
+ if (((tcp_header_ptr -> nx_tcp_sequence_number == socket_ptr -> nx_tcp_socket_rx_sequence) &&
+ (search_end_sequence == socket_ptr -> nx_tcp_socket_rx_sequence))
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ || tcpip_offload
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+ )
{
/* Yes, this is the simple case of adding receive packets in sequence. */
@@ -534,7 +556,12 @@ NX_IP *ip_ptr;
socket_ptr -> nx_tcp_socket_receive_queue_tail = packet_ptr;
/* Setup a new delayed ACK timeout. */
- socket_ptr -> nx_tcp_socket_delayed_ack_timeout = _nx_tcp_ack_timer_rate;
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ if (!tcpip_offload)
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+ {
+ socket_ptr -> nx_tcp_socket_delayed_ack_timeout = _nx_tcp_ack_timer_rate;
+ }
}
/* Increment the receive TCP packet count. */
@@ -1059,7 +1086,7 @@ NX_IP *ip_ptr;
/* At this point, we can use the packet TCP header pointers since the received
packet is already queued. */
- /* Any packets for receving? */
+ /* Any packets for receiving? */
while (acked_packets && socket_ptr -> nx_tcp_socket_receive_suspension_list)
{
@@ -1134,7 +1161,11 @@ NX_IP *ip_ptr;
/* If the incoming packet caused the sequence number to move forward,
indicating the new piece of data is in order, in sequence, and valid for receiving. */
- if (original_rx_sequence != socket_ptr -> nx_tcp_socket_rx_sequence)
+ if ((original_rx_sequence != socket_ptr -> nx_tcp_socket_rx_sequence)
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ || tcpip_offload
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+ )
{
/* Determine if there is a socket receive notification function specified. */
if (socket_ptr -> nx_tcp_receive_callback)
diff --git a/common/src/nx_udp_socket_bind.c b/common/src/nx_udp_socket_bind.c
index 6917a2a6..c1ad243c 100644
--- a/common/src/nx_udp_socket_bind.c
+++ b/common/src/nx_udp_socket_bind.c
@@ -30,12 +30,117 @@
#include "tx_thread.h"
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_udp_socket_driver_bind PORTABLE C */
+/* 6.1.8 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function binds to a UDP port through TCP/IP offload interface. */
+/* */
+/* INPUT */
+/* */
+/* socket_ptr Pointer to UDP socket */
+/* port 16-bit UDP port number */
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_udp_socket_unbind Unbind UDP port */
+/* tx_mutex_get Obtain protection mutex */
+/* tx_mutex_put Release protection mutex */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_udp_socket_bind */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */
+/* */
+/**************************************************************************/
+static UINT _nx_udp_socket_driver_bind(NX_UDP_SOCKET *socket_ptr, UINT port, ULONG wait_option)
+{
+UINT status = NX_SUCCESS;
+UINT i;
+NX_INTERFACE *interface_ptr;
+NX_IP *ip_ptr;
+
+
+ /* Setup the pointer to the associated IP instance. */
+ ip_ptr = socket_ptr -> nx_udp_socket_ip_ptr;
+
+ /* Obtain the IP mutex. */
+ tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
+
+ /* Loop all interfaces to bind to ones support TCP/IP offload. */
+ for (i = 0; i < NX_MAX_IP_INTERFACES; i++)
+ {
+
+ /* Use a local variable for convenience. */
+ interface_ptr = &(ip_ptr -> nx_ip_interface[i]);
+
+ /* Check for valid interfaces. */
+ if ((interface_ptr -> nx_interface_valid == NX_FALSE) ||
+ (interface_ptr -> nx_interface_link_up == NX_FALSE))
+ {
+
+ /* Skip interface not valid. */
+ continue;
+ }
+
+ /* Check for TCP/IP offload feature. */
+ if (((interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) == 0) ||
+ (interface_ptr -> nx_interface_tcpip_offload_handler == NX_NULL))
+ {
+
+ /* Skip interface not support TCP/IP offload. */
+ continue;
+ }
+
+ /* Let TCP/IP offload interface bind to port. */
+ status = interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr,
+ socket_ptr,
+ NX_TCPIP_OFFLOAD_UDP_SOCKET_BIND,
+ NX_NULL, NX_NULL, NX_NULL, port,
+ NX_NULL, wait_option);
+ if (status)
+ {
+
+ /* At least one of the interface fails to bind to port. */
+ _nx_udp_socket_unbind(socket_ptr);
+ status = NX_TCPIP_OFFLOAD_ERROR;
+ break;
+ }
+ }
+
+ /* Release the IP protection. */
+ tx_mutex_put(&(ip_ptr -> nx_ip_protection));
+
+ return(status);
+}
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
+
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_udp_socket_bind PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -75,6 +180,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_udp_socket_bind(NX_UDP_SOCKET *socket_ptr, UINT port, ULONG wait_option)
@@ -89,6 +197,7 @@ NX_IP *ip_ptr;
TX_THREAD *thread_ptr;
NX_UDP_SOCKET *search_ptr;
NX_UDP_SOCKET *end_ptr;
+UINT status = NX_SUCCESS;
/* Setup the pointer to the associated IP instance. */
@@ -222,9 +331,6 @@ NX_UDP_SOCKET *end_ptr;
/* Release the mutex protection. */
tx_mutex_put(&(ip_ptr -> nx_ip_protection));
-
- /* Return success to the caller. */
- return(NX_SUCCESS);
}
else if (wait_option)
{
@@ -296,7 +402,7 @@ NX_UDP_SOCKET *end_ptr;
_tx_thread_system_suspend(thread_ptr);
/* Return the completion status. */
- return(thread_ptr -> tx_thread_suspend_status);
+ status = thread_ptr -> tx_thread_suspend_status;
}
else
{
@@ -305,7 +411,19 @@ NX_UDP_SOCKET *end_ptr;
tx_mutex_put(&(ip_ptr -> nx_ip_protection));
/* Return the port unavailable error. */
- return(NX_PORT_UNAVAILABLE);
+ status = NX_PORT_UNAVAILABLE;
+ }
+
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ if (status == NX_SUCCESS)
+ {
+
+ /* Bind to TCP/IP offload interface. */
+ status = _nx_udp_socket_driver_bind(socket_ptr, port, wait_option);
}
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
+ /* Return success to the caller. */
+ return(status);
}
diff --git a/common/src/nx_udp_socket_driver_packet_receive.c b/common/src/nx_udp_socket_driver_packet_receive.c
new file mode 100644
index 00000000..cfc9897f
--- /dev/null
+++ b/common/src/nx_udp_socket_driver_packet_receive.c
@@ -0,0 +1,158 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX Component */
+/** */
+/** User Datagram Protocol (UDP) */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define NX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "nx_api.h"
+#include "tx_thread.h"
+#include "nx_udp.h"
+#include "nx_packet.h"
+#include "nx_ip.h"
+#ifdef FEATURE_NX_IPV6
+#include "nx_ipv6.h"
+#endif /* FEATURE_NX_IPV6 */
+
+
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_udp_socket_driver_packet_receive PORTABLE C */
+/* 6.1.8 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function receives a UDP packet from the TCP/IP driver and add */
+/* fake TCP/IP header. Then pass the packet to IP deferred receive */
+/* routine. */
+/* */
+/* INPUT */
+/* */
+/* socket_ptr Pointer to owning socket */
+/* packet_ptr Pointer to packet to process */
+/* local_ip Pointer to local IP address */
+/* remote_ip Pointer to remote IP address */
+/* remote_port Pointer to remote UDP port */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* tx_mutex_get Obtain protection mutex */
+/* tx_mutex_put Release protection mutex */
+/* _nx_ip_packet_deferred_receive Defer IP packet receive */
+/* */
+/* CALLED BY */
+/* */
+/* Driver */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */
+/* */
+/**************************************************************************/
+VOID _nx_udp_socket_driver_packet_receive(NX_UDP_SOCKET *socket_ptr, NX_PACKET *packet_ptr,
+ NXD_ADDRESS *local_ip, NXD_ADDRESS *remote_ip, UINT remote_port)
+{
+
+NX_IP *ip_ptr;
+NX_UDP_HEADER *udp_header_ptr;
+
+ /* Setup the IP pointer. */
+ ip_ptr = socket_ptr -> nx_udp_socket_ip_ptr;
+
+ if (packet_ptr == NX_NULL)
+ {
+
+ /* Socket error. Just ignore. */
+ return;
+ }
+
+ /* Fake UDP and IP header. */
+ /* Prepend the UDP header to the packet. First, make room for the UDP header. */
+ packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_UDP_HEADER);
+
+ /* Increase the packet length. */
+ packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + (ULONG)sizeof(NX_UDP_HEADER);
+
+ /* Setup the UDP header pointer. */
+ /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
+ udp_header_ptr = (NX_UDP_HEADER *)packet_ptr -> nx_packet_prepend_ptr;
+
+ /* Build the first 32-bit word of the UDP header. */
+ udp_header_ptr -> nx_udp_header_word_0 =
+ ((ULONG)remote_port << NX_SHIFT_BY_16) | (ULONG)socket_ptr -> nx_udp_socket_port;
+
+ /* Build the second 32-bit word of the UDP header. */
+ udp_header_ptr -> nx_udp_header_word_1 = (packet_ptr -> nx_packet_length << NX_SHIFT_BY_16);
+
+ /* Endian swapping logic. If NX_LITTLE_ENDIAN is specified, these macros will
+ swap the endian of the UDP header. */
+ NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_0);
+ NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
+
+#ifndef NX_DISABLE_IPV4
+ if (remote_ip -> nxd_ip_version == NX_IP_VERSION_V4)
+ {
+ _nx_ip_header_add(ip_ptr, packet_ptr, remote_ip -> nxd_ip_address.v4,
+ local_ip -> nxd_ip_address.v4,
+ socket_ptr -> nx_udp_socket_type_of_service,
+ socket_ptr -> nx_udp_socket_time_to_live,
+ NX_IP_UDP,
+ socket_ptr -> nx_udp_socket_fragment_enable);
+ }
+#endif /* !NX_DISABLE_IPV4 */
+
+#ifdef FEATURE_NX_IPV6
+ if (remote_ip -> nxd_ip_version == NX_IP_VERSION_V6)
+ {
+ if (_nx_ipv6_header_add(ip_ptr, &packet_ptr,
+ NX_PROTOCOL_UDP,
+ packet_ptr -> nx_packet_length,
+ ip_ptr -> nx_ipv6_hop_limit,
+ remote_ip -> nxd_ip_address.v6,
+ local_ip -> nxd_ip_address.v6,
+ NX_NULL))
+ {
+
+ /* Release the IP internal mutex. */
+ tx_mutex_put(&(ip_ptr -> nx_ip_protection));
+ return;
+ }
+ }
+#endif /* FEATURE_NX_IPV6 */
+
+ _nx_ip_packet_deferred_receive(ip_ptr, packet_ptr);
+}
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
diff --git a/common/src/nx_udp_socket_unbind.c b/common/src/nx_udp_socket_unbind.c
index 145e2743..05953d1e 100644
--- a/common/src/nx_udp_socket_unbind.c
+++ b/common/src/nx_udp_socket_unbind.c
@@ -31,12 +31,98 @@
#include "tx_thread.h"
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_udp_socket_driver_unbind PORTABLE C */
+/* 6.1.8 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function unbinds a UDP port through TCP/IP offload interface. */
+/* */
+/* INPUT */
+/* */
+/* socket_ptr Pointer to UDP socket */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_udp_socket_bind */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */
+/* */
+/**************************************************************************/
+static UINT _nx_udp_socket_driver_unbind(NX_UDP_SOCKET *socket_ptr)
+{
+UINT i;
+NX_INTERFACE *interface_ptr;
+NX_IP *ip_ptr;
+
+
+ /* Setup the pointer to the associated IP instance. */
+ ip_ptr = socket_ptr -> nx_udp_socket_ip_ptr;
+
+ /* Loop all interfaces to unbind to ones support TCP/IP offload. */
+ for (i = 0; i < NX_MAX_IP_INTERFACES; i++)
+ {
+
+ /* Use a local variable for convenience. */
+ interface_ptr = &(ip_ptr -> nx_ip_interface[i]);
+
+ /* Check for valid interfaces. */
+ if (interface_ptr -> nx_interface_valid == NX_FALSE)
+ {
+
+ /* Skip interface not valid. */
+ continue;
+ }
+
+ /* Check for TCP/IP offload feature. */
+ if (((interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) == 0) ||
+ (interface_ptr -> nx_interface_tcpip_offload_handler == NX_NULL))
+ {
+
+ /* Skip interface not support TCP/IP offload. */
+ continue;
+ }
+
+ /* Let TCP/IP offload interface unbind port. Return value is ignored. */
+ interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr,
+ socket_ptr,
+ NX_TCPIP_OFFLOAD_UDP_SOCKET_UNBIND,
+ NX_NULL, NX_NULL, NX_NULL,
+ socket_ptr -> nx_udp_socket_port,
+ NX_NULL, NX_NO_WAIT);
+ }
+
+ return(NX_SUCCESS);
+}
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
+
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_udp_socket_unbind PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -74,6 +160,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_udp_socket_unbind(NX_UDP_SOCKET *socket_ptr)
@@ -138,6 +227,10 @@ NX_PACKET *next_packet_ptr;
/* Calculate the hash index in the UDP port array of the associated IP instance. */
index = (UINT)((port + (port >> 8)) & NX_UDP_PORT_TABLE_MASK);
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ _nx_udp_socket_driver_unbind(socket_ptr);
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
/* Disable interrupts while we unlink the current socket. */
TX_DISABLE
diff --git a/common/src/nx_utility.c b/common/src/nx_utility.c
index b8d1a827..04c4bae0 100644
--- a/common/src/nx_utility.c
+++ b/common/src/nx_utility.c
@@ -204,6 +204,116 @@ UINT i;
/* */
/* FUNCTION RELEASE */
/* */
+/* _nx_utility_uint_to_string PORTABLE C */
+/* 6.1.8 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function converts the unsigned integer to string. */
+/* */
+/* INPUT */
+/* */
+/* number Input number */
+/* base Base of the conversion */
+/* 8 for OCT */
+/* 10 for DEC */
+/* 16 for HEX */
+/* string_buffer Pointer to string buffer */
+/* string_buffer_size Size of string buffer */
+/* */
+/* OUTPUT */
+/* */
+/* size The size of output string */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */
+/* */
+/**************************************************************************/
+UINT _nx_utility_uint_to_string(UINT number, UINT base, CHAR *string_buffer, UINT string_buffer_size)
+{
+UINT i;
+UINT digit;
+UINT size;
+
+ /* Check for invalid input pointers. */
+ if ((string_buffer == NX_NULL) || (string_buffer_size == 0))
+ {
+ return(0);
+ }
+
+ /* Initialize. */
+ i = 0;
+ size = 0;
+
+ /* Loop to convert the number to ASCII. Minus 1 to put NULL terminal. */
+ while (size < string_buffer_size - 1)
+ {
+
+ /* Shift the current digits over one. */
+ for (i = size; i != 0; i--)
+ {
+
+ /* Move each digit over one place. */
+ string_buffer[i] = string_buffer[i-1];
+ }
+
+ /* Compute the next decimal digit. */
+ digit = number % base;
+
+ /* Update the input number. */
+ number = number / base;
+
+ /* Store the new digit in ASCII form. */
+ if (digit < 10)
+ {
+ string_buffer[0] = (CHAR) (digit + '0');
+ }
+ else
+ {
+ string_buffer[0] = (CHAR) (digit + 'a' - 0xa);
+ }
+
+ /* Increment the size. */
+ size++;
+
+ /* Determine if the number is now zero. */
+ if (number == 0)
+ break;
+ }
+
+ /* Determine if there is an overflow error. */
+ if (number)
+ {
+
+ /* Error, return bad values to user. */
+ size = 0;
+ }
+
+ /* Make the string NULL terminated. */
+ string_buffer[size] = (CHAR) NX_NULL;
+
+ /* Return size to caller. */
+ return(size);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
/* _nx_utility_base64_encode PORTABLE C */
/* 6.1.6 */
/* AUTHOR */
@@ -505,4 +615,4 @@ UINT source_size = base64name_size;
*bytes_copied = j;
return(NX_SUCCESS);
-}
+} \ No newline at end of file
diff --git a/common/src/nxd_tcp_client_socket_connect.c b/common/src/nxd_tcp_client_socket_connect.c
index 9cbd88ab..a2df3662 100644
--- a/common/src/nxd_tcp_client_socket_connect.c
+++ b/common/src/nxd_tcp_client_socket_connect.c
@@ -32,12 +32,163 @@
#include "nx_ipv4.h"
#include "nx_ip.h"
+
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxd_tcp_client_socket_driver_connect PORTABLE C */
+/* 6.1.8 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function handles the connect request for TCP/IP offload */
+/* interface. */
+/* */
+/* INPUT */
+/* */
+/* socket_ptr Pointer to TCP client socket */
+/* server_ip IP address of server */
+/* server_port Port number of server */
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* tx_mutex_get Obtain protection */
+/* tx_mutex_put Release protection */
+/* */
+/* CALLED BY */
+/* */
+/* _nxd_tcp_client_socket_connect */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */
+/* */
+/**************************************************************************/
+static UINT _nxd_tcp_client_socket_driver_connect(NX_TCP_SOCKET *socket_ptr,
+ NXD_ADDRESS *server_ip,
+ UINT server_port,
+ ULONG wait_option)
+{
+UINT status;
+NX_INTERFACE *interface_ptr;
+NX_IP *ip_ptr;
+
+
+ /* Setup the pointer to the associated IP instance. */
+ ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr;
+
+ /* Clear the socket timeout. */
+ socket_ptr -> nx_tcp_socket_timeout = 0;
+
+ /* Let TCP/IP offload interface make the connection. */
+ interface_ptr = socket_ptr -> nx_tcp_socket_connect_interface;
+ status = interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr,
+ NX_TCPIP_OFFLOAD_TCP_CLIENT_SOCKET_CONNECT,
+ NX_NULL, NX_NULL, server_ip,
+ socket_ptr -> nx_tcp_socket_port,
+ &server_port, wait_option);
+ if ((status == NX_SUCCESS) || (status == NX_IN_PROGRESS))
+ {
+
+ /* Set MSS. */
+#ifndef NX_DISABLE_IPV4
+ if (server_ip -> nxd_ip_version == NX_IP_VERSION_V4)
+ {
+ socket_ptr -> nx_tcp_socket_mss =
+ (ULONG)((interface_ptr -> nx_interface_ip_mtu_size - sizeof(NX_IPV4_HEADER)) - sizeof(NX_TCP_HEADER));
+ }
+#endif /* !NX_DISABLE_IPV4 */
+#ifdef FEATURE_NX_IPV6
+ if (server_ip -> nxd_ip_version == NX_IP_VERSION_V6)
+ {
+ socket_ptr -> nx_tcp_socket_mss =
+ (ULONG)((interface_ptr -> nx_interface_ip_mtu_size - sizeof(NX_IPV6_HEADER)) - sizeof(NX_TCP_HEADER));
+ }
+#endif /* FEATURE_NX_IPV6 */
+ socket_ptr -> nx_tcp_socket_connect_mss = socket_ptr -> nx_tcp_socket_mss;
+ socket_ptr -> nx_tcp_socket_peer_mss = socket_ptr -> nx_tcp_socket_mss;
+
+ if (status == NX_SUCCESS)
+ {
+
+ /* Connected to server. */
+ socket_ptr -> nx_tcp_socket_state = NX_TCP_ESTABLISHED;
+#ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
+
+ /* Is a connection completion callback registered with the TCP socket? */
+ if (socket_ptr -> nx_tcp_establish_notify)
+ {
+
+ /* Call the application's establish callback function. */
+ (socket_ptr -> nx_tcp_establish_notify)(socket_ptr);
+ }
+#endif
+
+ /* Release the IP protection. */
+ tx_mutex_put(&(ip_ptr -> nx_ip_protection));
+ return(NX_SUCCESS);
+ }
+ else
+ {
+
+ /* Connected to server. */
+ socket_ptr -> nx_tcp_socket_state = NX_TCP_SYN_SENT;
+ }
+ }
+ else
+ {
+
+ /* Unable to connect to server. */
+
+#ifndef NX_DISABLE_TCP_INFO
+
+ /* Reduce the active connections count. */
+ ip_ptr -> nx_ip_tcp_active_connections--;
+
+ /* Reduce the TCP connections count. */
+ ip_ptr -> nx_ip_tcp_connections--;
+#endif
+
+ /* Restore the socket state. */
+ socket_ptr -> nx_tcp_socket_state = NX_TCP_CLOSED;
+
+ /* Reset server port and server IP address. */
+ memset(&socket_ptr -> nx_tcp_socket_connect_ip, 0, sizeof(NXD_ADDRESS));
+ socket_ptr -> nx_tcp_socket_connect_port = 0;
+
+ /* Reset the next_hop_address information. */
+ socket_ptr -> nx_tcp_socket_next_hop_address = 0;
+
+ /* Release the IP protection. */
+ tx_mutex_put(&(ip_ptr -> nx_ip_protection));
+ return(NX_TCPIP_OFFLOAD_ERROR);
+ }
+
+ /* Release the IP protection. */
+ tx_mutex_put(&(ip_ptr -> nx_ip_protection));
+ return(NX_SUCCESS);
+}
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
+
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nxd_tcp_client_socket_connect PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -79,6 +230,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nxd_tcp_client_socket_connect(NX_TCP_SOCKET *socket_ptr,
@@ -307,8 +461,21 @@ ULONG ip_address_log = 0;
socket_ptr -> nx_tcp_socket_receive_queue_head = NX_NULL;
socket_ptr -> nx_tcp_socket_receive_queue_tail = NX_NULL;
- /* Send the SYN message. */
- _nx_tcp_packet_send_syn(socket_ptr, (socket_ptr -> nx_tcp_socket_tx_sequence - 1));
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ if ((outgoing_interface -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) &&
+ (outgoing_interface -> nx_interface_tcpip_offload_handler))
+ {
+
+ /* This interface supports TCP/IP offload. */
+ return(_nxd_tcp_client_socket_driver_connect(socket_ptr, server_ip, server_port, wait_option));
+ }
+ else
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+ {
+
+ /* Send the SYN message. */
+ _nx_tcp_packet_send_syn(socket_ptr, (socket_ptr -> nx_tcp_socket_tx_sequence - 1));
+ }
/* Optionally suspend the thread. If timeout occurs, return a connection timeout status. If
immediate response is selected, return a connection in progress status. Only on a real
diff --git a/common/src/nxd_udp_socket_send.c b/common/src/nxd_udp_socket_send.c
index a32c21e9..2f661756 100644
--- a/common/src/nxd_udp_socket_send.c
+++ b/common/src/nxd_udp_socket_send.c
@@ -28,6 +28,7 @@
#include "nx_api.h"
#include "nx_udp.h"
#include "nx_ip.h"
+#include "nx_packet.h"
#ifdef FEATURE_NX_IPV6
#include "nx_ipv6.h"
#endif /* FEATURE_NX_IPV6 */
@@ -36,12 +37,177 @@
#include "nx_ipsec.h"
#endif /* NX_IPSEC_ENABLE */
+
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_udp_socket_driver_send PORTABLE C */
+/* 6.1.8 */
+/* AUTHOR */
+/* */
+/* Yuxin Zhou, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sends a UDP packet through TCP/IP offload interface. */
+/* */
+/* INPUT */
+/* */
+/* socket_ptr Pointer to UDP socket */
+/* packet_ptr Pointer to UDP packet */
+/* ip_src_address Source IP address */
+/* ip_dst_address Destination IP address */
+/* port 16-bit UDP port number */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_ip_packet_send Packet send function */
+/* _nx_ipv6_packet_send Packet send function */
+/* */
+/* CALLED BY */
+/* */
+/* _nxd_udp_socket_send */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */
+/* */
+/**************************************************************************/
+static UINT _nx_udp_socket_driver_send(NX_UDP_SOCKET *socket_ptr,
+ NX_PACKET *packet_ptr,
+ NXD_ADDRESS *ip_src_address,
+ NXD_ADDRESS *ip_dst_address,
+ UINT port)
+{
+UINT status;
+NX_IP *ip_ptr;
+NX_INTERFACE *interface_ptr = NX_NULL;
+UCHAR *original_ptr = packet_ptr -> nx_packet_prepend_ptr + sizeof(NX_UDP_HEADER);
+ULONG original_length = packet_ptr -> nx_packet_length - sizeof(NX_UDP_HEADER);
+
+ /* Set up the pointer to the associated IP instance. */
+ ip_ptr = socket_ptr -> nx_udp_socket_ip_ptr;
+
+ /* Get the outgoing interface. */
+#ifndef NX_DISABLE_IPV4
+ if (ip_dst_address -> nxd_ip_version == NX_IP_VERSION_V4)
+ {
+ interface_ptr = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
+ }
+#endif /* NX_DISABLE_IPV4 */
+#ifdef FEATURE_NX_IPV6
+ if (ip_dst_address -> nxd_ip_version == NX_IP_VERSION_V6)
+ {
+ interface_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
+ }
+#endif /* FEATURE_NX_IPV6 */
+
+#ifdef NX_ENABLE_IP_PACKET_FILTER
+ /* Check if the IP packet filter is set. */
+ if (ip_ptr -> nx_ip_packet_filter || ip_ptr -> nx_ip_packet_filter_extended)
+ {
+
+ /* Add the IP Header to trigger filtering. */
+#ifndef NX_DISABLE_IPV4
+ if (ip_dst_address -> nxd_ip_version == NX_IP_VERSION_V4)
+ {
+ _nx_ip_header_add(ip_ptr, packet_ptr,
+ ip_src_address -> nxd_ip_address.v4,
+ ip_dst_address -> nxd_ip_address.v4,
+ socket_ptr -> nx_udp_socket_type_of_service,
+ socket_ptr -> nx_udp_socket_time_to_live,
+ NX_IP_UDP, socket_ptr -> nx_udp_socket_fragment_enable);
+ }
+#endif /* !NX_DISABLE_IPV4 */
+
+#ifdef FEATURE_NX_IPV6
+ if (ip_dst_address -> nxd_ip_version == NX_IP_VERSION_V6)
+ {
+ if (_nx_ipv6_header_add(ip_ptr, &packet_ptr, NX_PROTOCOL_UDP,
+ packet_ptr -> nx_packet_length,
+ ip_ptr -> nx_ipv6_hop_limit,
+ ip_src_address -> nxd_ip_address.v6,
+ ip_dst_address -> nxd_ip_address.v6, NX_NULL))
+ {
+
+ /* Packet consumed by IPv6 layer. Just return success. */
+ tx_mutex_put(&(ip_ptr -> nx_ip_protection));
+ return(NX_SUCCESS);
+ }
+
+ /* Reset IP header. */
+ packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + sizeof(NX_IPV6_HEADER);
+ packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - sizeof(NX_IPV6_HEADER);
+ }
+#endif /* FEATURE_NX_IPV6 */
+
+ if (ip_ptr -> nx_ip_packet_filter)
+ {
+ if (ip_ptr -> nx_ip_packet_filter((VOID *)(packet_ptr -> nx_packet_prepend_ptr),
+ NX_IP_PACKET_OUT) != NX_SUCCESS)
+ {
+
+ /* Packet consumed by IP filter. Just return success. */
+ _nx_packet_transmit_release(packet_ptr);
+ return(NX_SUCCESS);
+ }
+ }
+
+ /* Check if the IP packet filter extended is set. */
+ if (ip_ptr -> nx_ip_packet_filter_extended)
+ {
+
+ /* Yes, call the IP packet filter extended routine. */
+ if (ip_ptr -> nx_ip_packet_filter_extended(ip_ptr, packet_ptr, NX_IP_PACKET_OUT) != NX_SUCCESS)
+ {
+
+ /* Packet consumed by IP filter. Just return success. */
+ _nx_packet_transmit_release(packet_ptr);
+ return(NX_SUCCESS);
+ }
+ }
+ }
+#endif /* NX_ENABLE_IP_PACKET_FILTER */
+
+ /* Reset UDP and IP header. */
+ packet_ptr -> nx_packet_prepend_ptr = original_ptr;
+ packet_ptr -> nx_packet_length = original_length;
+
+ /* Let TCP/IP offload interface send the packet. */
+ status = interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr,
+ NX_TCPIP_OFFLOAD_UDP_SOCKET_SEND,
+ packet_ptr, ip_src_address, ip_dst_address,
+ socket_ptr -> nx_udp_socket_port,
+ &port, NX_NO_WAIT);
+
+ /* Release the IP protection. */
+ tx_mutex_put(&(ip_ptr -> nx_ip_protection));
+
+ if (status)
+ {
+ return(NX_TCPIP_OFFLOAD_ERROR);
+ }
+ else
+ {
+ return(NX_SUCCESS);
+ }
+}
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nxd_udp_socket_send PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -87,6 +253,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
+/* supported TCP/IP offload, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nxd_udp_socket_send(NX_UDP_SOCKET *socket_ptr,
@@ -109,6 +278,10 @@ NX_INTERFACE *interface_ptr = NX_NULL;
UINT status;
#endif /* FEATURE_NX_IPV6 */
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+NXD_ADDRESS ip_src_address;
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
#ifdef NX_IPSEC_ENABLE
VOID *sa = NX_NULL;
ULONG data_offset;
@@ -199,6 +372,11 @@ UINT compute_checksum = 1;
/* Fill in the IP src/dest address */
ip_dest_addr = &ip_address -> nxd_ip_address.v4;
ip_src_addr = &interface_ptr -> nx_interface_ip_address;
+
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ ip_src_address.nxd_ip_version = NX_IP_VERSION_V4;
+ ip_src_address.nxd_ip_address.v4 = interface_ptr -> nx_interface_ip_address;
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
}
#endif /* NX_DISABLE_IPV4 */
@@ -229,6 +407,11 @@ UINT compute_checksum = 1;
/* Get the packet interface information. */
interface_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
#endif /* NX_ENABLE_INTERFACE_CAPABILITY */
+
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ ip_src_address.nxd_ip_version = NX_IP_VERSION_V6;
+ COPY_IPV6_ADDRESS(ip_src_addr, ip_src_address.nxd_ip_address.v6);
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
}
#endif /* FEATURE_NX_IPV6 */
@@ -281,7 +464,7 @@ UINT compute_checksum = 1;
}
}
#endif /* NX_IPSEC_ENABLE */
-
+
/* Prepend the UDP header to the packet. First, make room for the UDP header. */
packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_UDP_HEADER);
@@ -320,16 +503,16 @@ UINT compute_checksum = 1;
NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_UDP_SEND, ip_ptr, socket_ptr, packet_ptr, udp_header_ptr -> nx_udp_header_word_0, NX_TRACE_INTERNAL_EVENTS, 0, 0);
/* Endian swapping logic. If NX_LITTLE_ENDIAN is specified, these macros will
- swap the endian of the UDP header. */
+ swap the endian of the UDP header. */
NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_0);
NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
/* Determine if we need to compute the UDP checksum.
- Note that with IPv6, UDP packet checksum is mandatory. However if the underly device
- driver is able to compute UDP checksum in hardware, let the driver handle the checksum
- computation.
- */
+ Note that with IPv6, UDP packet checksum is mandatory. However if the underly device
+ driver is able to compute UDP checksum in hardware, let the driver handle the checksum
+ computation.
+ */
if ((!socket_ptr -> nx_udp_socket_disable_checksum) ||
(ip_address -> nxd_ip_version == NX_IP_VERSION_V6))
@@ -343,8 +526,8 @@ UINT compute_checksum = 1;
#ifdef NX_IPSEC_ENABLE
/* In case this packet is going through the IPsec protected channel, the checksum would have to be computed
- in software even if the hardware checksum is available at driver layer. The checksum value must be present
- in order when applying IPsec process. */
+ in software even if the hardware checksum is available at driver layer. The checksum value must be present
+ in order when applying IPsec process. */
if ((packet_ptr -> nx_packet_ipsec_sa_ptr != NX_NULL) && (((NX_IPSEC_SA *)(packet_ptr -> nx_packet_ipsec_sa_ptr)) -> nx_ipsec_sa_encryption_method != NX_CRYPTO_NONE))
{
@@ -392,6 +575,14 @@ UINT compute_checksum = 1;
/* Get mutex protection. */
tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
+#ifdef NX_ENABLE_TCPIP_OFFLOAD
+ if ((interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) &&
+ (interface_ptr -> nx_interface_tcpip_offload_handler))
+ {
+ return(_nx_udp_socket_driver_send(socket_ptr, packet_ptr, &ip_src_address, ip_address, port));
+ }
+#endif /* NX_ENABLE_TCPIP_OFFLOAD */
+
#ifndef NX_DISABLE_IPV4
/* Send the UDP packet to the IPv4 component. */
if (ip_address -> nxd_ip_version == NX_IP_VERSION_V4)
diff --git a/crypto_libraries/inc/nx_crypto_huge_number.h b/crypto_libraries/inc/nx_crypto_huge_number.h
index a988fb9a..be905c5c 100644
--- a/crypto_libraries/inc/nx_crypto_huge_number.h
+++ b/crypto_libraries/inc/nx_crypto_huge_number.h
@@ -26,7 +26,7 @@
/* APPLICATION INTERFACE DEFINITION RELEASE */
/* */
/* nx_crypto_huge_number.h PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -44,6 +44,9 @@
/* 09-30-2020 Timothy Stapko Modified comment(s), and */
/* fixed number initialization,*/
/* resulting in version 6.1 */
+/* 08-02-2021 Timothy Stapko Modified comment(s), and */
+/* used ULONG64_DEFINED macro, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
@@ -77,10 +80,9 @@ extern "C" {
#endif /* NX_CRYPTO_HUGE_NUMBER_BITS */
#if (NX_CRYPTO_HUGE_NUMBER_BITS == 32)
-#ifndef ULONG64
+#ifndef ULONG64_DEFINED
+#define ULONG64_DEFINED
#define ULONG64 unsigned long long
-#endif
-#ifndef LONG64
#define LONG64 long long
#endif
#define HN_BASE LONG
diff --git a/crypto_libraries/inc/nx_crypto_sha5.h b/crypto_libraries/inc/nx_crypto_sha5.h
index 8b1b7ee0..aecf1ebe 100644
--- a/crypto_libraries/inc/nx_crypto_sha5.h
+++ b/crypto_libraries/inc/nx_crypto_sha5.h
@@ -25,7 +25,7 @@
/* COMPONENT DEFINITION RELEASE */
/* */
/* nx_crypto_sha5.h PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -45,6 +45,9 @@
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Timothy Stapko Modified comment(s), and */
+/* used ULONG64_DEFINED macro, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
@@ -65,13 +68,11 @@ extern "C" {
#include "nx_crypto.h"
-#ifndef ULONG64
+#ifndef ULONG64_DEFINED
+#define ULONG64_DEFINED
#define ULONG64 unsigned long long
#endif /* ULONG64 */
-#ifndef LONG64
-#define LONG64 long long
-#endif /* LONG64 */
#define NX_CRYPTO_SHA512_BLOCK_SIZE_IN_BYTES 128
#define NX_CRYPTO_SHA384_ICV_LEN_IN_BITS 384
diff --git a/crypto_libraries/ports/cortex_m3/ac5/inc/nx_crypto_port.h b/crypto_libraries/ports/cortex_m3/ac5/inc/nx_crypto_port.h
index 024d9356..6d804b37 100644
--- a/crypto_libraries/ports/cortex_m3/ac5/inc/nx_crypto_port.h
+++ b/crypto_libraries/ports/cortex_m3/ac5/inc/nx_crypto_port.h
@@ -26,7 +26,7 @@
/* COMPONENT DEFINITION RELEASE */
/* */
/* nx_crypto_port.h Cortex-M3/AC5 */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -41,6 +41,8 @@
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 Timothy Stapko Initial Version 6.1 */
+/* 08-02-2021 Bhupendra Naphade Modified comment(s), */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
@@ -48,6 +50,7 @@
#define _NX_CRYPTO_PORT_H_
#include <stdlib.h>
#include <string.h>
+#include "cmsis_compiler.h"
#ifdef NX_CRYPTO_STANDALONE_ENABLE
diff --git a/crypto_libraries/ports/cortex_m3/ac6/inc/nx_crypto_port.h b/crypto_libraries/ports/cortex_m3/ac6/inc/nx_crypto_port.h
new file mode 100644
index 00000000..00548f97
--- /dev/null
+++ b/crypto_libraries/ports/cortex_m3/ac6/inc/nx_crypto_port.h
@@ -0,0 +1,81 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX Crypto Component */
+/** */
+/** Crypto */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* COMPONENT DEFINITION RELEASE */
+/* */
+/* nx_crypto_port.h Cortex-M3/AC6 */
+/* 6.1.8 */
+/* AUTHOR */
+/* */
+/* Timothy Stapko, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions for the NetX Security */
+/* Encryption component. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 08-02-2021 Bhupendra Naphade Initial Version 6.1.8 */
+/* */
+/**************************************************************************/
+
+#ifndef _NX_CRYPTO_PORT_H_
+#define _NX_CRYPTO_PORT_H_
+#include <stdlib.h>
+#include <string.h>
+#include "cmsis_compiler.h"
+
+#ifdef NX_CRYPTO_STANDALONE_ENABLE
+
+/* Default to little endian, since this is what most ARM targets are. */
+#define NX_CRYPTO_LITTLE_ENDIAN 1
+
+/* Define macros that swap the endian for little endian ports. */
+#if NX_CRYPTO_LITTLE_ENDIAN
+#define NX_CRYPTO_CHANGE_ULONG_ENDIAN(arg) (arg) = (unsigned int)(__rev(arg))
+#define NX_CRYPTO_CHANGE_USHORT_ENDIAN(arg) (arg) = (unsigned short)(__rev(arg) >> 16)
+#else
+#define NX_CRYPTO_CHANGE_ULONG_ENDIAN(a)
+#define NX_CRYPTO_CHANGE_USHORT_ENDIAN(a)
+#endif
+
+#ifndef VOID
+#define VOID void
+typedef char CHAR;
+typedef unsigned char UCHAR;
+typedef int INT;
+typedef unsigned int UINT;
+typedef long LONG;
+typedef unsigned long ULONG;
+typedef short SHORT;
+typedef unsigned short USHORT;
+#endif
+
+#endif /* NX_CRYPTO_STANDALONE_ENABLE */
+
+#endif /* _NX_CRYPTO_PORT_H_ */
diff --git a/crypto_libraries/ports/cortex_m3/keil/inc/nx_crypto_port.h b/crypto_libraries/ports/cortex_m3/keil/inc/nx_crypto_port.h
index f32d3c0d..4686e62f 100644
--- a/crypto_libraries/ports/cortex_m3/keil/inc/nx_crypto_port.h
+++ b/crypto_libraries/ports/cortex_m3/keil/inc/nx_crypto_port.h
@@ -26,7 +26,7 @@
/* COMPONENT DEFINITION RELEASE */
/* */
/* nx_crypto_port.h Cortex-M3/Keil */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -41,6 +41,8 @@
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 Timothy Stapko Initial Version 6.1 */
+/* 08-02-2021 Bhupendra Naphade Modified comment(s), */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
@@ -48,6 +50,7 @@
#define _NX_CRYPTO_PORT_H_
#include <stdlib.h>
#include <string.h>
+#include "cmsis_compiler.h"
#ifdef NX_CRYPTO_STANDALONE_ENABLE
diff --git a/crypto_libraries/ports/cortex_m4/ac5/inc/nx_crypto_port.h b/crypto_libraries/ports/cortex_m4/ac5/inc/nx_crypto_port.h
index ab2dfd4a..5c87204b 100644
--- a/crypto_libraries/ports/cortex_m4/ac5/inc/nx_crypto_port.h
+++ b/crypto_libraries/ports/cortex_m4/ac5/inc/nx_crypto_port.h
@@ -26,7 +26,7 @@
/* COMPONENT DEFINITION RELEASE */
/* */
/* nx_crypto_port.h Cortex-M4/AC5 */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -41,6 +41,8 @@
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 Timothy Stapko Initial Version 6.1 */
+/* 08-02-2021 Bhupendra Naphade Modified comment(s), */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
@@ -48,6 +50,7 @@
#define _NX_CRYPTO_PORT_H_
#include <stdlib.h>
#include <string.h>
+#include "cmsis_compiler.h"
#ifdef NX_CRYPTO_STANDALONE_ENABLE
diff --git a/crypto_libraries/ports/cortex_m4/ac6/inc/nx_crypto_port.h b/crypto_libraries/ports/cortex_m4/ac6/inc/nx_crypto_port.h
new file mode 100644
index 00000000..07f0e1bf
--- /dev/null
+++ b/crypto_libraries/ports/cortex_m4/ac6/inc/nx_crypto_port.h
@@ -0,0 +1,81 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX Crypto Component */
+/** */
+/** Crypto */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* COMPONENT DEFINITION RELEASE */
+/* */
+/* nx_crypto_port.h Cortex-M4/AC6 */
+/* 6.1.8 */
+/* AUTHOR */
+/* */
+/* Timothy Stapko, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions for the NetX Security */
+/* Encryption component. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 08-02-2021 Bhupendra Naphade Initial Version 6.1.8 */
+/* */
+/**************************************************************************/
+
+#ifndef _NX_CRYPTO_PORT_H_
+#define _NX_CRYPTO_PORT_H_
+#include <stdlib.h>
+#include <string.h>
+#include "cmsis_compiler.h"
+
+#ifdef NX_CRYPTO_STANDALONE_ENABLE
+
+/* Default to little endian, since this is what most ARM targets are. */
+#define NX_CRYPTO_LITTLE_ENDIAN 1
+
+/* Define macros that swap the endian for little endian ports. */
+#if NX_CRYPTO_LITTLE_ENDIAN
+#define NX_CRYPTO_CHANGE_ULONG_ENDIAN(arg) (arg) = (unsigned int)(__rev(arg))
+#define NX_CRYPTO_CHANGE_USHORT_ENDIAN(arg) (arg) = (unsigned short)(__rev(arg) >> 16)
+#else
+#define NX_CRYPTO_CHANGE_ULONG_ENDIAN(a)
+#define NX_CRYPTO_CHANGE_USHORT_ENDIAN(a)
+#endif
+
+#ifndef VOID
+#define VOID void
+typedef char CHAR;
+typedef unsigned char UCHAR;
+typedef int INT;
+typedef unsigned int UINT;
+typedef long LONG;
+typedef unsigned long ULONG;
+typedef short SHORT;
+typedef unsigned short USHORT;
+#endif
+
+#endif /* NX_CRYPTO_STANDALONE_ENABLE */
+
+#endif /* _NX_CRYPTO_PORT_H_ */
diff --git a/crypto_libraries/ports/cortex_m4/keil/inc/nx_crypto_port.h b/crypto_libraries/ports/cortex_m4/keil/inc/nx_crypto_port.h
index f95f0451..8d516e18 100644
--- a/crypto_libraries/ports/cortex_m4/keil/inc/nx_crypto_port.h
+++ b/crypto_libraries/ports/cortex_m4/keil/inc/nx_crypto_port.h
@@ -26,7 +26,7 @@
/* COMPONENT DEFINITION RELEASE */
/* */
/* nx_crypto_port.h Cortex-M4/Keil */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -41,6 +41,8 @@
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 Timothy Stapko Initial Version 6.1 */
+/* 08-02-2021 Bhupendra Naphade Modified comment(s), */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
@@ -48,6 +50,7 @@
#define _NX_CRYPTO_PORT_H_
#include <stdlib.h>
#include <string.h>
+#include "cmsis_compiler.h"
#ifdef NX_CRYPTO_STANDALONE_ENABLE
diff --git a/crypto_libraries/ports/cortex_m7/ac5/inc/nx_crypto_port.h b/crypto_libraries/ports/cortex_m7/ac5/inc/nx_crypto_port.h
index 28e969cd..dd7140bd 100644
--- a/crypto_libraries/ports/cortex_m7/ac5/inc/nx_crypto_port.h
+++ b/crypto_libraries/ports/cortex_m7/ac5/inc/nx_crypto_port.h
@@ -26,7 +26,7 @@
/* COMPONENT DEFINITION RELEASE */
/* */
/* nx_crypto_port.h Cortex-M7/AC5 */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -41,6 +41,8 @@
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 Timothy Stapko Initial Version 6.1 */
+/* 08-02-2021 Bhupendra Naphade Modified comment(s), */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
@@ -48,6 +50,7 @@
#define _NX_CRYPTO_PORT_H_
#include <stdlib.h>
#include <string.h>
+#include "cmsis_compiler.h"
#ifdef NX_CRYPTO_STANDALONE_ENABLE
diff --git a/crypto_libraries/ports/cortex_m7/ac6/inc/nx_crypto_port.h b/crypto_libraries/ports/cortex_m7/ac6/inc/nx_crypto_port.h
new file mode 100644
index 00000000..4e2e12ea
--- /dev/null
+++ b/crypto_libraries/ports/cortex_m7/ac6/inc/nx_crypto_port.h
@@ -0,0 +1,81 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX Crypto Component */
+/** */
+/** Crypto */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* COMPONENT DEFINITION RELEASE */
+/* */
+/* nx_crypto_port.h Cortex-M7/AC6 */
+/* 6.1.8 */
+/* AUTHOR */
+/* */
+/* Timothy Stapko, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions for the NetX Security */
+/* Encryption component. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 08-02-2021 Bhupendra Naphade Initial Version 6.1.8 */
+/* */
+/**************************************************************************/
+
+#ifndef _NX_CRYPTO_PORT_H_
+#define _NX_CRYPTO_PORT_H_
+#include <stdlib.h>
+#include <string.h>
+#include "cmsis_compiler.h"
+
+#ifdef NX_CRYPTO_STANDALONE_ENABLE
+
+/* Default to little endian, since this is what most ARM targets are. */
+#define NX_CRYPTO_LITTLE_ENDIAN 1
+
+/* Define macros that swap the endian for little endian ports. */
+#if NX_CRYPTO_LITTLE_ENDIAN
+#define NX_CRYPTO_CHANGE_ULONG_ENDIAN(arg) (arg) = (unsigned int)(__rev(arg))
+#define NX_CRYPTO_CHANGE_USHORT_ENDIAN(arg) (arg) = (unsigned short)(__rev(arg) >> 16)
+#else
+#define NX_CRYPTO_CHANGE_ULONG_ENDIAN(a)
+#define NX_CRYPTO_CHANGE_USHORT_ENDIAN(a)
+#endif
+
+#ifndef VOID
+#define VOID void
+typedef char CHAR;
+typedef unsigned char UCHAR;
+typedef int INT;
+typedef unsigned int UINT;
+typedef long LONG;
+typedef unsigned long ULONG;
+typedef short SHORT;
+typedef unsigned short USHORT;
+#endif
+
+#endif /* NX_CRYPTO_STANDALONE_ENABLE */
+
+#endif /* _NX_CRYPTO_PORT_H_ */
diff --git a/nx_secure/inc/nx_secure_tls.h b/nx_secure/inc/nx_secure_tls.h
index 37a16d5c..dcb9364f 100644
--- a/nx_secure/inc/nx_secure_tls.h
+++ b/nx_secure/inc/nx_secure_tls.h
@@ -26,7 +26,7 @@
/* COMPONENT DEFINITION RELEASE */
/* */
/* nx_secure_tls.h PORTABLE C */
-/* 6.1.7 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -70,6 +70,11 @@
/* 06-02-2021 Yuxin Zhou Modified comment(s), and */
/* updated product constants, */
/* resulting in version 6.1.7 */
+/* 08-02-2021 Timothy Stapko Modified comment(s), added */
+/* hash clone and cleanup, */
+/* added state to cleanup */
+/* session cipher, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
@@ -130,7 +135,7 @@ extern "C" {
#define AZURE_RTOS_NETX_SECURE
#define NETX_SECURE_MAJOR_VERSION 6
#define NETX_SECURE_MINOR_VERSION 1
-#define NETX_SECURE_PATCH_VERSION 7
+#define NETX_SECURE_PATCH_VERSION 8
/* The following symbols are defined for backward compatibility reasons. */
#define EL_PRODUCT_NETX_SECURE
@@ -157,6 +162,14 @@ extern "C" {
#define NX_SECURE_MEMMOVE memmove
#endif /* NX_SECURE_MEMMOVE */
+#ifndef NX_SECURE_HASH_METADATA_CLONE
+#define NX_SECURE_HASH_METADATA_CLONE NX_SECURE_MEMCPY
+#endif /* NX_SECURE_HASH_METADATA_CLONE */
+
+#ifndef NX_SECURE_HASH_CLONE_CLEANUP
+#define NX_SECURE_HASH_CLONE_CLEANUP(x, y)
+#endif /* NX_SECURE_HASH_CLONE_CLEANUP */
+
/* Map NX_SECURE_CALLER_CHECKING_EXTERNS to NX_CALLER_CHECKING_EXTERNS, which is defined
in nx_port.h.*/
@@ -1130,12 +1143,16 @@ typedef struct NX_SECURE_TLS_SESSION_STRUCT
USHORT nx_secure_tls_protocol_version_override;
/* The highest supported protocol version obtained through negotiation. */
- USHORT nx_secure_tls_negotiated_highest_protocol_version;
+ USHORT nx_secure_tls_negotiated_highest_protocol_version;
/* State of local and remote encryption - post ChangeCipherSpec. */
UCHAR nx_secure_tls_remote_session_active;
UCHAR nx_secure_tls_local_session_active;
+ /* State of whether the client and server session cipher is initialized. */
+ UCHAR nx_secure_tls_session_cipher_client_initialized;
+ UCHAR nx_secure_tls_session_cipher_server_initialized;
+
/* Chosen ciphersuite. */
const NX_SECURE_TLS_CIPHERSUITE_INFO *nx_secure_tls_session_ciphersuite;
diff --git a/nx_secure/inc/nx_secure_user_sample.h b/nx_secure/inc/nx_secure_user_sample.h
index aba811b3..c53c4611 100644
--- a/nx_secure/inc/nx_secure_user_sample.h
+++ b/nx_secure/inc/nx_secure_user_sample.h
@@ -26,7 +26,7 @@
/* PORT SPECIFIC C INFORMATION RELEASE */
/* */
/* nx_secure_user.h PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* */
/* AUTHOR */
/* */
@@ -48,6 +48,8 @@
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Timothy Stapko Modified comment(s), */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
@@ -93,11 +95,12 @@
#define NX_SECURE_ENABLE_PSK_CIPHERSUITES
*/
-/* NX_SECURE_AEAD_CIPHER_CHECK AEAD ciphersuites other than AES-CCM or AES-GCM.
+/* NX_SECURE_AEAD_CIPHER_CHECK allows to detect user-implemented AEAD algorithms other than AES-CCM or
+ AES-GCM. It can be defined like #define NX_SECURE_AEAD_CIPHER_CHECK(a) ((a) == NEW_ALGORITHM_ID).
It works only when NX_SECURE_ENABLE_AEAD_CIPHER is defined.
By default this feature is not enabled. */
/*
- #define NX_SECURE_AEAD_CIPHER_CHECK
+ #define NX_SECURE_AEAD_CIPHER_CHECK(a) NX_FALSE
*/
/* NX_SECURE_ALLOW_SELF_SIGNED_CERTIFICATES enables self signed certificates. By default
@@ -305,4 +308,16 @@
#define NX_SECURE_X509_USE_EXTENDED_DISTINGUISHED_NAMES
*/
+/* If the handshake hash state cannot be copied using memory copy on metadata,
+ NX_SECURE_HASH_METADATA_CLONE should be defined to a function that clones the hash state.
+ UINT nx_crypto_hash_clone(VOID *dest_metadata, VOID *source_metadata, ULONG length);
+ #define NX_SECURE_HASH_METADATA_CLONE nx_crypto_hash_clone
+*/
+
+/* If cleaning up is required for the handshake hash crypto after being cloned,
+ NX_SECURE_HASH_CLONE_CLEANUP macro should be defined to a clean up function:
+ UINT nx_crypto_clone_cleanup(VOID *metadata, ULONG length);
+ #define NX_SECURE_HASH_CLONE_CLEANUP nx_crypto_clone_cleanup
+*/
+
#endif /* SRC_NX_SECURE_USER_H */ \ No newline at end of file
diff --git a/nx_secure/src/nx_secure_tls_1_3_generate_keys.c b/nx_secure/src/nx_secure_tls_1_3_generate_keys.c
index 06b5f269..c7bfea6b 100644
--- a/nx_secure/src/nx_secure_tls_1_3_generate_keys.c
+++ b/nx_secure/src/nx_secure_tls_1_3_generate_keys.c
@@ -169,7 +169,7 @@ UINT is_resumption_psk = NX_FALSE;
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_1_3_generate_handshake_keys PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -200,6 +200,9 @@ UINT is_resumption_psk = NX_FALSE;
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
+/* 08-02-2021 Timothy Stapko Modified comment(s), added */
+/* cleanup for session cipher, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
#if (NX_SECURE_TLS_TLS_1_3_ENABLED)
@@ -373,6 +376,17 @@ UINT hash_size;
/* Initialize the crypto method used in the session cipher. */
if (session_cipher_method -> nx_crypto_init != NULL)
{
+ if (tls_session -> nx_secure_tls_session_cipher_client_initialized && session_cipher_method -> nx_crypto_cleanup)
+ {
+ status = session_cipher_method -> nx_crypto_cleanup(tls_session -> nx_secure_session_cipher_metadata_area_client);
+ if (status != NX_CRYPTO_SUCCESS)
+ {
+ return(status);
+ }
+
+ tls_session -> nx_secure_tls_session_cipher_client_initialized = 0;
+ }
+
/* Set client write key. */
status = session_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_cipher_method,
tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_write_key,
@@ -386,6 +400,19 @@ UINT hash_size;
return(status);
}
+ tls_session -> nx_secure_tls_session_cipher_client_initialized = 1;
+
+ if (tls_session -> nx_secure_tls_session_cipher_server_initialized && session_cipher_method -> nx_crypto_cleanup)
+ {
+ status = session_cipher_method -> nx_crypto_cleanup(tls_session -> nx_secure_session_cipher_metadata_area_server);
+ if (status != NX_CRYPTO_SUCCESS)
+ {
+ return(status);
+ }
+
+ tls_session -> nx_secure_tls_session_cipher_server_initialized = 0;
+ }
+
/* Set server write key. */
status = session_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_cipher_method,
tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_write_key,
@@ -398,6 +425,8 @@ UINT hash_size;
{
return(status);
}
+
+ tls_session -> nx_secure_tls_session_cipher_server_initialized = 1;
}
return(NX_SUCCESS);
diff --git a/nx_secure/src/nx_secure_tls_1_3_session_keys_set.c b/nx_secure/src/nx_secure_tls_1_3_session_keys_set.c
index ba1b5912..55089aa5 100644
--- a/nx_secure/src/nx_secure_tls_1_3_session_keys_set.c
+++ b/nx_secure/src/nx_secure_tls_1_3_session_keys_set.c
@@ -30,7 +30,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_1_3_session_keys_set PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -74,6 +74,9 @@
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
+/* 08-02-2021 Timothy Stapko Modified comment(s), added */
+/* cleanup for session cipher, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
#define NX_SECURE_SOURCE_CODE
@@ -170,15 +173,39 @@ const NX_CRYPTO_METHOD *session_cipher_method = NX_NULL;
/* Set client write key. */
if (is_client)
{
+ if (tls_session -> nx_secure_tls_session_cipher_client_initialized && session_cipher_method -> nx_crypto_cleanup)
+ {
+ status = session_cipher_method -> nx_crypto_cleanup(tls_session -> nx_secure_session_cipher_metadata_area_client);
+ if (status != NX_CRYPTO_SUCCESS)
+ {
+ return(status);
+ }
+
+ tls_session -> nx_secure_tls_session_cipher_client_initialized = 0;
+ }
+
status = session_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_cipher_method,
tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_write_key,
session_cipher_method -> nx_crypto_key_size_in_bits,
&tls_session -> nx_secure_session_cipher_handler_client,
tls_session -> nx_secure_session_cipher_metadata_area_client,
tls_session -> nx_secure_session_cipher_metadata_size);
+
+ tls_session -> nx_secure_tls_session_cipher_client_initialized = 1;
}
else
{
+ if (tls_session -> nx_secure_tls_session_cipher_server_initialized && session_cipher_method -> nx_crypto_cleanup)
+ {
+ status = session_cipher_method -> nx_crypto_cleanup(tls_session -> nx_secure_session_cipher_metadata_area_server);
+ if (status != NX_CRYPTO_SUCCESS)
+ {
+ return(status);
+ }
+
+ tls_session -> nx_secure_tls_session_cipher_server_initialized = 0;
+ }
+
/* Set server write key. */
status = session_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_cipher_method,
tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_write_key,
@@ -186,6 +213,8 @@ const NX_CRYPTO_METHOD *session_cipher_method = NX_NULL;
&tls_session -> nx_secure_session_cipher_handler_server,
tls_session -> nx_secure_session_cipher_metadata_area_server,
tls_session -> nx_secure_session_cipher_metadata_size);
+
+ tls_session -> nx_secure_tls_session_cipher_server_initialized = 1;
}
if (status != NX_CRYPTO_SUCCESS)
{
diff --git a/nx_secure/src/nx_secure_tls_1_3_transcript_hash_save.c b/nx_secure/src/nx_secure_tls_1_3_transcript_hash_save.c
index 378cbe93..38a2de0b 100644
--- a/nx_secure/src/nx_secure_tls_1_3_transcript_hash_save.c
+++ b/nx_secure/src/nx_secure_tls_1_3_transcript_hash_save.c
@@ -30,7 +30,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_1_3_transcript_hash_save PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -66,6 +66,9 @@
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
+/* 08-02-2021 Timothy Stapko Modified comment(s), added */
+/* hash clone and cleanup, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
#if (NX_SECURE_TLS_TLS_1_3_ENABLED)
@@ -107,9 +110,9 @@ CHAR *metadata;
{
/* Copy over the handshake hash state into a local structure to do the intermediate calculation. */
- NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */
+ NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */
metadata = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch;
}
@@ -141,6 +144,11 @@ CHAR *metadata;
NX_NULL);
}
+ if (need_copy)
+ {
+ NX_SECURE_HASH_CLONE_CLEANUP(metadata, tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size);
+ }
+
return(status);
}
diff --git a/nx_secure/src/nx_secure_tls_finished_hash_generate.c b/nx_secure/src/nx_secure_tls_finished_hash_generate.c
index 05cb2ecc..99ec5388 100644
--- a/nx_secure/src/nx_secure_tls_finished_hash_generate.c
+++ b/nx_secure/src/nx_secure_tls_finished_hash_generate.c
@@ -33,7 +33,7 @@ static UCHAR handshake_hash[16 + 20]; /* We concatenate MD5 and SHA-1 hashes int
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_finished_hash_generate PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -72,6 +72,9 @@ static UCHAR handshake_hash[16 + 20]; /* We concatenate MD5 and SHA-1 hashes int
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
+/* 08-02-2021 Timothy Stapko Modified comment(s), added */
+/* hash clone and cleanup, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_secure_tls_finished_hash_generate(NX_SECURE_TLS_SESSION *tls_session,
@@ -133,9 +136,9 @@ UINT hash_size = 0;
#endif /* NX_SECURE_ENABLE_DTLS */
{
/* Copy over the handshake hash state into scratch space to do the intermediate calculation. */
- NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */
+ NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */
/* Finalize the handshake message hash that we started at the beginning of the handshake. */
method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha256_method;
@@ -158,16 +161,20 @@ UINT hash_size = 0;
NX_NULL,
NX_NULL);
- if(status != NX_CRYPTO_SUCCESS)
- {
- return(status);
- }
}
else
{
- return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
+ status = NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE;
}
+ NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size);
+
+ if (status != NX_CRYPTO_SUCCESS)
+ {
+ return(status);
+ }
+
/* For TLS 1.2, the PRF is defined by the ciphersuite. However, if we are using an older ciphersuite,
* default to the TLS 1.2 default PRF, which uses SHA-256-HMAC. */
method_ptr = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_prf;
@@ -186,15 +193,11 @@ UINT hash_size = 0;
tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)
#endif /* NX_SECURE_ENABLE_DTLS */
{
- /* Copy over the handshake hash metadata into scratch metadata area to do the intermediate calculation. Copy SHA-1 in
- first, then MD5. */
- NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size); /* Use case of memcpy is verified. */
- NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch +
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size); /* Use case of memcpy is verified. */
+ /* Copy over the handshake hash metadata into scratch metadata area to do the intermediate calculation. */
+ NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch +
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size); /* Use case of memcpy is verified. */
/* Finalize the handshake message hashes that we started at the beginning of the handshake. */
method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_md5_method;
@@ -218,17 +221,23 @@ UINT hash_size = 0;
metadata_size,
NX_NULL,
NX_NULL);
-
- if(status != NX_CRYPTO_SUCCESS)
- {
- return(status);
- }
}
else
{
- return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
+ status = NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE;
+ }
+
+ NX_SECURE_HASH_CLONE_CLEANUP(metadata, metadata_size);
+
+ if (status != NX_CRYPTO_SUCCESS)
+ {
+ return(status);
}
+ NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size); /* Use case of memcpy is verified. */
+
method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method;
handler = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_handler;
metadata = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch;
@@ -251,14 +260,18 @@ UINT hash_size = 0;
NX_NULL,
NX_NULL);
- if(status != NX_CRYPTO_SUCCESS)
- {
- return(status);
- }
+
}
else
{
- return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
+ status = NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE;
+ }
+
+ NX_SECURE_HASH_CLONE_CLEANUP(metadata, metadata_size);
+
+ if (status != NX_CRYPTO_SUCCESS)
+ {
+ return(status);
}
/* TLS 1.0 and TLS 1.1 use the same PRF. */
diff --git a/nx_secure/src/nx_secure_tls_process_certificate_verify.c b/nx_secure/src/nx_secure_tls_process_certificate_verify.c
index fd701588..ce6826d6 100644
--- a/nx_secure/src/nx_secure_tls_process_certificate_verify.c
+++ b/nx_secure/src/nx_secure_tls_process_certificate_verify.c
@@ -39,7 +39,7 @@ static const UCHAR _NX_SECURE_OID_SHA256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_process_certificate_verify PORTABLE C */
-/* 6.1.6 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -88,6 +88,9 @@ static const UCHAR _NX_SECURE_OID_SHA256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09
/* 04-02-2021 Timothy Stapko Modified comment(s), */
/* updated X.509 return value, */
/* resulting in version 6.1.6 */
+/* 08-02-2021 Timothy Stapko Modified comment(s), added */
+/* hash clone and cleanup, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_secure_tls_process_certificate_verify(NX_SECURE_TLS_SESSION *tls_session,
@@ -356,7 +359,7 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey;
/* Generate a hash of all sent and received handshake messages to this point (not a Finished hash!). */
/* Copy over the handshake hash state into a local structure to do the intermediate calculation. */
- NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */
@@ -378,6 +381,10 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey;
tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size,
NX_NULL,
NX_NULL);
+ }
+
+ NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size);
if (status != NX_CRYPTO_SUCCESS)
{
@@ -385,8 +392,6 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey;
return(status);
}
}
-
- }
#endif
@@ -403,12 +408,8 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey;
/* Signature size is the size of SHA-1 (20) + MD5 (16). */
signature_length = 36;
- /* Copy over the handshake hash metadata into scratch metadata area to do the intermediate calculation. Copy SHA-1 in
- first, then MD5. */
- NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size); /* Use case of memcpy is verified. */
- NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch +
+ /* Copy over the handshake hash metadata into scratch metadata area to do the intermediate calculation. */
+ NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch +
tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size,
tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata,
tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size); /* Use case of memcpy is verified. */
@@ -432,13 +433,22 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey;
tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size,
NX_NULL,
NX_NULL);
+ }
+
+ NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch +
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size);
if (status != NX_CRYPTO_SUCCESS)
{
+
/* Something failed in the hash calculation. */
return(status);
}
- }
+
+ NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size); /* Use case of memcpy is verified. */
hash_method = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method;
if (hash_method -> nx_crypto_operation != NX_NULL)
@@ -458,8 +468,15 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey;
NX_NULL,
NX_NULL);
+
+ }
+
+ NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size);
+
if (status != NX_CRYPTO_SUCCESS)
{
+
/* Something failed in the hash calculation. */
#ifdef NX_SECURE_KEY_CLEAR
NX_SECURE_MEMSET(handshake_hash, 0, sizeof(handshake_hash));
@@ -467,7 +484,6 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey;
return(status);
}
}
- }
#endif
diff --git a/nx_secure/src/nx_secure_tls_process_clienthello_extensions.c b/nx_secure/src/nx_secure_tls_process_clienthello_extensions.c
index 1d3468de..c8cca207 100644
--- a/nx_secure/src/nx_secure_tls_process_clienthello_extensions.c
+++ b/nx_secure/src/nx_secure_tls_process_clienthello_extensions.c
@@ -1289,7 +1289,7 @@ VOID _nx_secure_tls_get_signature_algorithm_id(UINT signature_algorithm, USHORT
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_process_clienthello_psk_extension PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -1323,6 +1323,9 @@ VOID _nx_secure_tls_get_signature_algorithm_id(UINT signature_algorithm, USHORT
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
+/* 08-02-2021 Timothy Stapko Modified comment(s), added */
+/* hash clone and cleanup, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES)
@@ -1562,9 +1565,9 @@ NX_SECURE_TLS_PSK_STORE *psk_store;
{
/* Save the handshake hash state. */
- NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */
+ NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */
}
/* Hash the ClientHello, adding the TLS record header. */
@@ -1576,17 +1579,31 @@ NX_SECURE_TLS_PSK_STORE *psk_store;
/* Save the transcript hash for the ClientHello, which is used in generating the PSK binders. */
status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_CLIENTHELLO, NX_FALSE);
- if(status != NX_SUCCESS)
+ if (status != NX_SUCCESS)
{
+
+ if (tls_session -> nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_data_size)
+ {
+ NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size);
+ }
+
return(status);
}
/* Restore the original metadata(ClientHello1 and HelloRetryRequest) from scratch buffer. */
if (tls_session -> nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_data_size)
{
- NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */
+
+ NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size);
+
+ NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */
+
+ NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size);
}
/* Generate the binder for our selected PSK. */
diff --git a/nx_secure/src/nx_secure_tls_process_record.c b/nx_secure/src/nx_secure_tls_process_record.c
index 62af893c..aaf99aaf 100644
--- a/nx_secure/src/nx_secure_tls_process_record.c
+++ b/nx_secure/src/nx_secure_tls_process_record.c
@@ -31,7 +31,7 @@ static VOID _nx_secure_tls_packet_trim(NX_PACKET *packet_ptr);
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_process_record PORTABLE C */
-/* 6.1.4 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -88,6 +88,9 @@ static VOID _nx_secure_tls_packet_trim(NX_PACKET *packet_ptr);
/* support for fragmented TLS */
/* Handshake messages, */
/* resulting in version 6.1.4 */
+/* 08-02-2021 Timothy Stapko Modified comment(s), checked */
+/* TLS state before processing,*/
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_secure_tls_process_record(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *packet_ptr,
@@ -130,6 +133,18 @@ NX_PACKET *decrypted_packet;
status = NX_CONTINUE;
*bytes_processed = 0;
+ /* Make sure the TLS socket is not closed. */
+ if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_NONE)
+ {
+
+ /* Session already closed. Release the packet. */
+ if (packet_ptr != NX_NULL)
+ {
+ nx_packet_release(packet_ptr);
+ }
+ return(NX_SECURE_TLS_INVALID_STATE);
+ }
+
/* Process the packet. */
if (packet_ptr != NX_NULL)
{
diff --git a/nx_secure/src/nx_secure_tls_record_payload_encrypt.c b/nx_secure/src/nx_secure_tls_record_payload_encrypt.c
index 7552ea87..f0522569 100644
--- a/nx_secure/src/nx_secure_tls_record_payload_encrypt.c
+++ b/nx_secure/src/nx_secure_tls_record_payload_encrypt.c
@@ -36,7 +36,7 @@ UCHAR _nx_secure_tls_record_block_buffer[NX_SECURE_TLS_MAX_CIPHER_BLOCK_SIZE];
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_record_payload_encrypt PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -77,6 +77,11 @@ UCHAR _nx_secure_tls_record_block_buffer[NX_SECURE_TLS_MAX_CIPHER_BLOCK_SIZE];
/* fixed data copy in chained */
/* packet, */
/* resulting in version 6.1 */
+/* 08-02-2021 Timothy Stapko Modified comment(s), called */
+/* NX_CRYPTO_ENCRYPT_CALCULATE */
+/* to finalize the encryption */
+/* of this record, resulting */
+/* in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_secure_tls_record_payload_encrypt(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *send_packet,
@@ -96,6 +101,8 @@ ULONG remainder_length;
UINT data_offset = 0;
VOID *handler = NX_NULL;
VOID *crypto_method_metadata;
+UINT icv_size = 0;
+UCHAR *icv_ptr = NX_NULL;
if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL)
{
@@ -320,17 +327,22 @@ VOID *crypto_method_metadata;
current_packet = current_packet -> nx_packet_next;
} while (current_packet != NX_NULL);
-#ifdef NX_SECURE_ENABLE_AEAD_CIPHER
if (session_cipher_method -> nx_crypto_ICV_size_in_bits > 0)
{
+
+ /* Get icv_size and icv_ptr for AEAD cipher */
if ((session_cipher_method -> nx_crypto_ICV_size_in_bits >> 3) >
sizeof(_nx_secure_tls_record_block_buffer))
{
return(NX_SIZE_ERROR);
}
- /* Get TAG. */
- status = session_cipher_method -> nx_crypto_operation(NX_CRYPTO_ENCRYPT_CALCULATE,
+ icv_size = session_cipher_method -> nx_crypto_ICV_size_in_bits >> 3;
+ icv_ptr = _nx_secure_tls_record_block_buffer;
+ }
+
+ /* Call NX_CRYPTO_ENCRYPT_CALCULATE to finalize the encryption of this record. */
+ status = session_cipher_method -> nx_crypto_operation(NX_CRYPTO_ENCRYPT_CALCULATE,
handler,
(NX_CRYPTO_METHOD*)session_cipher_method,
NX_NULL,
@@ -338,26 +350,28 @@ VOID *crypto_method_metadata;
NX_NULL,
0,
NX_NULL,
- _nx_secure_tls_record_block_buffer,
- (session_cipher_method -> nx_crypto_ICV_size_in_bits >> 3),
+ icv_ptr,
+ icv_size,
crypto_method_metadata,
tls_session -> nx_secure_session_cipher_metadata_size,
NX_NULL, NX_NULL);
- if (status)
- {
- return(status);
- }
+ if (status)
+ {
+ return(status);
+ }
- status = nx_packet_data_append(send_packet, _nx_secure_tls_record_block_buffer,
- (session_cipher_method -> nx_crypto_ICV_size_in_bits >> 3),
- tls_session -> nx_secure_tls_packet_pool, NX_WAIT_FOREVER);
+ if (icv_ptr && icv_size)
+ {
+
+ /* Append data for AEAD cipher */
+ status = nx_packet_data_append(send_packet, icv_ptr, icv_size,
+ tls_session -> nx_secure_tls_packet_pool, NX_WAIT_FOREVER);
if (status)
{
return(status);
}
}
-#endif /* NX_SECURE_ENABLE_AEAD_CIPHER */
-
+
return(NX_SUCCESS);
}
diff --git a/nx_secure/src/nx_secure_tls_send_certificate_verify.c b/nx_secure/src/nx_secure_tls_send_certificate_verify.c
index fd60b31b..02341cb1 100644
--- a/nx_secure/src/nx_secure_tls_send_certificate_verify.c
+++ b/nx_secure/src/nx_secure_tls_send_certificate_verify.c
@@ -40,7 +40,7 @@ static const UCHAR _NX_SECURE_OID_SHA256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_send_certificate_verify PORTABLE C */
-/* 6.1.7 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -95,6 +95,9 @@ static const UCHAR _NX_SECURE_OID_SHA256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09
/* supported hardware EC */
/* private key, */
/* resulting in version 6.1.7 */
+/* 08-02-2021 Timothy Stapko Modified comment(s), added */
+/* hash clone and cleanup, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_secure_tls_send_certificate_verify(NX_SECURE_TLS_SESSION *tls_session,
@@ -381,7 +384,7 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output;
/* Generate a hash of all sent and received handshake messages to this point (not a Finished hash!). */
/* Copy over the handshake hash state into a local structure to do the intermediate calculation. */
- NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */
@@ -405,7 +408,10 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output;
NX_NULL);
}
- if(status != NX_CRYPTO_SUCCESS)
+ NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size);
+
+ if (status != NX_CRYPTO_SUCCESS)
{
return(status);
}
@@ -423,12 +429,8 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output;
tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)
#endif /* NX_SECURE_ENABLE_DTLS */
{
- /* Copy over the handshake hash metadata into scratch metadata area to do the intermediate calculation. Copy SHA-1 in
- first, then MD5. */
- NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size); /* Use case of memcpy is verified. */
- NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch +
+ /* Copy over the handshake hash metadata into scratch metadata area to do the intermediate calculation. */
+ NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch +
tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size,
tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata,
tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size); /* Use case of memcpy is verified. */
@@ -453,11 +455,20 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output;
NX_NULL,
NX_NULL);
- if(status != NX_CRYPTO_SUCCESS)
+ }
+
+ NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch +
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size);
+
+ if (status != NX_CRYPTO_SUCCESS)
{
return(status);
}
- }
+
+ NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size); /* Use case of memcpy is verified. */
hash_method = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method;
if (hash_method -> nx_crypto_operation != NX_NULL)
@@ -477,12 +488,16 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output;
NX_NULL,
NX_NULL);
- if(status != NX_CRYPTO_SUCCESS)
+ }
+
+ NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size);
+
+ if (status != NX_CRYPTO_SUCCESS)
{
return(status);
}
}
- }
#endif
/* Make sure we found a supported version (essentially an assertion check). */
diff --git a/nx_secure/src/nx_secure_tls_send_clienthello_extensions.c b/nx_secure/src/nx_secure_tls_send_clienthello_extensions.c
index 8184f830..2d6d809c 100644
--- a/nx_secure/src/nx_secure_tls_send_clienthello_extensions.c
+++ b/nx_secure/src/nx_secure_tls_send_clienthello_extensions.c
@@ -826,7 +826,7 @@ USHORT named_curve;
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_send_clienthello_psk_extension PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -865,6 +865,9 @@ USHORT named_curve;
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
+/* 08-02-2021 Timothy Stapko Modified comment(s), added */
+/* hash clone and cleanup, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
@@ -1071,9 +1074,9 @@ NX_SECURE_TLS_PSK_STORE *psk_store;
{
/* Save the handshake hash state. */
- NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */
+ NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */
}
/* Hash the ClientHello up to its current point. */
@@ -1087,17 +1090,30 @@ NX_SECURE_TLS_PSK_STORE *psk_store;
/* Save the transcript hash for the ClientHello, which is used in generating the PSK binders. */
status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_CLIENTHELLO, NX_FALSE);
- if(status != NX_SUCCESS)
+ if (status != NX_SUCCESS)
{
+
+ if (tls_session -> nx_secure_tls_client_state != NX_SECURE_TLS_CLIENT_STATE_IDLE)
+ {
+ NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size);
+ }
+
return(status);
}
/* Restore the original metadata(ClientHello1 and HelloRetryRequest) from scratch buffer. */
if (tls_session -> nx_secure_tls_client_state != NX_SECURE_TLS_CLIENT_STATE_IDLE)
{
- NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
- tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */
+ NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size);
+
+ NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */
+
+ NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
+ tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size);
}
/* Loop through all IDs and set the binders accordingly. */
diff --git a/nx_secure/src/nx_secure_tls_send_record.c b/nx_secure/src/nx_secure_tls_send_record.c
index 4ef47b86..c364cfb6 100644
--- a/nx_secure/src/nx_secure_tls_send_record.c
+++ b/nx_secure/src/nx_secure_tls_send_record.c
@@ -29,7 +29,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_send_record PORTABLE C */
-/* 6.1.7 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -86,6 +86,10 @@
/* resulting in version 6.1 */
/* 06-02-2021 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1.7 */
+/* 08-02-2021 Timothy Stapko Modified comment(s), */
+/* used wait forever on */
+/* transmission mutex, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_secure_tls_send_record(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *send_packet,
@@ -118,7 +122,7 @@ NX_PACKET *current_packet;
tx_mutex_put(&_nx_secure_tls_protection);
/* Get transmit mutex first. */
- status = tx_mutex_get(&(tls_session -> nx_secure_tls_session_transmit_mutex), wait_option);
+ status = tx_mutex_get(&(tls_session -> nx_secure_tls_session_transmit_mutex), TX_WAIT_FOREVER);
tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
diff --git a/nx_secure/src/nx_secure_tls_session_keys_set.c b/nx_secure/src/nx_secure_tls_session_keys_set.c
index a632cf8f..2f7cafea 100644
--- a/nx_secure/src/nx_secure_tls_session_keys_set.c
+++ b/nx_secure/src/nx_secure_tls_session_keys_set.c
@@ -30,7 +30,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_session_keys_set PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -76,6 +76,9 @@
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
+/* 08-02-2021 Timothy Stapko Modified comment(s), added */
+/* cleanup for session cipher, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
#define NX_SECURE_SOURCE_CODE
@@ -223,15 +226,39 @@ const NX_CRYPTO_METHOD *session_cipher_method = NX_NULL;
/* Set client write key. */
if (is_client)
{
+ if (tls_session -> nx_secure_tls_session_cipher_client_initialized && session_cipher_method -> nx_crypto_cleanup)
+ {
+ status = session_cipher_method -> nx_crypto_cleanup(tls_session -> nx_secure_session_cipher_metadata_area_client);
+ if (status != NX_CRYPTO_SUCCESS)
+ {
+ return(status);
+ }
+
+ tls_session -> nx_secure_tls_session_cipher_client_initialized = 0;
+ }
+
status = session_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_cipher_method,
tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_write_key,
session_cipher_method -> nx_crypto_key_size_in_bits,
&tls_session -> nx_secure_session_cipher_handler_client,
tls_session -> nx_secure_session_cipher_metadata_area_client,
tls_session -> nx_secure_session_cipher_metadata_size);
+
+ tls_session -> nx_secure_tls_session_cipher_client_initialized = 1;
}
else
{
+ if (tls_session -> nx_secure_tls_session_cipher_server_initialized && session_cipher_method -> nx_crypto_cleanup)
+ {
+ status = session_cipher_method -> nx_crypto_cleanup(tls_session -> nx_secure_session_cipher_metadata_area_server);
+ if (status != NX_CRYPTO_SUCCESS)
+ {
+ return(status);
+ }
+
+ tls_session -> nx_secure_tls_session_cipher_server_initialized = 0;
+ }
+
/* Set server write key. */
status = session_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_cipher_method,
tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_write_key,
@@ -239,6 +266,8 @@ const NX_CRYPTO_METHOD *session_cipher_method = NX_NULL;
&tls_session -> nx_secure_session_cipher_handler_server,
tls_session -> nx_secure_session_cipher_metadata_area_server,
tls_session -> nx_secure_session_cipher_metadata_size);
+
+ tls_session -> nx_secure_tls_session_cipher_server_initialized = 1;
}
if(status != NX_CRYPTO_SUCCESS)
{
diff --git a/nx_secure/src/nx_secure_tls_session_renegotiate.c b/nx_secure/src/nx_secure_tls_session_renegotiate.c
index a8d935ef..cc4c0d98 100644
--- a/nx_secure/src/nx_secure_tls_session_renegotiate.c
+++ b/nx_secure/src/nx_secure_tls_session_renegotiate.c
@@ -29,7 +29,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_session_renegotiate PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -87,13 +87,16 @@
/* supported chained packet, */
/* fixed renegotiation bug, */
/* resulting in version 6.1 */
+/* 08-02-2021 Timothy Stapko Modified comment(s), */
+/* fixed packet leak bug, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
#ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION
UINT _nx_secure_tls_session_renegotiate(NX_SECURE_TLS_SESSION *tls_session, UINT wait_option)
{
UINT status = NX_NOT_SUCCESSFUL;
-NX_PACKET *incoming_packet;
+NX_PACKET *incoming_packet = NX_NULL;
NX_PACKET *send_packet;
/* Get the protection. */
@@ -196,6 +199,11 @@ NX_PACKET *send_packet;
break;
}
}
+
+ if (incoming_packet != NX_NULL)
+ {
+ nx_secure_tls_packet_release(incoming_packet);
+ }
}
#endif
@@ -257,6 +265,11 @@ NX_PACKET *send_packet;
break;
}
}
+
+ if (incoming_packet != NX_NULL)
+ {
+ nx_secure_tls_packet_release(incoming_packet);
+ }
}
#endif
diff --git a/nx_secure/src/nx_secure_tls_session_reset.c b/nx_secure/src/nx_secure_tls_session_reset.c
index 5446592e..7dee30bc 100644
--- a/nx_secure/src/nx_secure_tls_session_reset.c
+++ b/nx_secure/src/nx_secure_tls_session_reset.c
@@ -29,7 +29,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_session_reset PORTABLE C */
-/* 6.1 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -71,6 +71,9 @@
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* fixed renegotiation bug, */
/* resulting in version 6.1 */
+/* 08-02-2021 Timothy Stapko Modified comment(s), added */
+/* cleanup for session cipher, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_secure_tls_session_reset(NX_SECURE_TLS_SESSION *session_ptr)
@@ -125,6 +128,8 @@ UINT temp_status;
/* Sessions are not active when we start the socket. */
session_ptr -> nx_secure_tls_remote_session_active = 0;
session_ptr -> nx_secure_tls_local_session_active = 0;
+ session_ptr -> nx_secure_tls_session_cipher_client_initialized = 0;
+ session_ptr -> nx_secure_tls_session_cipher_server_initialized = 0;
/* Set the current ciphersuite to TLS_NULL_WITH_NULL_NULL which is the
* specified ciphersuite for the handshake (pre-change cipher spec). */
diff --git a/nx_secure/src/nx_secure_x509_crl_revocation_check.c b/nx_secure/src/nx_secure_x509_crl_revocation_check.c
index 269f7da2..fd2ab173 100644
--- a/nx_secure/src/nx_secure_x509_crl_revocation_check.c
+++ b/nx_secure/src/nx_secure_x509_crl_revocation_check.c
@@ -35,7 +35,7 @@ static UINT _nx_secure_x509_crl_parse_entry(const UCHAR *buffer, ULONG length, U
/* FUNCTION RELEASE */
/* */
/* _nx_secure_x509_crl_revocation_check PORTABLE C */
-/* 6.1.6 */
+/* 6.1.8 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -90,6 +90,9 @@ static UINT _nx_secure_x509_crl_parse_entry(const UCHAR *buffer, ULONG length, U
/* 04-02-2021 Timothy Stapko Modified comment(s), */
/* removed dependency on TLS, */
/* resulting in version 6.1.6 */
+/* 08-02-2021 Timothy Stapko Modified comment(s), */
+/* fixed compiler warnings, */
+/* resulting in version 6.1.8 */
/* */
/**************************************************************************/
UINT _nx_secure_x509_crl_revocation_check(const UCHAR *crl_data, UINT crl_length,
@@ -106,7 +109,7 @@ UINT length;
const UCHAR *current_buffer;
NX_SECURE_X509_CERT *issuer_certificate;
UINT issuer_location;
-const UCHAR *serial_number;
+const UCHAR *serial_number = NX_NULL;
UINT serial_number_length;
NX_SECURE_MEMSET(&crl, 0, sizeof(NX_SECURE_X509_CRL));
diff --git a/utility/CMakeLists.txt b/utility/CMakeLists.txt
new file mode 100644
index 00000000..99f6e16e
--- /dev/null
+++ b/utility/CMakeLists.txt
@@ -0,0 +1,16 @@
+# Each protocol handler is listed below. If you want
+# to disable some / all of these, comment out the block(s) in question
+
+if(NXD_ENABLE_FILE_SERVERS)
+ target_sources(${PROJECT_NAME}
+ PRIVATE
+ # {{BEGIN_TARGET_SOURCES}}
+ ${CMAKE_CURRENT_LIST_DIR}/iperf/nx_iperf.c
+
+ # {{END_TARGET_SOURCES}}
+ )
+
+ target_include_directories(${PROJECT_NAME} PUBLIC
+ ${CMAKE_CURRENT_LIST_DIR}/iperf
+ )
+endif() \ No newline at end of file
diff --git a/utility/iperf/demo_iperf.c b/utility/iperf/demo_iperf.c
new file mode 100644
index 00000000..b26fd7d9
--- /dev/null
+++ b/utility/iperf/demo_iperf.c
@@ -0,0 +1,167 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX IPerf stack Component */
+/** */
+/** This is a small demo of the high-performance NetX IPerf stack. */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+#include "tx_api.h"
+#include "nx_api.h"
+
+/* Define demo stack size. */
+#define NX_PACKET_POOL_SIZE ((1536 + sizeof(NX_PACKET)) * 30)
+#define DEMO_STACK_SIZE 2048
+#define HTTP_STACK_SIZE 2048
+#define IPERF_STACK_SIZE 2048
+
+/* Define the ThreadX and NetX object control blocks... */
+TX_THREAD thread_0;
+NX_PACKET_POOL pool_0;
+NX_IP ip_0;
+
+UCHAR *pointer;
+UCHAR *http_stack;
+UCHAR *iperf_stack;
+#ifdef FEATURE_NX_IPV6
+NXD_ADDRESS ipv6_address;
+#endif
+
+/* Define the counters used in the demo application... */
+ULONG error_counter;
+
+/* Define thread prototypes. */
+VOID thread_0_entry(ULONG thread_input);
+extern VOID nx_iperf_entry(NX_PACKET_POOL *pool_ptr, NX_IP *ip_ptr, UCHAR* http_stack, ULONG http_stack_size, UCHAR *iperf_stack, ULONG iperf_stack_size);
+
+/***** Substitute your ethernet driver entry function here *********/
+extern VOID _nx_ram_network_driver(NX_IP_DRIVER*);
+
+
+/* Define main entry point. */
+int main()
+{
+
+ /* Enter the ThreadX kernel. */
+ tx_kernel_enter();
+}
+
+
+/* Define what the initial system looks like. */
+void tx_application_define(void *first_unused_memory)
+{
+
+UINT status;
+
+ /* Setup the working pointer. */
+ pointer = (UCHAR *) first_unused_memory;
+
+ /* Initialize the NetX system. */
+ nx_system_initialize();
+
+ /* Create a packet pool. */
+ status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool",
+ (1536 + sizeof(NX_PACKET)),
+ pointer, NX_PACKET_POOL_SIZE);
+ pointer = pointer + NX_PACKET_POOL_SIZE;
+
+ /* Check for packet pool create errors. */
+ if (status)
+ error_counter++;
+
+ /* Create an IP instance. */
+ status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(192, 168, 100, 18), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
+ pointer, 2048, 1);
+ pointer = pointer + 2048;
+
+ /* Check for IP create errors. */
+ if (status)
+ error_counter++;
+
+ /* Enable ARP and supply ARP cache memory for IP Instance 0. */
+ status = nx_arp_enable(&ip_0, (void *) pointer, 1024);
+ pointer = pointer + 1024;
+
+ /* Check for ARP enable errors. */
+ if (status)
+ error_counter++;
+
+ /* Enable ICMP */
+ status = nx_icmp_enable(&ip_0);
+
+ /* Check for ICMP enable errors. */
+ if(status)
+ error_counter++;
+
+ /* Enable UDP traffic. */
+ status = nx_udp_enable(&ip_0);
+
+ /* Check for UDP enable errors. */
+ if (status)
+ error_counter++;
+
+ /* Enable TCP traffic. */
+ status = nx_tcp_enable(&ip_0);
+
+ /* Check for TCP enable errors. */
+ if (status)
+ error_counter++;
+
+ /* Create the main thread. */
+ tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
+ pointer, DEMO_STACK_SIZE,
+ 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
+ pointer = pointer + DEMO_STACK_SIZE;
+
+#ifdef FEATURE_NX_IPV6
+ /* Set up the IPv6 address here. */
+ ipv6_address.nxd_ip_address.v6[3] = 0x3;
+ ipv6_address.nxd_ip_address.v6[2] = 0x0;
+ ipv6_address.nxd_ip_address.v6[1] = 0x0;
+ ipv6_address.nxd_ip_address.v6[0] = 0xfe800000;
+ ipv6_address.nxd_ip_version = NX_IP_VERSION_V6;
+
+ /* Enable ICMPv6 services. */
+ status = nxd_icmp_enable(&ip_0);
+ if (status)
+ error_counter++;
+
+ /* Enable IPv6 services. */
+ status = nxd_ipv6_enable(&ip_0);
+ if (status)
+ error_counter++;
+
+ status = nxd_ipv6_address_set(&ip_0, 0, &ipv6_address, 10, NX_NULL);
+ if (status)
+ error_counter++;
+#endif
+}
+
+/* Define the test threads. */
+void thread_0_entry(ULONG thread_input)
+{
+#ifdef FEATURE_NX_IPV6
+ tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
+#endif
+
+ /* Set the HTTP stack and IPerf stack. */
+ http_stack = pointer;
+ pointer += HTTP_STACK_SIZE;
+ iperf_stack = pointer;
+ pointer += IPERF_STACK_SIZE;
+
+ /* Call entry function to start iperf test. */
+ nx_iperf_entry(&pool_0, &ip_0, http_stack, HTTP_STACK_SIZE, iperf_stack, IPERF_STACK_SIZE);
+} \ No newline at end of file
diff --git a/utility/iperf/nx_iperf.c b/utility/iperf/nx_iperf.c
new file mode 100644
index 00000000..f7abab96
--- /dev/null
+++ b/utility/iperf/nx_iperf.c
@@ -0,0 +1,2446 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX Utility */
+/** */
+/** NetX Duo IPerf Test Program */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#include "tx_api.h"
+#include "nx_api.h"
+#include "nx_iperf.h"
+#ifndef NX_WEB_HTTP_NO_FILEX
+#include "fx_api.h"
+#else
+#include "filex_stub.h"
+#endif
+
+#include "nx_web_http_server.h"
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+#include "tx_execution_profile.h"
+#endif /* TX_EXECUTION_PROFILE_ENABLE */
+
+/* Define the counters used in the demo application... */
+
+NX_WEB_HTTP_SERVER nx_iperf_web_server;
+FX_MEDIA nx_iperf_ram_disk;
+NX_IP *nx_iperf_test_ip;
+NX_PACKET_POOL *nx_iperf_test_pool;
+UCHAR *nx_iperf_stack_area;
+ULONG nx_iperf_stack_area_size;
+ULONG nx_iperf_test_error_counter;
+ctrl_info nx_iperf_ctrl_info;
+
+static NXD_ADDRESS udp_tx_ip_address;
+static NXD_ADDRESS tcp_tx_ip_address;
+
+static ULONG udp_tx_port = NX_IPERF_DESTINATION_PORT;
+static ULONG tcp_tx_port = NX_IPERF_DESTINATION_PORT;
+
+static UINT udp_tx_packet_size = 1470;
+static UINT udp_tx_test_time = 10;
+static UINT udp_rx_test_time = 10;
+static UINT tcp_tx_test_time = 10;
+static UINT tcp_rx_test_time = 10;
+
+static ULONG error_counter;
+
+NX_TCP_SOCKET tcp_server_socket;
+NX_TCP_SOCKET tcp_client_socket;
+NX_UDP_SOCKET udp_server_socket;
+NX_UDP_SOCKET udp_client_socket;
+ULONG thread_tcp_rx_counter;
+ULONG thread_tcp_tx_counter;
+ULONG thread_udp_rx_counter;
+ULONG thread_udp_tx_counter;
+static TX_THREAD thread_tcp_rx_iperf;
+static TX_THREAD thread_tcp_tx_iperf;
+static TX_THREAD thread_udp_rx_iperf;
+static TX_THREAD thread_udp_tx_iperf;
+
+extern ULONG _tx_timer_system_clock;
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+EXECUTION_TIME thread_time = 0;
+EXECUTION_TIME isr_time = 0;
+EXECUTION_TIME idle_time = 0;
+extern TX_THREAD *_tx_thread_created_ptr;
+#endif
+
+
+static void nx_iperf_send_image(NX_WEB_HTTP_SERVER *server_ptr, UCHAR *img, UINT imgsize);
+static void nx_iperf_print_tcp_rx_results(NX_WEB_HTTP_SERVER *server_ptr, NXD_ADDRESS *peer_ip_address);
+static void nx_iperf_print_tcp_tx_results(NX_WEB_HTTP_SERVER *server_ptr, NXD_ADDRESS *peer_ip_address);
+static void nx_iperf_print_udp_rx_results(NX_WEB_HTTP_SERVER *server_ptr, NXD_ADDRESS *peer_ip_address);
+static void nx_iperf_print_udp_tx_results(NX_WEB_HTTP_SERVER *server_ptr, NXD_ADDRESS *peer_ip_address);
+
+void nx_iperf_tcp_rx_test(UCHAR *, ULONG);
+void nx_iperf_tcp_tx_test(UCHAR *, ULONG);
+void nx_iperf_udp_rx_test(UCHAR *, ULONG);
+void nx_iperf_udp_tx_test(UCHAR *, ULONG);
+
+void nx_iperf_tcp_rx_cleanup(void);
+void nx_iperf_tcp_tx_cleanup(void);
+void nx_iperf_udp_rx_cleanup(void);
+void nx_iperf_udp_tx_cleanup(void);
+
+char *nx_iperf_get_ip_addr_string(NXD_ADDRESS *ip_address, UINT *string_length);
+void nx_iperf_test_info_parse(ctrl_info *iperf_ctrlInfo_ptr);
+void nx_iperf_tcp_rx_connect_received(NX_TCP_SOCKET *socket_ptr, UINT port);
+void nx_iperf_tcp_rx_disconnect_received(NX_TCP_SOCKET *socket_ptr);
+UINT nx_iperf_authentication_check(struct NX_WEB_HTTP_SERVER_STRUCT *server_ptr, UINT request_type, CHAR *resource, CHAR **name, CHAR **password, CHAR **realm);
+UINT nx_iperf_get_notify(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type, CHAR *resource, NX_PACKET *packet_ptr);
+void nx_iperf_entry(NX_PACKET_POOL *pool_ptr, NX_IP *ip_ptr, UCHAR *http_stack, ULONG http_stack_size, UCHAR *iperf_stack, ULONG iperf_stack_size);
+
+void nx_iperf_thread_tcp_rx_entry(ULONG thread_input);
+void nx_iperf_thread_tcp_tx_entry(ULONG thread_input);
+void nx_iperf_thread_udp_tx_entry(ULONG thread_input);
+void nx_iperf_thread_udp_rx_entry(ULONG thread_input);
+
+void nx_iperf_entry(NX_PACKET_POOL *pool_ptr, NX_IP *ip_ptr, UCHAR *http_stack, ULONG http_stack_size, UCHAR *iperf_stack, ULONG iperf_stack_size)
+{
+UINT status;
+
+ /* Create the HTTP Server. */
+ status = nx_web_http_server_create(&nx_iperf_web_server, "My HTTP Server", ip_ptr, NX_WEB_HTTP_SERVER_PORT, &nx_iperf_ram_disk, http_stack, http_stack_size, pool_ptr, nx_iperf_authentication_check, nx_iperf_get_notify);
+
+ /* Check the status. */
+ if (status)
+ {
+
+ /* Update the error counter and return. */
+ nx_iperf_test_error_counter++;
+ return;
+ }
+
+ /* Set the iPerf Stack and Size. */
+ nx_iperf_stack_area = iperf_stack;
+ nx_iperf_stack_area_size = iperf_stack_size;
+
+ /* Set the IP instance and Packet Pool. */
+ nx_iperf_test_ip = ip_ptr;
+ nx_iperf_test_pool = pool_ptr;
+
+ /* Start the HTTP Server. */
+ status = nx_web_http_server_start(&nx_iperf_web_server);
+
+ /* Check the status. */
+ if (status)
+ {
+
+ /* Update the error counter and return. */
+ nx_iperf_test_error_counter++;
+ return;
+ }
+}
+
+UINT nx_iperf_authentication_check(struct NX_WEB_HTTP_SERVER_STRUCT *server_ptr, UINT request_type, CHAR *resource, CHAR **name, CHAR **password, CHAR **realm)
+{
+
+
+#ifdef NX_IPERF_AUTH_ENABLE
+
+ NX_PARAMETER_NOT_USED(server_ptr);
+ NX_PARAMETER_NOT_USED(request_type);
+ NX_PARAMETER_NOT_USED(resource);
+ *name = "PlaceholderName";
+ *password = "PlaceholderPassword";
+ *realm = "test.htm";
+
+ return(NX_WEB_HTTP_BASIC_AUTHENTICATE);
+#else
+ NX_PARAMETER_NOT_USED(server_ptr);
+ NX_PARAMETER_NOT_USED(request_type);
+ NX_PARAMETER_NOT_USED(resource);
+ NX_PARAMETER_NOT_USED(name);
+ NX_PARAMETER_NOT_USED(password);
+ NX_PARAMETER_NOT_USED(realm);
+
+ return(NX_SUCCESS);
+#endif
+}
+
+static CHAR device_ip_addr_string[40];
+char *nx_iperf_get_ip_addr_string(NXD_ADDRESS *ip_address, UINT *string_length)
+{
+UINT length = 0;
+#ifdef FEATURE_NX_IPV6
+UINT i;
+#endif
+
+ memset(device_ip_addr_string, 0, sizeof(device_ip_addr_string));
+
+#ifdef FEATURE_NX_IPV6
+ if (ip_address -> nxd_ip_version == NX_IP_VERSION_V6)
+ {
+ for (i = 0; i < 4; i ++)
+ {
+ length += _nx_utility_uint_to_string((UINT)ip_address -> nxd_ip_address.v6[i] >> 16, 16, &device_ip_addr_string[length], sizeof(device_ip_addr_string) - length);
+ device_ip_addr_string[length++] = ':';
+ length += _nx_utility_uint_to_string((UINT)ip_address -> nxd_ip_address.v6[i] & 0xFFFF, 16, &device_ip_addr_string[length], sizeof(device_ip_addr_string) - length);
+ if (i != 3)
+ {
+ device_ip_addr_string[length++] = ':';
+ }
+ }
+ }
+ else
+#endif
+ {
+#ifndef NX_DISABLE_IPV4
+ length = _nx_utility_uint_to_string(ip_address -> nxd_ip_address.v4 >> 24, 10, device_ip_addr_string, sizeof(device_ip_addr_string) - length);
+ device_ip_addr_string[length++] = '.';
+ length += _nx_utility_uint_to_string(((ip_address -> nxd_ip_address.v4 >> 16) & 0xFF), 10, &device_ip_addr_string[length], sizeof(device_ip_addr_string) - length);
+ device_ip_addr_string[length++] = '.';
+ length += _nx_utility_uint_to_string(((ip_address -> nxd_ip_address.v4 >> 8) & 0xFF), 10, &device_ip_addr_string[length], sizeof(device_ip_addr_string) - length);
+ device_ip_addr_string[length++] = '.';
+ length += _nx_utility_uint_to_string((ip_address -> nxd_ip_address.v4 & 0xFF), 10, &device_ip_addr_string[length], sizeof(device_ip_addr_string) - length);
+#endif
+ }
+
+ *string_length = length;
+ return device_ip_addr_string;
+}
+
+/* This function takes the token/value pair, and stores the information in the ctrl_info_ptr. */
+/* For example, a token/value pair can be: "TestType"="TC_Rx", and the ctrl_info_ptr stores the information. */
+static void nx_iperf_check_token_value(char *token, char *value_ptr, ctrl_info *ctrl_info_ptr)
+{
+UINT val;
+UINT i;
+UINT token_length = 0;
+UINT value_length = 0;
+UINT status;
+
+ /* Check string length of token. */
+ status = _nx_utility_string_length_check(token, &token_length, NX_MAX_STRING_LENGTH);
+ if (status)
+ {
+ return;
+ }
+
+ /* Check string length of value. */
+ if (value_ptr)
+ {
+ status = _nx_utility_string_length_check(value_ptr, &value_length, NX_MAX_STRING_LENGTH);
+ if (status)
+ {
+ return;
+ }
+ }
+
+ /* Check for name. */
+ if ((token_length == sizeof("TestType") - 1 ) &&
+ (memcmp(token, "TestType", token_length) == 0))
+ {
+ /* Check for value. */
+ ctrl_info_ptr -> ctrl_sign = UNKNOWN_TEST;
+ if (value_ptr)
+ {
+ if ((value_length == sizeof(TCP_Rx) - 1 ) &&
+ (memcmp(value_ptr, TCP_Rx, value_length) == 0))
+ {
+ ctrl_info_ptr -> ctrl_sign = TCP_RX_START;
+ }
+ else if ((value_length == sizeof(TCP_Tx) - 1 ) &&
+ (memcmp(value_ptr, TCP_Tx, value_length) == 0))
+ {
+ ctrl_info_ptr -> ctrl_sign = TCP_TX_START;
+ }
+ else if ((value_length == sizeof(UDP_Rx) - 1 ) &&
+ (memcmp(value_ptr, UDP_Rx, value_length) == 0))
+ {
+ ctrl_info_ptr -> ctrl_sign = UDP_RX_START;
+ }
+ else if ((value_length == sizeof(UDP_Tx) - 1 ) &&
+ (memcmp(value_ptr, UDP_Tx, value_length) == 0))
+ {
+ ctrl_info_ptr -> ctrl_sign = UDP_TX_START;
+ }
+ }
+ }
+ else if ((token_length == (sizeof("ip") - 1)) &&
+ (memcmp(token, "ip", token_length) == 0))
+ {
+ char *ptr = value_ptr;
+ int colon_sum, colon_count;
+ ctrl_info_ptr -> ip = 0;
+ val = 0;
+ colon_sum = 0;
+ colon_count = 0;
+ if (value_ptr == 0)
+ {
+ ctrl_info_ptr -> version = NX_IP_VERSION_V4;
+ }
+ while (ptr && (*ptr != 0))
+ {
+ if (*ptr == '.')
+ {
+ ctrl_info_ptr -> version = NX_IP_VERSION_V4;
+ while (value_ptr && (*value_ptr != 0))
+ {
+ if (*value_ptr == '.')
+ {
+ ctrl_info_ptr -> ip = (ctrl_info_ptr -> ip << 8) + val;
+ val = 0;
+ }
+ else
+ {
+ val = val * 10 + ((UINT)(*value_ptr - '0'));
+ }
+ value_ptr++;
+ }
+ ctrl_info_ptr -> ip = (ctrl_info_ptr -> ip << 8) + val;
+ break;
+ }
+ else if (*ptr == '%')
+ {
+ if ((*(++ptr) == '3') && (*(++ptr) == 'A'))
+ {
+ ctrl_info_ptr -> version = NX_IP_VERSION_V6;
+ colon_sum++;
+ }
+ }
+ ptr++;
+ }
+ while (value_ptr && (*value_ptr != 0) && (colon_sum != 0))
+ {
+ if (*value_ptr == '%')
+ {
+ if ((*(++value_ptr) == '3') && (*(++value_ptr) == 'A'))
+ {
+ ctrl_info_ptr -> ipv6[colon_count / 2] = (ctrl_info_ptr -> ipv6[colon_count / 2] << 16) + val;
+ colon_count++;
+
+ if (*(value_ptr + 1) == '%')
+ {
+ value_ptr++;
+ if ((*(++value_ptr) == '3') && (*(++value_ptr) == 'A'))
+ {
+ for (i = 0; i <= (UINT)(7 - colon_sum); i++)
+ {
+ ctrl_info_ptr -> ipv6[colon_count / 2] = ctrl_info_ptr -> ipv6[colon_count / 2] << 16;
+ colon_count++;
+ }
+ }
+ }
+ val = 0;
+ }
+ }
+ else
+ {
+ if (*value_ptr >= '0' && *value_ptr <= '9')
+ {
+ val = val * 16 + ((UINT)(*value_ptr - '0'));
+ }
+ else if (*value_ptr >= 'a' && *value_ptr <= 'f')
+ {
+ val = val * 16 + ((UINT)(*value_ptr - 'a')) + 10;
+ }
+ else if (*value_ptr >= 'A' && *value_ptr <= 'F')
+ {
+ val = val * 16 + ((UINT)(*value_ptr - 'A')) + 10;
+ }
+ }
+ value_ptr++;
+ }
+ if (ctrl_info_ptr -> version == NX_IP_VERSION_V6)
+ {
+ ctrl_info_ptr -> ipv6[3] = (ctrl_info_ptr -> ipv6[3] << 16) + val;
+ }
+ }
+ else if ((token_length == (sizeof("test_time") - 1)) &&
+ (memcmp(token, "test_time", token_length) == 0))
+ {
+ ctrl_info_ptr -> TestTime = 0;
+ while (value_ptr && (*value_ptr != 0))
+ {
+ ctrl_info_ptr -> TestTime = ctrl_info_ptr -> TestTime * 10 + ((UINT)(*value_ptr - '0'));
+ value_ptr++;
+ }
+ ctrl_info_ptr -> TestTime = ctrl_info_ptr -> TestTime * NX_IP_PERIODIC_RATE;
+ }
+ else if ((token_length == (sizeof("rate") - 1)) &&
+ (memcmp(token, "rate", token_length) == 0))
+ {
+ ctrl_info_ptr -> Rate = 0;
+ while (value_ptr && (*value_ptr != 0))
+ {
+ ctrl_info_ptr -> Rate = ctrl_info_ptr -> Rate * 10 + ((UINT)(*value_ptr - '0'));
+ value_ptr++;
+ }
+ }
+ else if ((token_length == (sizeof("size") - 1)) &&
+ (memcmp(token, "size", token_length) == 0))
+ {
+ ctrl_info_ptr -> PacketSize = 0;
+ while (value_ptr && (*value_ptr != 0))
+ {
+ ctrl_info_ptr -> PacketSize = ctrl_info_ptr -> PacketSize * 10 + ((UINT)(*value_ptr - '0'));
+ value_ptr++;
+ }
+ }
+ else if ((token_length == (sizeof("port") - 1)) &&
+ (memcmp(token, "port", token_length) == 0))
+ {
+ ctrl_info_ptr -> port = 0;
+ while (value_ptr && (*value_ptr != 0))
+ {
+ ctrl_info_ptr -> port = ctrl_info_ptr -> port * 10 + ((UINT)(*value_ptr - '0'));
+ value_ptr++;
+ }
+ }
+}
+
+/* This function parses the incoming HTTP command line. For each token/value pair, it
+ invokes the nx_iperf_check_token_value routine to parse the values. */
+static void nx_iperf_parse_command(NX_PACKET *packet_ptr, ctrl_info *ctrl_info_ptr)
+{
+UCHAR *cmd_string = packet_ptr -> nx_packet_prepend_ptr;
+UCHAR *token = NX_NULL;
+UCHAR *end_cmd;
+UCHAR *next_token;
+UCHAR *value_ptr;
+
+ /* At this point, cmd_string points to the beginning of the HTTP request,
+ which takes the form of:
+ "GET /test.htm?TestType=xxxxx&ip=....&rxed_pkts=xxxx&test_time=xxxx&tputs=xxxx" */
+
+ /* First skip the "Get /test.html?" string. */
+ cmd_string += (sizeof("GET /test.htm?") - 1);
+
+ /* Find the end of the cmd string, */
+ end_cmd = cmd_string;
+ while (end_cmd < packet_ptr -> nx_packet_append_ptr)
+ {
+ if (*end_cmd == ' ')
+ {
+ break;
+ }
+ end_cmd++;
+ }
+ *end_cmd = 0;
+
+ /* The first token starts from cmd_string. */
+ token = cmd_string;
+ next_token = cmd_string;
+ while (next_token < end_cmd)
+ {
+ /* Find the next token .*/
+ while (next_token < end_cmd)
+ {
+ if (*next_token == '=')
+ {
+ break;
+ }
+ next_token++;
+ }
+
+ if (*next_token == '=')
+ {
+ /* Find a name=value pair. Now we need to find the "=" sign. */
+ *next_token = 0;
+ value_ptr = next_token + 1;
+ next_token++;
+
+ while (next_token < end_cmd)
+ {
+ if (*next_token == '&')
+ {
+ *next_token = 0;
+
+ break;
+ }
+ next_token++;
+ }
+
+ if (value_ptr == next_token)
+ {
+ /* There is no value string. */
+ value_ptr = NX_NULL;
+ }
+
+ /* Move next_token beyond the NULL terminator. */
+ next_token++;
+
+
+ nx_iperf_check_token_value((char *)token, (char *)value_ptr, ctrl_info_ptr);
+ }
+ token = next_token;
+ }
+
+ /* Finished parsing the whole command. */
+}
+
+static CHAR mytempstring[30];
+static VOID nx_iperf_print_main_test_window(NX_WEB_HTTP_SERVER *server_ptr)
+{
+NX_PACKET *resp_packet_ptr;
+UINT status;
+NXD_ADDRESS server_ip;
+UINT length = 0;
+
+#ifdef FEATURE_NX_IPV6
+UINT address_index;
+ULONG prefix_length;
+UINT interface_index;
+#endif
+
+ status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, &resp_packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
+
+ /* write HTML code into the packet */
+ /* htmlwrite(p,s,l) (nx_packet_data_append(p,s,l, server_ptr-> nx_web_http_server_packet_pool_ptr,NX_WAIT_FOREVER)) */
+
+ status += htmlwrite(resp_packet_ptr, outtermosttable, sizeof(outtermosttable) - 1);
+ status += htmlwrite(resp_packet_ptr, maintabletag, sizeof(maintabletag) - 1);
+
+ /* print the IP address line. */
+ status += htmlwrite(resp_packet_ptr, h1line1, sizeof(h1line1) - 1);
+
+#ifndef NX_DISABLE_IPV4
+ server_ip.nxd_ip_version = NX_IP_VERSION_V4;
+ server_ip.nxd_ip_address.v4 = nx_iperf_test_ip -> nx_ip_interface[0].nx_interface_ip_address;
+ status += htmlwrite(resp_packet_ptr, nx_iperf_get_ip_addr_string(&server_ip, &length), length);
+ status += htmlwrite(resp_packet_ptr, "\n", sizeof("\n") - 1);
+#endif
+
+#ifdef FEATURE_NX_IPV6
+ address_index = 0;
+
+ /* Loop to output the IPv6 address. */
+ while (1)
+ {
+
+ /* Get the IPv6 address. */
+ if (nxd_ipv6_address_get(nx_iperf_test_ip, address_index, &server_ip, &prefix_length, &interface_index) == NX_SUCCESS)
+ {
+ status += htmlwrite(resp_packet_ptr, nx_iperf_get_ip_addr_string(&server_ip, &length), length);
+ status += htmlwrite(resp_packet_ptr, "\n", sizeof("\n") - 1);
+ address_index++;
+ }
+ else
+ {
+ break;
+ }
+ }
+#endif
+
+ status += htmlwrite(resp_packet_ptr, h1line2, sizeof(h1line2) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+ status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr);
+
+ if (status)
+ {
+ nx_packet_release(resp_packet_ptr);
+ nx_iperf_test_error_counter++;
+ }
+
+ status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, &resp_packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
+ status += htmlwrite(resp_packet_ptr, udptxsubmittag1, sizeof(udptxsubmittag1) - 1);
+ status += htmlwrite(resp_packet_ptr, nx_iperf_get_ip_addr_string(&udp_tx_ip_address, &length), length);
+ status += htmlwrite(resp_packet_ptr, udptxsubmittag2, sizeof(udptxsubmittag2) - 1);
+ length = _nx_utility_uint_to_string(udp_tx_port, 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, udptxsubmittag3, sizeof(udptxsubmittag3) - 1);
+ length = _nx_utility_uint_to_string(udp_tx_test_time, 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, udptxsubmittag4, sizeof(udptxsubmittag4) - 1);
+ length = _nx_utility_uint_to_string(udp_tx_packet_size, 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, udptxsubmittag5, sizeof(udptxsubmittag5) - 1);
+ status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr);
+
+ if (status)
+ {
+ nx_packet_release(resp_packet_ptr);
+ nx_iperf_test_error_counter++;
+ }
+
+ status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, &resp_packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
+ status += htmlwrite(resp_packet_ptr, udprxsubmittag1, sizeof(udprxsubmittag1) - 1);
+ length = _nx_utility_uint_to_string(udp_rx_test_time, 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, udprxsubmittag2, sizeof(udprxsubmittag2) - 1);
+ status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr);
+
+ if (status)
+ {
+ nx_packet_release(resp_packet_ptr);
+ nx_iperf_test_error_counter++;
+ }
+
+ status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, &resp_packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
+ status += htmlwrite(resp_packet_ptr, tcptxsubmittag1, sizeof(tcptxsubmittag1) - 1);
+ status += htmlwrite(resp_packet_ptr, nx_iperf_get_ip_addr_string(&tcp_tx_ip_address, &length), length);
+ status += htmlwrite(resp_packet_ptr, tcptxsubmittag2, sizeof(tcptxsubmittag2) - 1);
+ length = _nx_utility_uint_to_string(tcp_tx_port, 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, tcptxsubmittag3, sizeof(tcptxsubmittag3) - 1);
+ length = _nx_utility_uint_to_string(tcp_tx_test_time, 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, tcptxsubmittag4, sizeof(tcptxsubmittag4) - 1);
+ status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr);
+
+ if (status)
+ {
+ nx_packet_release(resp_packet_ptr);
+ nx_iperf_test_error_counter++;
+ }
+
+ status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, &resp_packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
+ status += htmlwrite(resp_packet_ptr, tcprxsubmittag1, sizeof(tcprxsubmittag1) - 1);
+ length = _nx_utility_uint_to_string(tcp_rx_test_time, 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, tcprxsubmittag2, sizeof(tcprxsubmittag2) - 1);
+ status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr);
+
+ if (status)
+ {
+ nx_packet_release(resp_packet_ptr);
+ nx_iperf_test_error_counter++;
+ }
+
+ status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, &resp_packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
+ status += htmlwrite(resp_packet_ptr, tableendtag, sizeof(tableendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+
+ status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr);
+
+ if (status)
+ {
+ nx_packet_release(resp_packet_ptr);
+ nx_iperf_test_error_counter++;
+ }
+}
+
+static void nx_iperf_print_end_of_page(NX_WEB_HTTP_SERVER *server_ptr)
+{
+UINT status;
+NX_PACKET *resp_packet_ptr;
+
+ status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, &resp_packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
+
+ /* End of the page. */
+ status += htmlwrite(resp_packet_ptr, tableendtag, sizeof(tableendtag) - 1); /* outtermost table. */
+ status += htmlwrite(resp_packet_ptr, doublebr, sizeof(doublebr) - 1);
+ status += htmlwrite(resp_packet_ptr, centerendtag, sizeof(centerendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, bodyendtag, sizeof(bodyendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, htmlendtag, sizeof(htmlendtag) - 1);
+
+ status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr);
+
+ if (status)
+ {
+ nx_packet_release(resp_packet_ptr);
+ nx_iperf_test_error_counter++;
+ }
+}
+
+static void nx_iperf_print_header(NX_WEB_HTTP_SERVER *server_ptr)
+{
+NX_PACKET *resp_packet_ptr;
+UINT status;
+
+ status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr,
+ &resp_packet_ptr,
+ NX_TCP_PACKET,
+ NX_WAIT_FOREVER);
+
+
+ /* write HTML code into the packet */
+ /* htmlwrite(p,s,l) (nx_packet_data_append(p,s,l, server_ptr-> nx_web_http_server_packet_pool_ptr,NX_WAIT_FOREVER)) */
+
+ status += htmlwrite(resp_packet_ptr, htmlresponse, sizeof(htmlresponse) - 1);
+ status += htmlwrite(resp_packet_ptr, htmltag, sizeof(htmltag) - 1);
+ status += htmlwrite(resp_packet_ptr, titleline, sizeof(titleline) - 1);
+ status += htmlwrite(resp_packet_ptr, bodytag, sizeof(bodytag) - 1);
+ status += htmlwrite(resp_packet_ptr, logo_area, sizeof(logo_area) - 1);
+ status += htmlwrite(resp_packet_ptr, hrline, sizeof(hrline) - 1);
+ status += htmlwrite(resp_packet_ptr, centertag, sizeof(centertag) - 1);
+
+ status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr);
+
+ if (status)
+ {
+ nx_packet_release(resp_packet_ptr);
+ nx_iperf_test_error_counter++;
+ }
+}
+
+
+static void nx_iperf_print_test_inprogress(NX_WEB_HTTP_SERVER *server_ptr, char *msg)
+{
+NX_PACKET *resp_packet_ptr;
+UINT status;
+UINT length = 0;
+
+ status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr,
+ &resp_packet_ptr,
+ NX_TCP_PACKET,
+ NX_WAIT_FOREVER);
+ status += htmlwrite(resp_packet_ptr, tdcentertag, sizeof(tdcentertag) - 1);
+ status += htmlwrite(resp_packet_ptr, fontcolortag, sizeof(fontcolortag) - 1);
+ _nx_utility_string_length_check(msg, &length, NX_MAX_STRING_LENGTH);
+ status += htmlwrite(resp_packet_ptr, msg, length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+
+ status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr);
+
+ if (status)
+ {
+ nx_packet_release(resp_packet_ptr);
+ nx_iperf_test_error_counter++;
+ }
+}
+
+static void nx_iperf_print_empty_line(NX_WEB_HTTP_SERVER *server_ptr)
+{
+NX_PACKET *resp_packet_ptr;
+UINT status = 0;
+
+ status += nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, &resp_packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
+ status += htmlwrite(resp_packet_ptr, choosetesttag, sizeof(choosetesttag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+ status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr);
+
+ if (status)
+ {
+ nx_packet_release(resp_packet_ptr);
+ nx_iperf_test_error_counter++;
+ }
+}
+
+static void nx_iperf_send_test_result_info(NX_WEB_HTTP_SERVER *server_ptr)
+{
+char *response_string = NX_NULL;
+NXD_ADDRESS peer_ip_address;
+
+ if (nx_iperf_ctrl_info.TestStatus == 0)
+ {
+ nx_iperf_print_empty_line(server_ptr);
+
+ /* No test is running. Do nothing. */
+ return;
+ }
+ else if (nx_iperf_ctrl_info.TestStatus == 1)
+ {
+ switch (nx_iperf_ctrl_info.ctrl_sign)
+ {
+ case UDP_RX_START:
+ response_string = "UDP Receive Test started. After the iperf test finishes, click <a href=\"/\">here</a> to get results.";
+ break;
+ case TCP_RX_START:
+ response_string = "TCP Receive Test started. After the iperf test finishes, click <a href=\"/\">here</a> to get results.";
+ break;
+ case UDP_TX_START:
+ response_string = "UDP Transmit Test starts in 2 seconds. After iperf test is done, click <a href=\"/\">here</a> to get results.";
+ break;
+ case TCP_TX_START:
+ response_string = "TCP Transmit test starts in 2 seconds. After iperf test is done, click <a href=\"/\">here</a> to get results.";
+ break;
+ }
+ nx_iperf_print_test_inprogress(server_ptr, response_string);
+ }
+ else if (nx_iperf_ctrl_info.TestStatus == 2)
+ {
+
+ /* Check the ThroughPut value and StartTime,
+ if the StartTime is zero means no connection.
+ if throughput value is zero means maybe user interrupt the test.
+ recalculate the ThroughPut before Interrupt. */
+ if ((!nx_iperf_ctrl_info.ThroughPut) && (nx_iperf_ctrl_info.StartTime))
+ {
+
+ /* Calculate the run time and Throughput(Mbps). */
+ nx_iperf_ctrl_info.RunTime = tx_time_get() - nx_iperf_ctrl_info.StartTime;
+
+ /* Check the run time. */
+ if (nx_iperf_ctrl_info.RunTime > nx_iperf_ctrl_info.TestTime)
+ {
+ nx_iperf_ctrl_info.RunTime = nx_iperf_ctrl_info.TestTime;
+ }
+
+ /* Calculate Throughput(Mbps). */
+ nx_iperf_ctrl_info.ThroughPut = (nx_iperf_ctrl_info.BytesTxed + nx_iperf_ctrl_info.BytesRxed) / nx_iperf_ctrl_info.RunTime * NX_IP_PERIODIC_RATE / 125000;
+ }
+
+ peer_ip_address.nxd_ip_version = nx_iperf_ctrl_info.version;
+
+#ifdef FEATURE_NX_IPV6
+ if (peer_ip_address.nxd_ip_version == NX_IP_VERSION_V6)
+ {
+ peer_ip_address.nxd_ip_address.v6[0] = nx_iperf_ctrl_info.ipv6[0];
+ peer_ip_address.nxd_ip_address.v6[1] = nx_iperf_ctrl_info.ipv6[1];
+ peer_ip_address.nxd_ip_address.v6[2] = nx_iperf_ctrl_info.ipv6[2];
+ peer_ip_address.nxd_ip_address.v6[3] = nx_iperf_ctrl_info.ipv6[3];
+ }
+ else
+#endif
+ {
+#ifndef NX_DISABLE_IPV4
+ peer_ip_address.nxd_ip_address.v4 = nx_iperf_ctrl_info.ip;
+#endif
+ }
+
+ switch (nx_iperf_ctrl_info.ctrl_sign)
+ {
+ case UDP_RX_START:
+ nx_iperf_print_udp_rx_results(server_ptr, &peer_ip_address);
+ break;
+ case TCP_RX_START:
+ nx_iperf_print_tcp_rx_results(server_ptr, &peer_ip_address);
+ break;
+ case UDP_TX_START:
+ nx_iperf_print_udp_tx_results(server_ptr, &peer_ip_address);
+ break;
+ case TCP_TX_START:
+ nx_iperf_print_tcp_tx_results(server_ptr, &peer_ip_address);
+ break;
+ }
+ memset(&nx_iperf_ctrl_info, 0, sizeof(nx_iperf_ctrl_info));
+ }
+}
+
+UINT nx_iperf_get_notify(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type, CHAR *resource, NX_PACKET *packet_ptr)
+{
+ctrl_info new_cmd;
+UINT status;
+ULONG port;
+UINT length;
+
+ NX_PARAMETER_NOT_USED(request_type);
+
+ memset(&new_cmd, 0, sizeof(ctrl_info));
+
+ /* Get peer IP address. */
+ status = nxd_tcp_socket_peer_info_get(&server_ptr -> nx_web_http_server_current_session_ptr -> nx_tcp_session_socket, &udp_tx_ip_address, &port);
+ if (status)
+ {
+ return(status);
+ }
+ tcp_tx_ip_address = udp_tx_ip_address;
+
+ /* Disconnect to mark the end of respond. */
+#ifndef NX_WEB_HTTP_KEEPALIVE_DISABLE
+ server_ptr -> nx_web_http_server_keepalive = NX_FALSE;
+#endif
+
+ _nx_utility_string_length_check(resource, &length, NX_WEB_HTTP_MAX_RESOURCE);
+ if (((length == sizeof("/test.htm") - 1) && (memcmp(resource, "/test.htm", length) == 0)) ||
+ ((length == 1) && *resource == '/'))
+ {
+
+ /* Printer the header. */
+ nx_iperf_print_header(server_ptr);
+
+ /* Parse the command. */
+ nx_iperf_parse_command(packet_ptr, &new_cmd);
+
+ /* If the current test is still running, and we have a new command,
+ we need to clean up the current one. */
+ if (new_cmd.ctrl_sign)
+ {
+ if ((nx_iperf_ctrl_info.TestStatus != 0) || ((nx_iperf_ctrl_info.ctrl_sign & NX_IPERF_CLEAN_UP_MASK) == 1))
+ {
+
+ switch (nx_iperf_ctrl_info.ctrl_sign)
+ {
+ case TCP_RX_START:
+ nx_iperf_tcp_rx_cleanup();
+ break;
+ case TCP_TX_START:
+ nx_iperf_tcp_tx_cleanup();
+ break;
+ case UDP_RX_START:
+ nx_iperf_udp_rx_cleanup();
+ break;
+ case UDP_TX_START:
+ nx_iperf_udp_tx_cleanup();
+ break;
+ default:
+ break;
+ }
+ memset(&nx_iperf_ctrl_info, 0, sizeof(nx_iperf_ctrl_info));
+ }
+
+ memcpy(&nx_iperf_ctrl_info, &new_cmd, sizeof(ctrl_info)); /* Use case of memcpy is verified. */
+
+ /* Create the test thread and run the test. */
+ nx_iperf_test_info_parse(&nx_iperf_ctrl_info);
+
+ /* Update the TestStatus. */
+ nx_iperf_ctrl_info.TestStatus = 1;
+ }
+
+ /* Check the status, set the default value. */
+ if (nx_iperf_ctrl_info.TestStatus == 0)
+ {
+
+ /* Check the IP version. */
+ if (udp_tx_ip_address.nxd_ip_version == NX_IP_VERSION_V4)
+ {
+ udp_tx_packet_size = 1470;
+ }
+ else
+ {
+ udp_tx_packet_size = 1450;
+ }
+ }
+
+ /* Print the main window. */
+ nx_iperf_print_main_test_window(server_ptr);
+
+ /* If there is a new command, show the result of launching the command. */
+ nx_iperf_send_test_result_info(server_ptr);
+
+ nx_iperf_print_end_of_page(server_ptr);
+
+ /* Update the TestStatus. */
+ if (nx_iperf_ctrl_info.TestStatus == 1)
+ {
+ nx_iperf_ctrl_info.TestStatus = 2;
+ }
+
+ return(NX_WEB_HTTP_CALLBACK_COMPLETED);
+ }
+ /* send the logo files */
+ if ((length == sizeof("/nxlogo.png") - 1) && (memcmp(resource, "/nxlogo.png", length) == 0))
+ {
+ nx_iperf_send_image(server_ptr, (UCHAR *)nxlogo_png, nxlogo_png_size);
+ return(NX_WEB_HTTP_CALLBACK_COMPLETED);
+ }
+
+ if ((length == sizeof("/mslogo.jpg") - 1) && (memcmp(resource, "/mslogo.jpg", length) == 0))
+ {
+ nx_iperf_send_image(server_ptr, (UCHAR *)mslogo_jpg, mslogo_jpg_size);
+ return(NX_WEB_HTTP_CALLBACK_COMPLETED);
+ }
+
+ return(NX_SUCCESS);
+}
+
+static void nx_iperf_send_image(NX_WEB_HTTP_SERVER *server_ptr, UCHAR *img, UINT imgsize)
+{
+
+UINT remaining;
+UCHAR *position;
+UINT max_size;
+UINT status;
+
+ status = nx_tcp_socket_mss_get(&(server_ptr -> nx_web_http_server_current_session_ptr -> nx_tcp_session_socket), (ULONG *)&max_size);
+ if (status)
+ {
+ return;
+ }
+
+ remaining = imgsize;
+ position = img;
+ while (remaining)
+ {
+ if (remaining > max_size)
+ {
+ nx_web_http_server_callback_data_send(server_ptr, (void *)position, max_size);
+ position += max_size;
+ remaining -= max_size;
+ }
+ else
+ {
+ nx_web_http_server_callback_data_send(server_ptr, (void *)position, remaining);
+ remaining = 0;
+ }
+ }
+}
+
+
+void nx_iperf_test_info_parse(ctrl_info *iperf_ctrlInfo_ptr)
+{
+
+ /* Check the sign and set the related parameters. */
+ switch ((iperf_ctrlInfo_ptr -> ctrl_sign) & NX_IPERF_CTRL_SIGN_MASK)
+ {
+
+ case TCP_RX_START:
+ {
+ if (iperf_ctrlInfo_ptr -> TestTime == 0)
+ {
+ iperf_ctrlInfo_ptr -> TestTime = 10 * NX_IP_PERIODIC_RATE;
+ }
+ tcp_rx_test_time = (UINT)((iperf_ctrlInfo_ptr -> TestTime) / NX_IP_PERIODIC_RATE);
+
+ nx_iperf_tcp_rx_test(nx_iperf_stack_area, nx_iperf_stack_area_size);
+ break;
+ }
+
+ case TCP_TX_START:
+ {
+
+ if (iperf_ctrlInfo_ptr -> TestTime == 0)
+ {
+ iperf_ctrlInfo_ptr -> TestTime = 10 * NX_IP_PERIODIC_RATE;
+ }
+ tcp_tx_test_time = (UINT)((iperf_ctrlInfo_ptr -> TestTime) / NX_IP_PERIODIC_RATE);
+
+ /* Set the transmit ip address. */
+ if (iperf_ctrlInfo_ptr -> version == NX_IP_VERSION_V4)
+ {
+#ifndef NX_DISABLE_IPV4
+ tcp_tx_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
+ tcp_tx_ip_address.nxd_ip_address.v4 = iperf_ctrlInfo_ptr -> ip;
+#else
+ break;
+#endif
+ }
+
+#ifdef FEATURE_NX_IPV6
+ else
+ {
+ tcp_tx_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
+ tcp_tx_ip_address.nxd_ip_address.v6[0] = iperf_ctrlInfo_ptr -> ipv6[0];
+ tcp_tx_ip_address.nxd_ip_address.v6[1] = iperf_ctrlInfo_ptr -> ipv6[1];
+ tcp_tx_ip_address.nxd_ip_address.v6[2] = iperf_ctrlInfo_ptr -> ipv6[2];
+ tcp_tx_ip_address.nxd_ip_address.v6[3] = iperf_ctrlInfo_ptr -> ipv6[3];
+ }
+#endif
+ tcp_tx_port = iperf_ctrlInfo_ptr -> port;
+
+ nx_iperf_tcp_tx_test(nx_iperf_stack_area, nx_iperf_stack_area_size);
+ break;
+ }
+
+ case UDP_RX_START:
+ {
+ if (iperf_ctrlInfo_ptr -> TestTime == 0)
+ {
+ iperf_ctrlInfo_ptr -> TestTime = 10 * NX_IP_PERIODIC_RATE;
+ }
+ udp_rx_test_time = (UINT)((iperf_ctrlInfo_ptr -> TestTime) / NX_IP_PERIODIC_RATE);
+
+ nx_iperf_udp_rx_test(nx_iperf_stack_area, nx_iperf_stack_area_size);
+ break;
+ }
+
+ case UDP_TX_START:
+ {
+ if (iperf_ctrlInfo_ptr -> TestTime == 0)
+ {
+ iperf_ctrlInfo_ptr -> TestTime = 10 * NX_IP_PERIODIC_RATE;
+ }
+ udp_tx_test_time = (UINT)((iperf_ctrlInfo_ptr -> TestTime) / NX_IP_PERIODIC_RATE);
+
+ if ((iperf_ctrlInfo_ptr -> PacketSize == 0) || (iperf_ctrlInfo_ptr -> PacketSize > 1470))
+ {
+ iperf_ctrlInfo_ptr -> PacketSize = 1470;
+ }
+ udp_tx_packet_size = (UINT)(iperf_ctrlInfo_ptr -> PacketSize);
+ udp_tx_port = iperf_ctrlInfo_ptr -> port;
+
+ /* Set the transmit ip address. */
+ if (iperf_ctrlInfo_ptr -> version == NX_IP_VERSION_V4)
+ {
+#ifndef NX_DISABLE_IPV4
+ udp_tx_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
+ udp_tx_ip_address.nxd_ip_address.v4 = iperf_ctrlInfo_ptr -> ip;
+#else
+ break;
+#endif
+ }
+
+#ifdef FEATURE_NX_IPV6
+ else
+ {
+ udp_tx_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
+ udp_tx_ip_address.nxd_ip_address.v6[0] = iperf_ctrlInfo_ptr -> ipv6[0];
+ udp_tx_ip_address.nxd_ip_address.v6[1] = iperf_ctrlInfo_ptr -> ipv6[1];
+ udp_tx_ip_address.nxd_ip_address.v6[2] = iperf_ctrlInfo_ptr -> ipv6[2];
+ udp_tx_ip_address.nxd_ip_address.v6[3] = iperf_ctrlInfo_ptr -> ipv6[3];
+ if (udp_tx_packet_size > 1450)
+ {
+ udp_tx_packet_size = 1450;
+ }
+ }
+#endif
+
+ if (iperf_ctrlInfo_ptr -> Rate == 0)
+ {
+ iperf_ctrlInfo_ptr -> Rate = 10;
+ }
+
+ nx_iperf_udp_tx_test(nx_iperf_stack_area, nx_iperf_stack_area_size);
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+}
+
+static void nx_iperf_print_tcp_rx_results(NX_WEB_HTTP_SERVER *server_ptr, NXD_ADDRESS *peer_ip_address)
+{
+
+UINT status;
+NX_PACKET *resp_packet_ptr;
+UINT length = 0;
+
+ status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr,
+ &resp_packet_ptr,
+ NX_TCP_PACKET,
+ NX_WAIT_FOREVER);
+
+ htmlwrite(resp_packet_ptr, toptdtag, sizeof(toptdtag) - 1);
+ htmlwrite(resp_packet_ptr, tabletag, sizeof(tabletag) - 1);
+ status += htmlwrite(resp_packet_ptr, rightspanline, sizeof(rightspanline) - 1);
+ htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ htmlwrite(resp_packet_ptr, "TCP Receive Test Done:", sizeof("TCP Receive Test Done:") - 1);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, rightspanline, sizeof(rightspanline) - 1);
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Source IP Address: ", sizeof("Source IP Address: ") - 1);
+ status += htmlwrite(resp_packet_ptr, nx_iperf_get_ip_addr_string(peer_ip_address, &length), length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Test Time(milliseconds): ", sizeof("Test Time(milliseconds): ") - 1);
+ length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.RunTime * 1000 / NX_IP_PERIODIC_RATE), 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Number of Packets Received: ", sizeof("Number of Packets Received: ") - 1);
+ length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.PacketsRxed), 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Number of Bytes Received: ", sizeof("Number of Bytes Received: ") - 1);
+ length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.BytesRxed), 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Throughput(Mbps): ", sizeof("Throughput(Mbps): ") - 1);
+ length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.ThroughPut), 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ length = _nx_utility_uint_to_string(nx_iperf_ctrl_info.idleTime, 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, "Idle Time: ", sizeof("Idle Time: ") - 1);
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, "%", sizeof("%") - 1);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+#endif
+
+ htmlwrite(resp_packet_ptr, tableendtag, sizeof(tableendtag) - 1);
+ htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+
+ status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr);
+
+ if (status)
+ {
+ nx_packet_release(resp_packet_ptr);
+ nx_iperf_test_error_counter++;
+ }
+
+ /* Delete the receive thread. */
+ nx_iperf_tcp_rx_cleanup();
+}
+
+static void nx_iperf_print_tcp_tx_results(NX_WEB_HTTP_SERVER *server_ptr, NXD_ADDRESS *peer_ip_address)
+{
+UINT status;
+NX_PACKET *resp_packet_ptr;
+UINT length = 0;
+
+ status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr,
+ &resp_packet_ptr,
+ NX_TCP_PACKET,
+ NX_WAIT_FOREVER);
+
+ htmlwrite(resp_packet_ptr, toptdtag, sizeof(toptdtag) - 1);
+ htmlwrite(resp_packet_ptr, tabletag, sizeof(tabletag) - 1);
+ status += htmlwrite(resp_packet_ptr, rightspanline, sizeof(rightspanline) - 1);
+ htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ htmlwrite(resp_packet_ptr, "TCP Transmit Test Done:", sizeof("TCP Transmit Test Done:") - 1);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, rightspanline, sizeof(rightspanline) - 1);
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Destination IP Address: ", sizeof("Destination IP Address: ") - 1);
+ status += htmlwrite(resp_packet_ptr, nx_iperf_get_ip_addr_string(peer_ip_address, &length), length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Destination Port: ", sizeof("Destination Port: ") - 1);
+ length = _nx_utility_uint_to_string(nx_iperf_ctrl_info.port, 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Test Time(milliseconds): ", sizeof("Test Time(milliseconds): ") - 1);
+ length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.RunTime * 1000 / NX_IP_PERIODIC_RATE), 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Number of Packets Transmitted: ", sizeof("Number of Packets Transmitted: ") - 1);
+ length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.PacketsTxed), 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Number of Bytes Transmitted: ", sizeof("Number of Bytes Transmitted: ") - 1);
+ length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.BytesTxed), 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Throughput(Mbps): ", sizeof("Throughput(Mbps): ") - 1);
+ length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.ThroughPut), 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ length = _nx_utility_uint_to_string(nx_iperf_ctrl_info.idleTime, 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, "Idle Time: ", sizeof("Idle Time: ") - 1);
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, "%", sizeof("%") - 1);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+#endif
+
+ status += htmlwrite(resp_packet_ptr, tableendtag, sizeof(tableendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+
+ status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr);
+
+ if (status)
+ {
+ nx_packet_release(resp_packet_ptr);
+ nx_iperf_test_error_counter++;
+ }
+
+ /* Delete the receive thread. */
+ nx_iperf_tcp_tx_cleanup();
+}
+
+static void nx_iperf_print_udp_rx_results(NX_WEB_HTTP_SERVER *server_ptr, NXD_ADDRESS *peer_ip_address)
+{
+UINT status;
+NX_PACKET *resp_packet_ptr;
+UINT length = 0;
+
+ status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr,
+ &resp_packet_ptr,
+ NX_TCP_PACKET,
+ NX_WAIT_FOREVER);
+
+ /* now send the data back to the client. */
+ htmlwrite(resp_packet_ptr, toptdtag, sizeof(toptdtag) - 1);
+ htmlwrite(resp_packet_ptr, tabletag, sizeof(tabletag) - 1);
+ status += htmlwrite(resp_packet_ptr, rightspanline, sizeof(rightspanline) - 1);
+ htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ htmlwrite(resp_packet_ptr, "UDP Receive Test Done:", sizeof("UDP Receive Test Done:") - 1);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, rightspanline, sizeof(rightspanline) - 1);
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Source IP Address: ", sizeof("Source IP Address: ") - 1);
+ status += htmlwrite(resp_packet_ptr, nx_iperf_get_ip_addr_string(peer_ip_address, &length), length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Test Time(milliseconds): ", sizeof("Test Time(milliseconds): ") - 1);
+ length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.RunTime * 1000 / NX_IP_PERIODIC_RATE), 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Number of Packets Received: ", sizeof("Number of Packets Received: ") - 1);
+ length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.PacketsRxed), 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Number of Bytes Received: ", sizeof("Number of Bytes Received: ") - 1);
+ length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.BytesRxed), 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Throughput(Mbps): ", sizeof("Throughput(Mbps): ") - 1);
+ length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.ThroughPut), 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.idleTime), 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, "Idle Time: ", sizeof("Idle Time: ") - 1);
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, "%", sizeof("%") - 1);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+#endif
+
+ status += htmlwrite(resp_packet_ptr, tableendtag, sizeof(tableendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+
+ status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr);
+
+ if (status)
+ {
+ nx_packet_release(resp_packet_ptr);
+ nx_iperf_test_error_counter++;
+ }
+
+ nx_iperf_udp_rx_cleanup();
+}
+
+static void nx_iperf_print_udp_tx_results(NX_WEB_HTTP_SERVER *server_ptr, NXD_ADDRESS *peer_ip_address)
+{
+UINT status;
+NX_PACKET *resp_packet_ptr;
+UINT length = 0;
+
+ status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr,
+ &resp_packet_ptr,
+ NX_TCP_PACKET,
+ NX_WAIT_FOREVER);
+
+ /* now send the data back to the client. */
+ htmlwrite(resp_packet_ptr, toptdtag, sizeof(toptdtag) - 1);
+ htmlwrite(resp_packet_ptr, tabletag, sizeof(tabletag) - 1);
+ status += htmlwrite(resp_packet_ptr, rightspanline, sizeof(rightspanline) - 1);
+ htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ htmlwrite(resp_packet_ptr, "UDP Transmit Test Done:", sizeof("UDP Transmit Test Done:") - 1);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, rightspanline, sizeof(rightspanline) - 1);
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Destination IP Address: ", sizeof("Destination IP Address: ") - 1);
+ status += htmlwrite(resp_packet_ptr, nx_iperf_get_ip_addr_string(peer_ip_address, &length), length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Destination Port: ", sizeof("Destination Port: ") - 1);
+ length = _nx_utility_uint_to_string(nx_iperf_ctrl_info.port, 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Test Time(milliseconds): ", sizeof("Test Time(milliseconds): ") - 1);
+ length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.RunTime * 1000 / NX_IP_PERIODIC_RATE), 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Number of Packets Transmitted: ", sizeof("Number of Packets Transmitted: ") - 1);
+ length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.PacketsTxed), 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Number of Bytes Transmitted: ", sizeof("Number of Bytes Transmitted: ") - 1);
+ length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.BytesTxed), 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ status += htmlwrite(resp_packet_ptr, "Throughput(Mbps): ", sizeof("Throughput(Mbps): ") - 1);
+ length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.ThroughPut), 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1);
+ status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1);
+ length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.idleTime), 10, mytempstring, sizeof(mytempstring));
+ status += htmlwrite(resp_packet_ptr, "Idle Time: ", sizeof("Idle Time: ") - 1);
+ status += htmlwrite(resp_packet_ptr, mytempstring, length);
+ status += htmlwrite(resp_packet_ptr, "%", sizeof("%") - 1);
+ status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1);
+#endif
+
+ status += htmlwrite(resp_packet_ptr, tableendtag, sizeof(tableendtag) - 1);
+ status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1);
+
+ status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr);
+
+ if (status)
+ {
+ nx_packet_release(resp_packet_ptr);
+ nx_iperf_test_error_counter++;
+ }
+
+ nx_iperf_udp_tx_cleanup();
+}
+
+void nx_iperf_thread_tcp_rx_entry(ULONG thread_input)
+{
+UINT status;
+NX_PACKET *packet_ptr;
+ULONG actual_status;
+ULONG expire_time;
+ctrl_info *ctrlInfo_ptr;
+NXD_ADDRESS ip_address;
+ULONG port;
+
+ /* Set the pointer. */
+ ctrlInfo_ptr = (ctrl_info *)thread_input;
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ /* Update the time. */
+ thread_time = 0;
+ isr_time = 0;
+ idle_time = 0;
+#endif
+
+ /* Update the test result. */
+ ctrlInfo_ptr -> PacketsRxed = 0;
+ ctrlInfo_ptr -> BytesRxed = 0;
+ ctrlInfo_ptr -> ThroughPut = 0;
+ ctrlInfo_ptr -> StartTime = 0;
+ ctrlInfo_ptr -> RunTime = 0;
+ ctrlInfo_ptr -> ErrorCode = 0;
+
+ /* Ensure the IP instance has been initialized. */
+ status = nx_ip_status_check(nx_iperf_test_ip, NX_IP_INITIALIZE_DONE, &actual_status, NX_IP_PERIODIC_RATE);
+
+ /* Check status... */
+ if (status != NX_SUCCESS)
+ {
+ error_counter++;
+ return;
+ }
+
+ /* Create a socket. */
+ status = nx_tcp_socket_create(nx_iperf_test_ip, &tcp_server_socket, "TCP Server Socket",
+ NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 32 * 1024,
+ NX_NULL, nx_iperf_tcp_rx_disconnect_received);
+
+ /* Check for error. */
+ if (status)
+ {
+ error_counter++;
+ return;
+ }
+
+ /* Setup this thread to listen. */
+ status = nx_tcp_server_socket_listen(nx_iperf_test_ip, NX_IPERF_TCP_RX_PORT, &tcp_server_socket, 5, nx_iperf_tcp_rx_connect_received);
+
+ /* Check for error. */
+ if (status)
+ {
+ nx_tcp_socket_delete(&tcp_server_socket);
+ error_counter++;
+ return;
+ }
+
+ /* Increment thread tcp rx's counter. */
+ thread_tcp_rx_counter++;
+
+ /* Accept a client socket connection. */
+ status = nx_tcp_server_socket_accept(&tcp_server_socket, NX_WAIT_FOREVER);
+
+ /* Check for error. */
+ if (status)
+ {
+ nx_tcp_server_socket_unlisten(nx_iperf_test_ip, NX_IPERF_TCP_RX_PORT);
+ nx_tcp_socket_delete(&tcp_server_socket);
+ error_counter++;
+ return;
+ }
+
+ /*Get source ip address*/
+ status = nxd_tcp_socket_peer_info_get(&tcp_server_socket, &ip_address, &port);
+ if (status)
+ {
+ nx_tcp_server_socket_unaccept(&tcp_server_socket);
+ nx_tcp_server_socket_unlisten(nx_iperf_test_ip, NX_IPERF_TCP_RX_PORT);
+ nx_tcp_socket_delete(&tcp_server_socket);
+ error_counter++;
+ return;
+ }
+
+ ctrlInfo_ptr -> version = ip_address.nxd_ip_version;
+ if (ctrlInfo_ptr -> version == NX_IP_VERSION_V4)
+ {
+#ifndef NX_DISABLE_IPV4
+ ctrlInfo_ptr -> ip = ip_address.nxd_ip_address.v4;
+#endif
+ }
+#ifdef FEATURE_NX_IPV6
+ else if (ctrlInfo_ptr -> version == NX_IP_VERSION_V6)
+ {
+ memcpy(ctrlInfo_ptr -> ipv6, ip_address.nxd_ip_address.v6, sizeof(ULONG) * 4); /* Use case of memcpy is verified. */
+ }
+#endif
+
+ /* Set the test start time. */
+ ctrlInfo_ptr -> StartTime = tx_time_get();
+ expire_time = (ULONG)(ctrlInfo_ptr -> StartTime + (ctrlInfo_ptr -> TestTime) + 20);
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ _tx_execution_thread_total_time_reset();
+ _tx_execution_isr_time_reset();
+ _tx_execution_idle_time_reset();
+#endif
+
+ while (tx_time_get() < expire_time)
+ {
+ /* Receive a TCP message from the socket. */
+ status = nx_tcp_socket_receive(&tcp_server_socket, &packet_ptr, NX_WAIT_FOREVER);
+
+ /* Check for error. */
+ if (status)
+ {
+ error_counter++;
+ break;
+ }
+
+ /* Update the counter. */
+ ctrlInfo_ptr -> PacketsRxed++;
+ ctrlInfo_ptr -> BytesRxed += packet_ptr -> nx_packet_length;
+
+ /* Release the packet. */
+ nx_packet_release(packet_ptr);
+ }
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ _tx_execution_thread_total_time_get(&thread_time);
+ _tx_execution_isr_time_get(&isr_time);
+ _tx_execution_idle_time_get(&idle_time);
+#endif
+
+ /* Calculate the test time and Throughput(Mbps). */
+ ctrlInfo_ptr -> RunTime = tx_time_get() - ctrlInfo_ptr -> StartTime;
+ ctrlInfo_ptr -> ThroughPut = ctrlInfo_ptr -> BytesRxed / ctrlInfo_ptr -> RunTime * NX_IP_PERIODIC_RATE / 125000;
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ ctrlInfo_ptr -> idleTime = (ULONG)((unsigned long long)idle_time * 100 / ((unsigned long long)thread_time + (unsigned long long)isr_time + (unsigned long long)idle_time));
+#endif
+
+ /* Disconnect the server socket. */
+ status = nx_tcp_socket_disconnect(&tcp_server_socket, 10);
+
+ /* Check for error. */
+ if (status)
+ {
+ error_counter++;
+ }
+
+ /* Unaccept the server socket. */
+ status = nx_tcp_server_socket_unaccept(&tcp_server_socket);
+ status += nx_tcp_server_socket_unlisten(nx_iperf_test_ip, NX_IPERF_TCP_RX_PORT);
+
+ /* Check for error. */
+ if (status)
+ {
+ error_counter++;
+ }
+
+ if (error_counter)
+ {
+ ctrlInfo_ptr -> ErrorCode = error_counter;
+ }
+
+ /* Delete the socket. */
+ nx_tcp_socket_delete(&tcp_server_socket);
+}
+
+void nx_iperf_tcp_rx_connect_received(NX_TCP_SOCKET *socket_ptr, UINT port)
+{
+ /* Check for the proper socket and port. */
+ if ((socket_ptr != &tcp_server_socket) || (port != NX_IPERF_TCP_RX_PORT))
+ {
+ error_counter++;
+ }
+}
+
+void nx_iperf_tcp_rx_disconnect_received(NX_TCP_SOCKET *socket)
+{
+ /* Check for proper disconnected socket. */
+ if (socket != &tcp_server_socket)
+ {
+ error_counter++;
+ }
+}
+
+void nx_iperf_tcp_rx_cleanup(void)
+{
+ nx_tcp_socket_disconnect(&tcp_server_socket, NX_NO_WAIT);
+ nx_tcp_server_socket_unaccept(&tcp_server_socket);
+ nx_tcp_server_socket_unlisten(nx_iperf_test_ip, NX_IPERF_TCP_RX_PORT);
+ nx_tcp_socket_delete(&tcp_server_socket);
+
+ tx_thread_terminate(&thread_tcp_rx_iperf);
+ tx_thread_delete(&thread_tcp_rx_iperf);
+}
+
+void nx_iperf_tcp_rx_test(UCHAR *stack_space, ULONG stack_size)
+{
+
+UINT status;
+
+ status = tx_thread_create(&thread_tcp_rx_iperf, "thread tcp rx",
+ nx_iperf_thread_tcp_rx_entry,
+ (ULONG)&nx_iperf_ctrl_info,
+ stack_space, stack_size, NX_IPERF_THREAD_PRIORITY, NX_IPERF_THREAD_PRIORITY,
+ TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ if (status)
+ {
+ nx_iperf_ctrl_info.ErrorCode = 1;
+ }
+ return;
+}
+
+void nx_iperf_thread_tcp_tx_entry(ULONG thread_input)
+{
+UINT status;
+UINT is_first = NX_TRUE;
+NX_PACKET *my_packet = NX_NULL;
+#ifndef NX_DISABLE_PACKET_CHAIN
+NX_PACKET *packet_ptr;
+NX_PACKET *last_packet;
+ULONG remaining_size;
+#endif /* NX_DISABLE_PACKET_CHAIN */
+ULONG expire_time;
+ctrl_info *ctrlInfo_ptr;
+ULONG packet_size;
+NXD_ADDRESS server_ip;
+
+ /* Set the pointer. */
+ ctrlInfo_ptr = (ctrl_info *)thread_input;
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ thread_time = 0;
+ isr_time = 0;
+ idle_time = 0;
+#endif
+
+ ctrlInfo_ptr -> PacketsTxed = 0;
+ ctrlInfo_ptr -> BytesTxed = 0;
+ ctrlInfo_ptr -> ThroughPut = 0;
+ ctrlInfo_ptr -> StartTime = 0;
+ ctrlInfo_ptr -> RunTime = 0;
+ ctrlInfo_ptr -> ErrorCode = 0;
+
+ server_ip.nxd_ip_version = ctrlInfo_ptr -> version;
+
+#ifdef FEATURE_NX_IPV6
+ if (ctrlInfo_ptr -> version == NX_IP_VERSION_V6)
+ {
+ server_ip.nxd_ip_address.v6[0] = ctrlInfo_ptr -> ipv6[0];
+ server_ip.nxd_ip_address.v6[1] = ctrlInfo_ptr -> ipv6[1];
+ server_ip.nxd_ip_address.v6[2] = ctrlInfo_ptr -> ipv6[2];
+ server_ip.nxd_ip_address.v6[3] = ctrlInfo_ptr -> ipv6[3];
+ }
+ else if (ctrlInfo_ptr -> version == NX_IP_VERSION_V4)
+#endif
+ {
+#ifndef NX_DISABLE_IPV4
+ server_ip.nxd_ip_address.v4 = ctrlInfo_ptr -> ip;
+#endif
+ }
+
+ /* TCP Transmit Test Starts in 2 seconds. */
+ tx_thread_sleep(200);
+
+ /* Create the socket. */
+ status = nx_tcp_socket_create(nx_iperf_test_ip, &tcp_client_socket, "TCP Client Socket",
+ NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 32 * 1024,
+ NX_NULL, NX_NULL);
+
+ /* Check for error. */
+ if (status)
+ {
+ error_counter++;
+ return;
+ }
+
+ /* Bind the socket. */
+ status = nx_tcp_client_socket_bind(&tcp_client_socket, NX_ANY_PORT, NX_WAIT_FOREVER);
+
+ /* Check for error. */
+ if (status)
+ {
+ nx_tcp_socket_delete(&tcp_client_socket);
+ error_counter++;
+ return;
+ }
+
+ /* Attempt to connect the socket. */
+ status = nxd_tcp_client_socket_connect(&tcp_client_socket, &server_ip, ctrlInfo_ptr -> port, NX_WAIT_FOREVER);
+
+ /* Check for error. */
+ if (status)
+ {
+ nx_tcp_client_socket_unbind(&tcp_client_socket);
+ nx_tcp_socket_delete(&tcp_client_socket);
+ error_counter++;
+ return;
+ }
+
+ /* Set the test start time. */
+ ctrlInfo_ptr -> StartTime = tx_time_get();
+ expire_time = (ULONG)(ctrlInfo_ptr -> StartTime + (ctrlInfo_ptr -> TestTime));
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ _tx_execution_thread_total_time_reset();
+ _tx_execution_isr_time_reset();
+ _tx_execution_idle_time_reset();
+#endif
+
+ /* Set the packet size. */
+ status = nx_tcp_socket_mss_get(&tcp_client_socket, &packet_size);
+
+ /* Check for error. */
+ if (status)
+ {
+ nx_tcp_socket_disconnect(&tcp_client_socket, NX_NO_WAIT);
+ nx_tcp_client_socket_unbind(&tcp_client_socket);
+ nx_tcp_socket_delete(&tcp_client_socket);
+ error_counter++;
+ return;
+ }
+
+ /* Loop to transmit the packet. */
+ while (tx_time_get() < expire_time)
+ {
+
+ /* Allocate a packet. */
+ status = nx_packet_allocate(nx_iperf_test_pool, &my_packet, NX_TCP_PACKET, NX_WAIT_FOREVER);
+
+ /* Check status. */
+ if (status != NX_SUCCESS)
+ {
+ break;
+ }
+
+ /* Write ABCs into the packet payload! */
+ /* Adjust the write pointer. */
+ if (my_packet -> nx_packet_prepend_ptr + packet_size <= my_packet -> nx_packet_data_end)
+ {
+ my_packet -> nx_packet_append_ptr = my_packet -> nx_packet_prepend_ptr + packet_size;
+#ifndef NX_DISABLE_PACKET_CHAIN
+ remaining_size = 0;
+#endif /* NX_DISABLE_PACKET_CHAIN */
+ }
+ else
+ {
+#ifdef NX_DISABLE_PACKET_CHAIN
+ packet_size = (ULONG)(my_packet -> nx_packet_data_end - my_packet -> nx_packet_prepend_ptr);
+ my_packet -> nx_packet_append_ptr = my_packet -> nx_packet_prepend_ptr + packet_size;
+#else
+ my_packet -> nx_packet_append_ptr = my_packet -> nx_packet_data_end;
+ remaining_size = packet_size - (ULONG)(my_packet -> nx_packet_append_ptr - my_packet -> nx_packet_prepend_ptr);
+ last_packet = my_packet;
+#endif /* NX_DISABLE_PACKET_CHAIN */
+ }
+ my_packet -> nx_packet_length = packet_size;
+
+#ifndef NX_DISABLE_PACKET_CHAIN
+ while (remaining_size)
+ {
+
+ /* Allocate a packet. */
+ status = nx_packet_allocate(nx_iperf_test_pool, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
+
+ /* Check status. */
+ if (status != NX_SUCCESS)
+ {
+ break;
+ }
+
+ last_packet -> nx_packet_next = packet_ptr;
+ last_packet = packet_ptr;
+ if (remaining_size < (ULONG)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr))
+ {
+ packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + remaining_size;
+ }
+ else
+ {
+ packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_data_end;
+ }
+ remaining_size = remaining_size - (ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr);
+ }
+#endif /* NX_DISABLE_PACKET_CHAIN */
+
+ if (is_first)
+ {
+ memset(my_packet -> nx_packet_prepend_ptr, 0, (UINT)(my_packet -> nx_packet_data_end - my_packet -> nx_packet_prepend_ptr));
+ is_first = NX_FALSE;
+ }
+
+ /* Send the packet out! */
+ status = nx_tcp_socket_send(&tcp_client_socket, my_packet, NX_WAIT_FOREVER);
+
+ /* Determine if the status is valid. */
+ if (status)
+ {
+ error_counter++;
+ nx_packet_release(my_packet);
+ break;
+ }
+ else
+ {
+
+ /* Update the counter. */
+ ctrlInfo_ptr -> PacketsTxed++;
+ ctrlInfo_ptr -> BytesTxed += packet_size;
+ }
+ }
+
+ /* Calculate the test time and Throughput(Mbps). */
+ ctrlInfo_ptr -> RunTime = tx_time_get() - ctrlInfo_ptr -> StartTime;
+ ctrlInfo_ptr -> ThroughPut = ctrlInfo_ptr -> BytesTxed / ctrlInfo_ptr -> RunTime * NX_IP_PERIODIC_RATE / 125000;
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ _tx_execution_thread_total_time_get(&thread_time);
+ _tx_execution_isr_time_get(&isr_time);
+ _tx_execution_idle_time_get(&idle_time);
+#endif
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ ctrlInfo_ptr -> idleTime = (ULONG)((unsigned long long)idle_time * 100 / ((unsigned long long)thread_time + (unsigned long long)isr_time + (unsigned long long)idle_time));
+#endif
+
+ /* Disconnect this socket. */
+ status = nx_tcp_socket_disconnect(&tcp_client_socket, NX_NO_WAIT);
+
+ /* Determine if the status is valid. */
+ if (status)
+ {
+ error_counter++;
+ }
+
+ /* Unbind the socket. */
+ status = nx_tcp_client_socket_unbind(&tcp_client_socket);
+
+ /* Check for error. */
+ if (status)
+ {
+ error_counter++;
+ }
+
+ if (error_counter)
+ {
+ ctrlInfo_ptr -> ErrorCode = error_counter;
+ }
+
+ /* Delete the socket. */
+ nx_tcp_socket_delete(&tcp_client_socket);
+}
+
+void nx_iperf_tcp_tx_cleanup(void)
+{
+ nx_tcp_socket_disconnect(&tcp_client_socket, NX_NO_WAIT);
+ nx_tcp_client_socket_unbind(&tcp_client_socket);
+ nx_tcp_socket_delete(&tcp_client_socket);
+
+ tx_thread_terminate(&thread_tcp_tx_iperf);
+ tx_thread_delete(&thread_tcp_tx_iperf);
+}
+
+void nx_iperf_tcp_tx_test(UCHAR *stack_space, ULONG stack_size)
+{
+UINT status;
+
+ status = tx_thread_create(&thread_tcp_tx_iperf, "thread tcp tx",
+ nx_iperf_thread_tcp_tx_entry,
+ (ULONG)&nx_iperf_ctrl_info,
+ stack_space, stack_size, NX_WEB_HTTP_SERVER_PRIORITY + 1, NX_WEB_HTTP_SERVER_PRIORITY + 1,
+ TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ if (status)
+ {
+ nx_iperf_ctrl_info.ErrorCode = 1;
+ }
+ return;
+}
+
+
+void nx_iperf_thread_udp_rx_entry(ULONG thread_input)
+{
+UINT status;
+ULONG expire_time;
+NX_PACKET *my_packet;
+ctrl_info *ctrlInfo_ptr;
+int packetID = 0;
+UINT sender_port;
+ULONG tmp;
+NXD_ADDRESS source_ip_address;
+
+ /* Set the pointer. */
+ ctrlInfo_ptr = (ctrl_info *)thread_input;
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ thread_time = 0;
+ isr_time = 0;
+ idle_time = 0;
+#endif
+
+ /* Update the test result. */
+ ctrlInfo_ptr -> PacketsRxed = 0;
+ ctrlInfo_ptr -> BytesRxed = 0;
+ ctrlInfo_ptr -> ThroughPut = 0;
+ ctrlInfo_ptr -> StartTime = 0;
+ ctrlInfo_ptr -> RunTime = 0;
+ ctrlInfo_ptr -> ErrorCode = 0;
+
+ /* Create a UDP socket. */
+ status = nx_udp_socket_create(nx_iperf_test_ip, &udp_server_socket, "UDP Server Socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
+
+ /* Check status. */
+ if (status)
+ {
+ error_counter++;
+ return;
+ }
+
+ /* Bind the UDP socket to the IP port. */
+ status = nx_udp_socket_bind(&udp_server_socket, NX_IPERF_UDP_RX_PORT, TX_WAIT_FOREVER);
+
+ /* Check status. */
+ if (status)
+ {
+ nx_udp_socket_delete(&udp_server_socket);
+ error_counter++;
+ return;
+ }
+
+ /* Disable checksum for UDP. */
+ nx_udp_socket_checksum_disable(&udp_server_socket);
+
+ /* Receive a UDP packet. */
+ status = nx_udp_socket_receive(&udp_server_socket, &my_packet, TX_WAIT_FOREVER);
+
+ /* Check status. */
+ if (status)
+ {
+ nx_udp_socket_unbind(&udp_server_socket);
+ nx_udp_socket_delete(&udp_server_socket);
+ error_counter++;
+ return;
+ }
+
+ /* Get source ip address*/
+ nxd_udp_source_extract(my_packet, &source_ip_address, &sender_port);
+
+ /* Set the IP address Version. */
+ ctrlInfo_ptr -> version = source_ip_address.nxd_ip_version;
+
+#ifndef NX_DISABLE_IPV4
+ if (ctrlInfo_ptr -> version == NX_IP_VERSION_V4)
+ {
+ ctrlInfo_ptr -> ip = source_ip_address.nxd_ip_address.v4;
+ }
+#endif
+#ifdef FEATURE_NX_IPV6
+ if (ctrlInfo_ptr -> version == NX_IP_VERSION_V6)
+ {
+ ctrlInfo_ptr -> ipv6[0] = source_ip_address.nxd_ip_address.v6[0];
+ ctrlInfo_ptr -> ipv6[1] = source_ip_address.nxd_ip_address.v6[1];
+ ctrlInfo_ptr -> ipv6[2] = source_ip_address.nxd_ip_address.v6[2];
+ ctrlInfo_ptr -> ipv6[3] = source_ip_address.nxd_ip_address.v6[3];
+ }
+#endif
+
+ /* Release the packet. */
+ nx_packet_release(my_packet);
+
+ /* Set the test start time. */
+ ctrlInfo_ptr -> StartTime = tx_time_get();
+ expire_time = (ULONG)(ctrlInfo_ptr -> StartTime + (ctrlInfo_ptr -> TestTime) + 5); /* Wait 5 more ticks to synchronize. */
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ _tx_execution_thread_total_time_reset();
+ _tx_execution_isr_time_reset();
+ _tx_execution_idle_time_reset();
+#endif
+
+ while (tx_time_get() < expire_time)
+ {
+
+ /* Receive a UDP packet. */
+ status = nx_udp_socket_receive(&udp_server_socket, &my_packet, TX_WAIT_FOREVER);
+
+ /* Check status. */
+ if (status != NX_SUCCESS)
+ {
+ error_counter++;
+ break;
+ }
+
+ /* Update the counter. */
+ ctrlInfo_ptr -> PacketsRxed++;
+ ctrlInfo_ptr -> BytesRxed += my_packet -> nx_packet_length;
+
+ /* Detect the end of the test signal. */
+ packetID = *(int *)(my_packet -> nx_packet_prepend_ptr);
+
+ tmp = (ULONG)packetID;
+ NX_CHANGE_ULONG_ENDIAN(tmp);
+ packetID = (int)tmp;
+
+
+ /* Check the packet ID. */
+ if (packetID < 0)
+ {
+
+ /* Test has finished. */
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ _tx_execution_thread_total_time_get(&thread_time);
+ _tx_execution_isr_time_get(&isr_time);
+ _tx_execution_idle_time_get(&idle_time);
+#endif
+
+ /* Calculate the test time and Throughput. */
+ ctrlInfo_ptr -> RunTime = tx_time_get() - ctrlInfo_ptr -> StartTime;
+ ctrlInfo_ptr -> ThroughPut = ctrlInfo_ptr -> BytesRxed / ctrlInfo_ptr -> RunTime * NX_IP_PERIODIC_RATE / 125000;
+
+ /* received end of the test signal */
+
+ /* Send the UDP packet. */
+ status = nxd_udp_socket_send(&udp_server_socket, my_packet, &source_ip_address, sender_port);
+
+ /* Check the status. */
+ if (status)
+ {
+
+ /* Release the packet. */
+ nx_packet_release(my_packet);
+ }
+ else
+ {
+
+ /* Loop to receive the end of the test signal. */
+ while (1)
+ {
+
+ /* Receive a UDP packet. */
+ status = nx_udp_socket_receive(&udp_server_socket, &my_packet, 20);
+
+ /* Check the status. */
+ if (status)
+ {
+ break;
+ }
+
+ /* Send the UDP packet. */
+ status = nxd_udp_socket_send(&udp_server_socket, my_packet, &source_ip_address, sender_port);
+
+ /* Check the status. */
+ if (status)
+ {
+
+ /* Release the packet. */
+ nx_packet_release(my_packet);
+ }
+ }
+ }
+ break;
+ }
+ else
+ {
+
+ /* Release the packet. */
+ nx_packet_release(my_packet);
+ }
+ }
+
+ if (packetID >= 0)
+ {
+
+ /* Test is not synchronized. */
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ _tx_execution_thread_total_time_get(&thread_time);
+ _tx_execution_isr_time_get(&isr_time);
+ _tx_execution_idle_time_get(&idle_time);
+#endif
+
+ /* Calculate the test time and Throughput. */
+ ctrlInfo_ptr -> RunTime = tx_time_get() - ctrlInfo_ptr -> StartTime;
+ ctrlInfo_ptr -> ThroughPut = ctrlInfo_ptr -> BytesRxed / ctrlInfo_ptr -> RunTime * NX_IP_PERIODIC_RATE / 125000;
+ }
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ ctrlInfo_ptr -> idleTime = (ULONG)((unsigned long long)idle_time * 100 / ((unsigned long long)thread_time + (unsigned long long)isr_time + (unsigned long long)idle_time));
+#endif
+
+ /* Unbind and Delete the socket. */
+ nx_udp_socket_unbind(&udp_server_socket);
+ nx_udp_socket_delete(&udp_server_socket);
+
+ /* Check error counter. */
+ if (error_counter)
+ {
+ ctrlInfo_ptr -> ErrorCode = error_counter;
+ }
+}
+
+void nx_iperf_udp_rx_cleanup(void)
+{
+ nx_udp_socket_unbind(&udp_server_socket);
+ nx_udp_socket_delete(&udp_server_socket);
+
+ tx_thread_terminate(&thread_udp_rx_iperf);
+ tx_thread_delete(&thread_udp_rx_iperf);
+}
+
+void nx_iperf_udp_rx_test(UCHAR *stack_space, ULONG stack_size)
+{
+UINT status;
+
+ status = tx_thread_create(&thread_udp_rx_iperf, "thread udp rx",
+ nx_iperf_thread_udp_rx_entry,
+ (ULONG)&nx_iperf_ctrl_info,
+ stack_space, stack_size, NX_WEB_HTTP_SERVER_PRIORITY + 1, NX_WEB_HTTP_SERVER_PRIORITY + 1,
+ TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ if (status)
+ {
+ nx_iperf_ctrl_info.ErrorCode = 1;
+ }
+ return;
+}
+
+static void nx_iperf_send_udp_packet(int udp_id, ctrl_info *ctrlInfo_ptr)
+{
+
+UINT status;
+NX_PACKET *my_packet = NX_NULL;
+udp_payload *payload_ptr;
+ULONG tmp;
+
+NXD_ADDRESS server_ip;
+
+ server_ip.nxd_ip_version = ctrlInfo_ptr -> version;
+
+#ifdef FEATURE_NX_IPV6
+ if (ctrlInfo_ptr -> version == NX_IP_VERSION_V6)
+ {
+ server_ip.nxd_ip_address.v6[0] = ctrlInfo_ptr -> ipv6[0];
+ server_ip.nxd_ip_address.v6[1] = ctrlInfo_ptr -> ipv6[1];
+ server_ip.nxd_ip_address.v6[2] = ctrlInfo_ptr -> ipv6[2];
+ server_ip.nxd_ip_address.v6[3] = ctrlInfo_ptr -> ipv6[3];
+ }
+ else if (ctrlInfo_ptr -> version == NX_IP_VERSION_V4)
+#endif
+ {
+#ifndef NX_DISABLE_IPV4
+ server_ip.nxd_ip_address.v4 = ctrlInfo_ptr -> ip;
+#endif
+ }
+
+ /* Send the end of test indicator. */
+ nx_packet_allocate(nx_iperf_test_pool, &my_packet, NX_UDP_PACKET, TX_WAIT_FOREVER);
+ my_packet -> nx_packet_append_ptr = my_packet -> nx_packet_prepend_ptr + ctrlInfo_ptr -> PacketSize;
+
+ payload_ptr = (udp_payload *)my_packet -> nx_packet_prepend_ptr;
+ payload_ptr -> udp_id = udp_id;
+ payload_ptr -> tv_sec = _tx_timer_system_clock / NX_IP_PERIODIC_RATE;
+ payload_ptr -> tv_usec = _tx_timer_system_clock / NX_IP_PERIODIC_RATE * 1000000;
+
+ tmp = (ULONG)payload_ptr -> udp_id;
+ NX_CHANGE_ULONG_ENDIAN(tmp);
+ payload_ptr -> udp_id = (int)tmp;
+
+ NX_CHANGE_ULONG_ENDIAN(payload_ptr -> tv_sec);
+ NX_CHANGE_ULONG_ENDIAN(payload_ptr -> tv_usec);
+
+ /* Adjust the write pointer. */
+ my_packet -> nx_packet_length = (UINT)(ctrlInfo_ptr -> PacketSize);
+
+ /* Send the UDP packet. */
+ status = nxd_udp_socket_send(&udp_client_socket, my_packet, &server_ip, ctrlInfo_ptr -> port);
+
+ /* Check the status. */
+ if (status)
+ {
+
+ /* Release the packet. */
+ nx_packet_release(my_packet);
+ return;
+ }
+}
+
+void nx_iperf_thread_udp_tx_entry(ULONG thread_input)
+{
+UINT status;
+ULONG expire_time;
+ctrl_info *ctrlInfo_ptr;
+NX_PACKET *my_packet;
+int i;
+long udp_id;
+
+ /* Initialize the value. */
+ udp_id = 0;
+ ctrlInfo_ptr = (ctrl_info *)thread_input;
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ thread_time = 0;
+ isr_time = 0;
+ idle_time = 0;
+#endif
+
+ ctrlInfo_ptr -> PacketsTxed = 0;
+ ctrlInfo_ptr -> BytesTxed = 0;
+ ctrlInfo_ptr -> ThroughPut = 0;
+ ctrlInfo_ptr -> StartTime = 0;
+ ctrlInfo_ptr -> RunTime = 0;
+ ctrlInfo_ptr -> ErrorCode = 0;
+
+ /* UDP Transmit Test Starts in 2 seconds. */
+ tx_thread_sleep(200);
+
+ /* Create a UDP socket. */
+ status = nx_udp_socket_create(nx_iperf_test_ip, &udp_client_socket, "UDP Client Socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
+
+ /* Check status. */
+ if (status)
+ {
+ error_counter++;
+ return;
+ }
+
+ /* Bind the UDP socket to the IP port. */
+ status = nx_udp_socket_bind(&udp_client_socket, NX_ANY_PORT, TX_WAIT_FOREVER);
+
+ /* Check status. */
+ if (status)
+ {
+ nx_udp_socket_delete(&udp_client_socket);
+ error_counter++;
+ return;
+ }
+
+ /* Do not calculate checksum for UDP. */
+ nx_udp_socket_checksum_disable(&udp_client_socket);
+
+ /* Set the test start time. */
+ ctrlInfo_ptr -> StartTime = tx_time_get();
+ expire_time = (ULONG)(ctrlInfo_ptr -> StartTime + (ctrlInfo_ptr -> TestTime));
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ _tx_execution_thread_total_time_reset();
+ _tx_execution_isr_time_reset();
+ _tx_execution_idle_time_reset();
+#endif
+
+ while (tx_time_get() < expire_time)
+ {
+
+ /* Write ABCs into the packet payload! */
+ nx_iperf_send_udp_packet(udp_id, ctrlInfo_ptr);
+
+ /* Update the ID. */
+ udp_id = (udp_id + 1) & 0x7FFFFFFF;
+
+ /* Update the counter. */
+ ctrlInfo_ptr -> PacketsTxed++;
+ ctrlInfo_ptr -> BytesTxed += ctrlInfo_ptr -> PacketSize;
+ }
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ _tx_execution_thread_total_time_get(&thread_time);
+ _tx_execution_isr_time_get(&isr_time);
+ _tx_execution_idle_time_get(&idle_time);
+#endif
+
+ /* Calculate the test time and Throughput. */
+ ctrlInfo_ptr -> RunTime = tx_time_get() - ctrlInfo_ptr -> StartTime;
+ ctrlInfo_ptr -> ThroughPut = ctrlInfo_ptr -> BytesTxed / ctrlInfo_ptr -> RunTime * NX_IP_PERIODIC_RATE / 125000;
+
+#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
+ ctrlInfo_ptr -> idleTime = (ULONG)((unsigned long long)idle_time * 100 / ((unsigned long long)thread_time + (unsigned long long)isr_time + (unsigned long long)idle_time));
+#endif
+
+ if (error_counter)
+ {
+ ctrlInfo_ptr -> ErrorCode = error_counter;
+ }
+
+ ctrlInfo_ptr -> PacketSize = 100;
+ for (i = 0; i < 10; i++)
+ {
+ /* Send the end of the test signal*/
+ nx_iperf_send_udp_packet((0 - udp_id), ctrlInfo_ptr);
+
+ /* Receive the packet. s*/
+ if (nx_udp_socket_receive(&udp_client_socket, &my_packet, 10) == NX_SUCCESS)
+ {
+ nx_packet_release(my_packet);
+ break;
+ }
+ }
+
+ /* Unbind and Delete the socket. */
+ nx_udp_socket_unbind(&udp_client_socket);
+ nx_udp_socket_delete(&udp_client_socket);
+}
+
+void nx_iperf_udp_tx_cleanup(void)
+{
+ nx_udp_socket_unbind(&udp_client_socket);
+ nx_udp_socket_delete(&udp_client_socket);
+ tx_thread_terminate(&thread_udp_tx_iperf);
+ tx_thread_delete(&thread_udp_tx_iperf);
+}
+
+void nx_iperf_udp_tx_test(UCHAR *stack_space, ULONG stack_size)
+{
+UINT status;
+
+ status = tx_thread_create(&thread_udp_tx_iperf, "thread udp tx",
+ nx_iperf_thread_udp_tx_entry,
+ (ULONG)&nx_iperf_ctrl_info,
+ stack_space, stack_size, NX_WEB_HTTP_SERVER_PRIORITY + 1, NX_WEB_HTTP_SERVER_PRIORITY + 1,
+ TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ if (status)
+ {
+ nx_iperf_ctrl_info.ErrorCode = 1;
+ }
+ return;
+}
+
diff --git a/utility/iperf/nx_iperf.h b/utility/iperf/nx_iperf.h
new file mode 100644
index 00000000..fc449dec
--- /dev/null
+++ b/utility/iperf/nx_iperf.h
@@ -0,0 +1,2218 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** NetX Utility */
+/** */
+/** NetX Duo IPerf Test Program */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+/* Enable authentication.
+#define NX_IPERF_AUTH_ENABLE
+*/
+
+#ifndef NX_IPERF_TCP_RX_PORT
+#define NX_IPERF_TCP_RX_PORT 5001
+#endif
+
+#ifndef NX_IPERF_UDP_RX_PORT
+#define NX_IPERF_UDP_RX_PORT 5001
+#endif
+
+#ifndef NX_IPERF_DESTINATION_PORT
+#define NX_IPERF_DESTINATION_PORT 5001
+#endif
+
+#ifndef NX_IPERF_THREAD_PRIORITY
+#define NX_IPERF_THREAD_PRIORITY 1
+#endif
+
+#ifndef ULONG64_DEFINED
+#define ULONG64_DEFINED
+#define ULONG64 unsigned long long
+#endif
+
+#define NX_IPERF_CTRL_SIGN_MASK 0x0F
+#define NX_IPERF_CLEAN_UP_MASK 0x01
+
+typedef struct
+{
+ ULONG CmdID;
+ ULONG version;
+ ULONG ip;
+ ULONG ipv6[4];
+ ULONG port;
+ UCHAR ctrl_sign;
+ UINT ErrorCode;
+ ULONG WperfPort;
+ ULONG64 PacketsTxed;
+ ULONG64 PacketsRxed;
+ ULONG64 BytesTxed;
+ ULONG64 BytesRxed;
+ ULONG64 StartTime;
+ ULONG64 RunTime;
+ ULONG64 TestTime;
+ ULONG64 ThroughPut;
+ ULONG64 PacketSize;
+ ULONG64 Rate;
+ UINT TestStatus; /* 0 means no test is running.
+ 1 means Test Thread is created and is running.
+ 2 means a test has finished. */
+ ULONG64 idleTime;
+} ctrl_info;
+
+/*test list for wperf*/
+typedef struct
+{
+ ULONG cmdID;
+ ULONG threadID;
+} thread_list;
+
+/* test type enum */
+enum testTypeList
+{
+ UNKNOWN_TEST = 0,
+ TCP_RX_START = 1,
+ UDP_RX_START = 3,
+ TCP_TX_START = 5,
+ UDP_TX_START = 7,
+
+ UDP_RX_STOP,
+ TCP_RX_STOP,
+ UDP_TX_STOP,
+ TCP_TX_STOP
+};
+
+enum errorCodeList
+{
+ UDP_RX_STOP_ERROR = 5000,
+ UDP_RX_CREATE_ERROR,
+ UDP_TX_STOP_ERROR,
+ UDP_TX_CREATE_ERROR,
+ TCP_RX_STOP_ERROR,
+ TCP_RX_CREATE_ERROR,
+ TCP_TX_STOP_ERROR,
+ TCP_TX_CREATE_ERROR
+};
+
+typedef struct
+{
+ int udp_id;
+ ULONG tv_sec;
+ ULONG tv_usec;
+} udp_payload;
+
+#define htmlwrite(p, s, l) (nx_packet_data_append(p, s, l, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER))
+
+#define htmlresponse "HTTP/1.0 200 \r\nContent-Type: text/html\r\n\r\n"
+#define htmltag "<HTML>"
+#define htmlendtag "</HTML>"
+#define titleline "<HEAD><TITLE>NetX IPerf Demonstration</TITLE></HEAD>\r\n"
+
+#define bodytag "<body bgcolor=\"#000000\">\r\n"
+#define bodyendtag "</body>\r\n"
+
+#define logo_area \
+ "<table border=0 align=center width=90%><tr>" \
+ "<td width=30%><img align=left src=mslogo.jpg>" \
+ "</td><td width=33%></td><td width=33%><img align=right src=nxlogo.png></td></tr></table>"
+
+#define hrline "<HR SIZE=6 WIDTH=\"90%\" NOSHADE COLOR=\"#FFFF00\">"
+#define h1line1 " <H1><font face=arial color=\"#FFFFFF\">NetX IP Address: "
+#define h1line2 "</font></H1><br>\r\n"
+#define tabletag "<table height=50%>"
+#define fonttag "<font face=arial color=\"#FFFFFF\" size=\"5\">"
+#define fontcolortag "<font face=arial color=\"#FFFF00\" size=\"5\">"
+#define fontendtag "</font>"
+
+#define centertag "<center WIDTH=\"90%\">\r\n"
+#define centerendtag "</center>"
+#define outtermosttable "<table width=80% border=0 bordercolor=#ffff00 rules=cols color=#FFFF00 farme=void><tr><td width=55%>\r\n"
+#define maintabletag "<TABLE BORDER=0 ALIGN=left WIDTH=85% ><TR><TD colspan=4>\r\n"
+#define tableendtag "</TABLE>"
+#define trtag "<TR>"
+#define trendtag "</TR>"
+#define tdtag "<TD>"
+#define toptdtag "<TD align=center style=\"vertical-align:top;\">"
+#define tdcolspan4tag "<TD colspan=\"4\">"
+#define tdcolspan3tag "<TD colspan=\"3\">"
+#define tdcolspan2tag "<TD colspan=\"2\">"
+#define tdendtag "</TD>\r\n"
+#define doublebr "<br><br>\r\n"
+#define spanline "<TR><TD colspan=\"4\"><br><br></TD></TR>"
+#define rightspanline "<TR><TD><br><br></TD></TR>"
+#define tdcentertag "<TD align=center>"
+
+
+#define formtag "<form action=\"/test.htm\" method=\"get\">"
+#define formendtag "</form>"
+
+#define UDPTXSTRING "Start UDP Transmit Test"
+#define UDP_Tx "UDP_Tx"
+#define udptxsubmittag1 \
+ "<form action=\"/test.htm\" method=\"get\">\r\n" \
+ "<TR><TD><input type=\"submit\" Value=\""UDPTXSTRING "\" style= \"background-color:#FFFF00; " \
+ "font-size:19px; font-weight: bold\"></TD></TR>\r\n" \
+ "<TR><TD><input type=\"hidden\" name=\"TestType\" value=\""UDP_Tx "\"></input></TD></TR>" \
+ "<TR><TD>"fonttag "Destination IP Address:</font></TD>\r\n" \
+ "<TD><input name=\"ip\" value=\""
+
+#define udptxsubmittag2 \
+ "\"></input></TD></TR>\r\n" \
+ "<TR><TD>"fonttag "Destination Port:</font></TD>\r\n" \
+ "<TD><input name=\"port\" value=\""
+
+#define udptxsubmittag3 \
+ "\"></input></TD></TR>\r\n" \
+ "<TR><TD>"fonttag "Test Time(Seconds):</font></TD>\r\n" \
+ "<TD><input name=\"test_time\" value=\""
+
+#define udptxsubmittag4 \
+ "\"></input></TD></TR>\r\n" \
+ "<TR><TD>"fonttag "Packet size:</font></TD>\r\n" \
+ "<TD><input name=\"size\" value=\""
+
+#define udptxsubmittag5 \
+ "\"></input></TD></TR>\r\n" \
+ "</form><TR><TD colspan=\"4\"><br><br></TD></TR>\r\n"
+
+#define UDPRXSTRING "Start UDP Receive Test"
+#define UDP_Rx "UDP_Rx"
+#define udprxsubmittag1 \
+ "<form action=\"/test.htm\" method=\"get\">\r\n" \
+ "<TR><TD><input type=\"submit\" Value=\""UDPRXSTRING "\" style= \"background-color:#FFFF00; font-size:19px; font-weight: bold\"></TD></TR>\r\n" \
+ "<TR><TD><input type=\"hidden\" name=\"TestType\" value=\""UDP_Rx "\"></input></TD></TR>" \
+ "<TR><TD>"fonttag "Test Time(Seconds):</font></TD>\r\n" \
+ "<TD><input name=\"test_time\" value=\""
+
+#define udprxsubmittag2 \
+ "\"></input></TD></TR></form>\r\n" \
+ "<TR><TD colspan=\"4\"><br><br></TD></TR>\r\n"
+
+#define TCP_Tx "TCP_Tx"
+#define tcptxsubmittag1 \
+ "<form action=\"/test.htm\" method=\"get\">\r\n" \
+ "<TR><TD><input type=\"submit\" Value=\"Start TCP Transmit Test\" style= \"background-color:#FFFF00; font-size:19px; font-weight: bold\"></TD></TR>\r\n" \
+ "<TR><TD><input type=\"hidden\" name=\"TestType\" value=\""TCP_Tx "\"></input></TD></TR>" \
+ "<TR><TD>"fonttag "Destination IP Address:</font></TD>\r\n" \
+ "<TD><input name=\"ip\" value=\""
+
+#define tcptxsubmittag2 \
+ "\"></input></TD></TR>\r\n" \
+ "<TR><TD>"fonttag "Destination Port:</font></TD>\r\n" \
+ "<TD><input name=\"port\" value=\""
+
+#define tcptxsubmittag3 \
+ "\"></input></TD></TR>\r\n" \
+ "<TR><TD>"fonttag "Test Time(Seconds):</font></TD>\r\n" \
+ "<TD><input name=\"test_time\" value=\""
+
+#define tcptxsubmittag4 \
+ "\"></input></TD></TR>\r\n" \
+ "</form><TR><TD colspan=\"4\"><br><br></TD></TR>\r\n"
+
+#define TCP_Rx "TCP_Rx"
+#define tcprxsubmittag1 \
+ "<form action=\"/test.htm\" method=\"get\">\r\n" \
+ "<TR><TD><input type=\"submit\" Value=\"Start TCP Receive Test\" style= \"background-color:#FFFF00; font-size:19px; font-weight: bold\"></TD></TR>\r\n" \
+ "<TR><TD><input type=\"hidden\" name=\"TestType\" value=\""TCP_Rx "\"></input></TD></TR>" \
+ "<TR><TD>"fonttag "Test Time(Seconds):</font></TD>\r\n" \
+ "<TD><input name=\"test_time\" value=\""
+
+#define tcprxsubmittag2 \
+ "\"></input></TD></TR>\r\n" \
+ "</form>\r\n<TR><TD colspan=\"4\"><br><br></TD></TR>\r\n"
+
+#define choosetesttag \
+ "<TD align=center><font align=center face=arial color=\"#FFFFFF\" size=\"5\">Choose a test from the left.</font></TD>\r\n"
+
+const unsigned char mslogo_jpg[] = {
+ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
+ 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
+ 0x00, 0x00, 0x01, 0xd7, 0x00, 0x00, 0x00, 0x9c,
+ 0x08, 0x06, 0x00, 0x00, 0x00, 0x2d, 0x6c, 0xe1,
+ 0xda, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47,
+ 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00,
+ 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00,
+ 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00,
+ 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00,
+ 0x2e, 0x22, 0x00, 0x00, 0x2e, 0x22, 0x01, 0xaa,
+ 0xe2, 0xdd, 0x92, 0x00, 0x00, 0x19, 0xc7, 0x49,
+ 0x44, 0x41, 0x54, 0x78, 0x5e, 0xed, 0xdd, 0x07,
+ 0xb8, 0x2c, 0x67, 0x5d, 0xc7, 0xf1, 0x7b, 0x91,
+ 0x2a, 0x10, 0x08, 0x08, 0xa1, 0xb7, 0x18, 0x20,
+ 0x14, 0xe9, 0x01, 0x44, 0x40, 0x5a, 0x00, 0x43,
+ 0x53, 0x8c, 0x08, 0x04, 0x43, 0x4d, 0x10, 0x94,
+ 0x26, 0x20, 0xc2, 0x23, 0x21, 0x54, 0x45, 0x10,
+ 0x69, 0x81, 0x50, 0x05, 0x42, 0x53, 0xe0, 0x41,
+ 0x50, 0x90, 0xa0, 0x14, 0x41, 0x41, 0x88, 0x0a,
+ 0xc6, 0x12, 0x5a, 0x10, 0x41, 0xa2, 0xb4, 0x20,
+ 0xd2, 0x04, 0x21, 0xfe, 0xbe, 0xb3, 0xb3, 0xcb,
+ 0xec, 0xbb, 0xef, 0xec, 0xee, 0xec, 0xd9, 0xbd,
+ 0xf7, 0x9c, 0x73, 0xbf, 0x9f, 0xe7, 0xf9, 0x9f,
+ 0x99, 0xdd, 0x9d, 0x99, 0xdd, 0xb3, 0x3b, 0x33,
+ 0xef, 0xbc, 0x75, 0xf6, 0x48, 0x92, 0x24, 0x49,
+ 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24,
+ 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92,
+ 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49,
+ 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24,
+ 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92,
+ 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49,
+ 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24,
+ 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92,
+ 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49,
+ 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24,
+ 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92,
+ 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49,
+ 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24,
+ 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92,
+ 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49,
+ 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24,
+ 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92,
+ 0x24, 0x49, 0x3a, 0xa0, 0xec, 0x6d, 0xa7, 0xbb,
+ 0xc2, 0x37, 0xee, 0x76, 0x15, 0xfe, 0x9f, 0x7f,
+ 0x4d, 0x5c, 0xa2, 0x79, 0x62, 0x33, 0xce, 0x3a,
+ 0xe8, 0xad, 0x67, 0x5e, 0x8b, 0x99, 0x13, 0x4e,
+ 0xdd, 0x73, 0x52, 0x26, 0xf7, 0x60, 0x7e, 0x83,
+ 0x8e, 0x38, 0xf1, 0xc8, 0x3d, 0x9f, 0x69, 0xe7,
+ 0x25, 0x49, 0x3b, 0xc0, 0xb9, 0xda, 0xe9, 0x6e,
+ 0x72, 0xd1, 0xc4, 0xc5, 0x36, 0x18, 0x07, 0x27,
+ 0xc6, 0x2e, 0x94, 0xa8, 0x2d, 0xb3, 0xce, 0xd8,
+ 0x8d, 0xbf, 0x91, 0x24, 0xed, 0x6a, 0x9e, 0xb8,
+ 0x25, 0x49, 0x5a, 0x33, 0x13, 0x57, 0x49, 0x92,
+ 0xd6, 0xcc, 0xc4, 0x55, 0x92, 0xa4, 0x35, 0x33,
+ 0x71, 0x95, 0x24, 0x69, 0xcd, 0x4c, 0x5c, 0x25,
+ 0x49, 0x5a, 0x33, 0x13, 0x57, 0x49, 0x92, 0xd6,
+ 0xcc, 0xc4, 0x55, 0xd2, 0xda, 0x9c, 0x73, 0xce,
+ 0x39, 0x17, 0x49, 0x1c, 0x9b, 0x78, 0x45, 0xe2,
+ 0xbd, 0x89, 0x0f, 0x27, 0xde, 0x9d, 0x38, 0x39,
+ 0x71, 0x58, 0xbb, 0x98, 0xb4, 0xeb, 0x99, 0xb8,
+ 0x6a, 0xbf, 0xc9, 0xc9, 0x76, 0x6f, 0xe2, 0xd2,
+ 0x89, 0xab, 0x25, 0xce, 0xdb, 0x3e, 0xad, 0x1d,
+ 0xa8, 0xfd, 0x2d, 0x7f, 0x35, 0xb3, 0x9f, 0x4e,
+ 0xfc, 0x61, 0xe2, 0x7e, 0x89, 0x9f, 0x4d, 0xdc,
+ 0x38, 0x71, 0xdb, 0xc4, 0x71, 0x89, 0xeb, 0x24,
+ 0xa4, 0x03, 0xc2, 0x6e, 0x1c, 0xa1, 0xe9, 0xac,
+ 0xc4, 0x21, 0xcd, 0x13, 0x9b, 0xf1, 0xc5, 0x83,
+ 0xde, 0x7a, 0xe6, 0x65, 0x99, 0x39, 0xe1, 0xd4,
+ 0x3d, 0xaf, 0xce, 0xe4, 0x3e, 0xcc, 0x6f, 0xd0,
+ 0x55, 0x4f, 0x3c, 0x72, 0xcf, 0xa7, 0xda, 0xf9,
+ 0x41, 0x72, 0xb2, 0x23, 0xa7, 0x30, 0x6f, 0x04,
+ 0xa9, 0xd3, 0xf6, 0xee, 0xdd, 0xfb, 0xe7, 0xed,
+ 0xfc, 0xca, 0xf2, 0x3e, 0x0c, 0xa6, 0xf1, 0xf0,
+ 0x44, 0xdf, 0xfe, 0xf4, 0xfe, 0xbc, 0xcf, 0x07,
+ 0xda, 0xf9, 0x46, 0xd6, 0x61, 0x80, 0x0c, 0x4e,
+ 0xc2, 0x47, 0x25, 0xb8, 0xc8, 0xfb, 0x8f, 0xc4,
+ 0x71, 0x59, 0xee, 0x1d, 0x99, 0x6a, 0x07, 0xc9,
+ 0x6f, 0xc9, 0xef, 0xf7, 0xc2, 0xc4, 0x83, 0x9b,
+ 0x27, 0xfa, 0x1d, 0x9d, 0xdf, 0xf7, 0x4d, 0xed,
+ 0xfc, 0x7e, 0x91, 0xcf, 0xca, 0xe4, 0x81, 0x89,
+ 0x4b, 0x31, 0x53, 0xf8, 0x40, 0x3e, 0xdf, 0xfb,
+ 0xdb, 0x79, 0x69, 0x4b, 0x4c, 0x5c, 0x87, 0xdb,
+ 0x49, 0x89, 0xeb, 0x9d, 0x33, 0x79, 0xdb, 0xe8,
+ 0x51, 0x15, 0xb9, 0x8c, 0xc3, 0x73, 0x42, 0xf9,
+ 0xbf, 0xd1, 0xc3, 0xd5, 0xe4, 0x7d, 0x38, 0x59,
+ 0xbd, 0x74, 0xf4, 0xa8, 0xea, 0x89, 0x79, 0x8f,
+ 0xa7, 0xb4, 0xf3, 0x8d, 0xac, 0xf3, 0xc7, 0x99,
+ 0xfc, 0xe2, 0xe8, 0xd1, 0xc4, 0xb7, 0x12, 0xd7,
+ 0xcc, 0xb2, 0x9f, 0x1b, 0x3d, 0xd4, 0x4e, 0x90,
+ 0xdf, 0xf2, 0x31, 0x99, 0x3c, 0x73, 0xf4, 0x68,
+ 0xae, 0xed, 0x90, 0xb8, 0x5e, 0x26, 0x93, 0xcf,
+ 0x26, 0x6a, 0x25, 0x25, 0x7f, 0x9b, 0xb8, 0x69,
+ 0x3e, 0x63, 0x93, 0x02, 0x4b, 0x5b, 0x61, 0xb1,
+ 0xf0, 0x81, 0xed, 0x27, 0x13, 0xb7, 0x18, 0xcd,
+ 0xae, 0x26, 0x27, 0x2b, 0x2e, 0x68, 0x8e, 0x1f,
+ 0x3d, 0x5a, 0x4e, 0xd6, 0x39, 0x4f, 0x26, 0x77,
+ 0x1c, 0x3d, 0x9a, 0x72, 0xc1, 0xc4, 0xed, 0x47,
+ 0xb3, 0xda, 0x09, 0xf2, 0x5b, 0x72, 0xa1, 0xf9,
+ 0xc4, 0xd1, 0xa3, 0x19, 0x67, 0x26, 0xde, 0x90,
+ 0xe0, 0x42, 0x8a, 0xf9, 0xaa, 0x6c, 0xe3, 0x7c,
+ 0x89, 0xcb, 0xb7, 0x0f, 0x37, 0xed, 0xde, 0x89,
+ 0xbe, 0x2a, 0x88, 0x1b, 0x25, 0xae, 0x31, 0x9a,
+ 0x95, 0xb6, 0xc6, 0xc4, 0x55, 0x0f, 0x68, 0xa7,
+ 0xab, 0xe2, 0x84, 0x74, 0x83, 0xd1, 0xec, 0xd2,
+ 0xc8, 0x19, 0xf4, 0xe5, 0x96, 0xff, 0xb7, 0x9d,
+ 0x6a, 0x67, 0x20, 0xb1, 0xa2, 0x5a, 0xa0, 0xf4,
+ 0x07, 0x89, 0xab, 0x27, 0x17, 0x78, 0xcf, 0xc4,
+ 0x2f, 0x65, 0xfe, 0x6a, 0x89, 0x49, 0x15, 0x44,
+ 0x12, 0xd3, 0x8b, 0x26, 0x8e, 0x4e, 0xbc, 0x26,
+ 0x0f, 0x3f, 0x9f, 0xf8, 0xed, 0xe6, 0x85, 0x0d,
+ 0xca, 0x7b, 0x71, 0xbe, 0x9b, 0x57, 0xd2, 0xc4,
+ 0xeb, 0xbf, 0x32, 0x9a, 0x95, 0xb6, 0xc6, 0xc4,
+ 0x55, 0x77, 0xcd, 0x49, 0xe7, 0xe2, 0xed, 0xfc,
+ 0x2a, 0xc8, 0xb5, 0x0e, 0xaa, 0x5e, 0xc8, 0xc9,
+ 0x96, 0x84, 0x95, 0xfa, 0xd6, 0x12, 0x45, 0xfa,
+ 0x7f, 0x36, 0x9a, 0xd5, 0x0e, 0x71, 0xab, 0x76,
+ 0xda, 0xc5, 0x5d, 0x9c, 0x1e, 0x9b, 0xdf, 0xf9,
+ 0xfb, 0xa3, 0x87, 0xa3, 0xdf, 0x3c, 0xf1, 0x4d,
+ 0xe6, 0xb3, 0xbf, 0x3d, 0x3b, 0x93, 0x2f, 0x26,
+ 0xfe, 0x28, 0x71, 0x4c, 0x82, 0xbb, 0x58, 0xed,
+ 0x8b, 0x2a, 0xaa, 0x1b, 0x26, 0x9a, 0x3b, 0x5a,
+ 0xcd, 0x71, 0xaf, 0x7c, 0x3e, 0x1b, 0xd7, 0x69,
+ 0xcb, 0x4c, 0x5c, 0x45, 0x51, 0xec, 0x2f, 0x8f,
+ 0x66, 0x87, 0xc9, 0x49, 0x88, 0x3b, 0x10, 0xad,
+ 0xb4, 0x6e, 0x3c, 0x36, 0xf1, 0x8c, 0x04, 0x0d,
+ 0x99, 0xfe, 0x3b, 0xf1, 0xae, 0xc4, 0x6d, 0x72,
+ 0x02, 0xfe, 0x4a, 0xa6, 0xda, 0x39, 0xae, 0xd2,
+ 0x4e, 0xbb, 0xde, 0xdd, 0x4d, 0x58, 0x2b, 0xae,
+ 0x99, 0xb8, 0xc0, 0x68, 0x76, 0x9f, 0x3a, 0x36,
+ 0xb1, 0x28, 0x11, 0xbf, 0x5c, 0x82, 0xd6, 0xcd,
+ 0xd2, 0x96, 0x98, 0xb8, 0x0a, 0xf7, 0x4f, 0x42,
+ 0xd9, 0xce, 0x0e, 0xc2, 0xc9, 0xea, 0xc7, 0x47,
+ 0xb3, 0xc3, 0xe4, 0xe4, 0xfb, 0xbd, 0xc4, 0xe3,
+ 0x33, 0x7b, 0x85, 0xc4, 0x4f, 0x24, 0xee, 0x90,
+ 0xc7, 0xdc, 0x8b, 0x57, 0x3b, 0x0b, 0x17, 0x67,
+ 0x25, 0x72, 0xa5, 0xdb, 0x4a, 0xf6, 0x6f, 0xf6,
+ 0x53, 0x8a, 0xa7, 0xbb, 0x7e, 0x98, 0x38, 0x6d,
+ 0x34, 0x3b, 0xe5, 0xbe, 0xed, 0x54, 0x5a, 0x99,
+ 0x89, 0xeb, 0x81, 0xe7, 0x0b, 0x09, 0x4e, 0x2a,
+ 0x5d, 0xd7, 0x4b, 0x0c, 0xaa, 0x37, 0xcd, 0xc9,
+ 0xea, 0xc7, 0x32, 0x79, 0xd0, 0xe8, 0xd1, 0xc4,
+ 0x7f, 0x26, 0x06, 0xd5, 0x99, 0x26, 0x41, 0xfd,
+ 0x61, 0x82, 0x22, 0xc3, 0xf6, 0x19, 0xed, 0x02,
+ 0x3f, 0x68, 0xa7, 0xdb, 0x09, 0x5d, 0xbe, 0xb8,
+ 0x88, 0xeb, 0xfa, 0x87, 0xc4, 0x93, 0x47, 0xb3,
+ 0x53, 0xee, 0x94, 0xfd, 0x9b, 0xa2, 0x6a, 0x69,
+ 0x65, 0x26, 0xae, 0x07, 0x1e, 0x72, 0x87, 0x1f,
+ 0x1a, 0xcd, 0x4e, 0x90, 0xb2, 0xd1, 0xe9, 0x7f,
+ 0x88, 0x9b, 0x27, 0x28, 0xde, 0xeb, 0xa2, 0x1e,
+ 0x75, 0x9f, 0x9e, 0x58, 0x49, 0xe4, 0x13, 0x17,
+ 0x4b, 0x1c, 0x9e, 0xb8, 0x41, 0x82, 0x01, 0x29,
+ 0x2e, 0x9c, 0xd8, 0x52, 0x6a, 0xcd, 0xfa, 0x89,
+ 0xf3, 0xb4, 0xb1, 0x70, 0x5b, 0x59, 0x86, 0x38,
+ 0x77, 0xe2, 0x12, 0x89, 0xc3, 0x12, 0x57, 0x4d,
+ 0x5c, 0x92, 0xe7, 0xda, 0x45, 0x56, 0x96, 0x6d,
+ 0x9c, 0x2b, 0x71, 0xf1, 0xc4, 0xb5, 0x12, 0xd7,
+ 0x4f, 0x5c, 0x25, 0x71, 0xfe, 0xc4, 0x4a, 0xff,
+ 0x23, 0xeb, 0x25, 0x2e, 0x90, 0xb8, 0x6c, 0xe2,
+ 0xea, 0x09, 0xb6, 0x77, 0x50, 0x62, 0x37, 0x9f,
+ 0x0f, 0x6a, 0xb9, 0x51, 0x5a, 0x32, 0xbf, 0x3b,
+ 0xf1, 0xa5, 0xe6, 0xd1, 0x8f, 0x50, 0x64, 0x5d,
+ 0xe6, 0x72, 0x0f, 0x48, 0xd9, 0x27, 0x86, 0x1e,
+ 0x07, 0x2c, 0x4f, 0xeb, 0x6f, 0x8e, 0xc9, 0x83,
+ 0x13, 0xe7, 0xe5, 0xb9, 0xf6, 0xe5, 0x03, 0xca,
+ 0xae, 0xfa, 0xa7, 0xed, 0xe7, 0x3a, 0x2d, 0x3b,
+ 0x75, 0xad, 0x9f, 0xeb, 0xa9, 0x89, 0x53, 0x12,
+ 0x7c, 0xf6, 0xae, 0xb3, 0x13, 0x97, 0x4d, 0x0e,
+ 0xf2, 0x3b, 0xa3, 0x87, 0xf3, 0x65, 0xdb, 0x9c,
+ 0x98, 0xba, 0x03, 0x54, 0x90, 0xa8, 0x92, 0xd8,
+ 0xfe, 0x7d, 0xa2, 0x2c, 0x2a, 0xae, 0xf5, 0x73,
+ 0xbd, 0x6b, 0x26, 0x65, 0x3f, 0xd7, 0x2f, 0x66,
+ 0xb9, 0xdf, 0x6c, 0xe7, 0x7b, 0x71, 0xc0, 0x66,
+ 0xf2, 0x0b, 0x09, 0xd6, 0xff, 0xe9, 0xc4, 0xa5,
+ 0x13, 0x5d, 0x34, 0x98, 0xfa, 0x44, 0xe2, 0x9d,
+ 0x89, 0x57, 0x67, 0x9b, 0xa7, 0xf3, 0x24, 0xb2,
+ 0x2e, 0x8d, 0xb7, 0x68, 0xc9, 0x5a, 0x7a, 0x52,
+ 0x96, 0xfb, 0x4c, 0x5e, 0xbf, 0x64, 0xe6, 0x1f,
+ 0x9d, 0xe0, 0xbb, 0xa3, 0x7b, 0x08, 0xe5, 0xe5,
+ 0xac, 0x7f, 0xcb, 0xbc, 0x3e, 0x53, 0x8f, 0x98,
+ 0xe5, 0xaf, 0x98, 0x09, 0x8d, 0x72, 0xee, 0x90,
+ 0xb8, 0x76, 0xe2, 0x22, 0x89, 0xae, 0x6f, 0x24,
+ 0xc8, 0x21, 0xfd, 0x69, 0xe2, 0x55, 0xd9, 0xc6,
+ 0x97, 0x79, 0x72, 0x19, 0xd9, 0x36, 0xdb, 0x63,
+ 0xd4, 0x23, 0xba, 0x2d, 0xf1, 0x3e, 0xdd, 0xe3,
+ 0xf5, 0x7b, 0x89, 0x4f, 0x26, 0xde, 0x9b, 0x78,
+ 0x7e, 0xb6, 0x3b, 0x77, 0x1f, 0xc9, 0xb6, 0x58,
+ 0x97, 0x6e, 0x57, 0xd4, 0x91, 0xdf, 0x32, 0x41,
+ 0x37, 0x2c, 0xba, 0x44, 0x8d, 0xf1, 0x7f, 0x52,
+ 0xff, 0xfd, 0x37, 0x09, 0x1a, 0x1a, 0xbd, 0xad,
+ 0xe7, 0xff, 0xa5, 0xb4, 0xa2, 0xdb, 0x7d, 0x8b,
+ 0xdf, 0xa1, 0xfc, 0xbd, 0x3f, 0x96, 0xf8, 0xa7,
+ 0xd1, 0x6c, 0xd5, 0xad, 0x13, 0xf4, 0x37, 0xed,
+ 0xa2, 0xcf, 0xf5, 0x87, 0x47, 0xb3, 0x13, 0xdf,
+ 0xca, 0x67, 0x58, 0x34, 0x30, 0xc5, 0x42, 0xf9,
+ 0xcc, 0xbc, 0xd7, 0xbf, 0x27, 0x28, 0x6d, 0x19,
+ 0x63, 0x7f, 0xbd, 0x72, 0xb6, 0xff, 0xf9, 0xbc,
+ 0xfe, 0xe2, 0xcc, 0x97, 0xdd, 0xc9, 0x3e, 0x9a,
+ 0xd7, 0x8e, 0x68, 0xe7, 0xe7, 0xca, 0xfa, 0x74,
+ 0xdf, 0xf9, 0xad, 0xd1, 0xa3, 0x2d, 0xe1, 0x3d,
+ 0x9f, 0xc7, 0x4c, 0xb6, 0xc9, 0x85, 0x6a, 0xf7,
+ 0xf3, 0xe2, 0x65, 0x79, 0x7d, 0xee, 0x20, 0x17,
+ 0x59, 0x8f, 0x3a, 0xf0, 0x13, 0x47, 0x8f, 0xa6,
+ 0x3c, 0x22, 0xeb, 0x7e, 0xb5, 0x9d, 0x67, 0x39,
+ 0x5a, 0x78, 0xbf, 0x68, 0xf4, 0x68, 0xca, 0x09,
+ 0x59, 0xee, 0xcc, 0xbc, 0xce, 0x39, 0xf4, 0x37,
+ 0x12, 0x77, 0x49, 0x50, 0x0f, 0xcd, 0xfe, 0x71,
+ 0x46, 0x5e, 0xa3, 0x77, 0xc0, 0x8c, 0x2c, 0x7f,
+ 0xdd, 0x4c, 0xb8, 0x40, 0xa7, 0xbe, 0x9a, 0x7d,
+ 0x6b, 0xdc, 0x28, 0xec, 0xbb, 0x09, 0x7e, 0xdb,
+ 0xbf, 0x4c, 0xbc, 0x32, 0xeb, 0x7f, 0x9c, 0x27,
+ 0x0f, 0x04, 0x26, 0xae, 0xc3, 0xed, 0x86, 0xc4,
+ 0xf5, 0xe7, 0x13, 0x0c, 0xd4, 0x50, 0x16, 0x93,
+ 0x1d, 0x93, 0x9d, 0xff, 0xb5, 0xed, 0x7c, 0xaf,
+ 0x6c, 0x97, 0x93, 0x15, 0x2d, 0x42, 0xcf, 0xdf,
+ 0x3c, 0x31, 0x42, 0x0e, 0x80, 0x04, 0xe6, 0x7f,
+ 0x12, 0xcb, 0x24, 0xae, 0x4f, 0xc8, 0xe4, 0xa9,
+ 0xa3, 0x47, 0x13, 0x9f, 0xc8, 0x72, 0x57, 0x6f,
+ 0xe7, 0x67, 0x64, 0x1d, 0x7e, 0x5f, 0x4e, 0xe6,
+ 0xbf, 0x97, 0xb8, 0x32, 0xcf, 0x2d, 0x81, 0xc4,
+ 0xed, 0x52, 0xd9, 0x6e, 0x73, 0xd1, 0x90, 0x6d,
+ 0x90, 0x60, 0x72, 0xa2, 0x2d, 0xdd, 0x24, 0x41,
+ 0xa2, 0x4c, 0x6b, 0xe5, 0x72, 0xff, 0xa1, 0xc1,
+ 0xd5, 0x21, 0xd9, 0xc6, 0xa4, 0xc8, 0x3b, 0xdb,
+ 0x61, 0x84, 0xa9, 0xa7, 0x25, 0xee, 0x9f, 0x58,
+ 0xb6, 0x75, 0x29, 0xad, 0x65, 0x7f, 0x27, 0xf1,
+ 0xcc, 0x6c, 0xab, 0xb7, 0xc1, 0x4f, 0xb6, 0xcd,
+ 0xf6, 0x58, 0xee, 0x61, 0x89, 0xf2, 0x04, 0x5b,
+ 0xc3, 0x89, 0xf3, 0xb9, 0xed, 0xfc, 0x8c, 0x6c,
+ 0x8f, 0x13, 0xe2, 0xf3, 0x13, 0x0c, 0x45, 0xb8,
+ 0x2c, 0x2e, 0x4e, 0x1e, 0x9a, 0xed, 0x72, 0x52,
+ 0x9c, 0xc8, 0xb6, 0x5e, 0x91, 0xc9, 0xd0, 0x52,
+ 0x8e, 0x55, 0x9d, 0x9d, 0xf7, 0xe7, 0x7b, 0xde,
+ 0x92, 0x7c, 0x66, 0x2e, 0xd8, 0xf8, 0x3e, 0xbb,
+ 0xde, 0x97, 0xb8, 0x55, 0xb6, 0xcf, 0xeb, 0x5c,
+ 0x6c, 0xf0, 0xb8, 0x74, 0xed, 0xbc, 0x3e, 0xef,
+ 0x22, 0xa1, 0x91, 0xf5, 0xb9, 0x58, 0x98, 0xfa,
+ 0x9e, 0x56, 0xf4, 0xe6, 0xbc, 0x5f, 0x73, 0xc1,
+ 0x99, 0x6d, 0xb2, 0x7f, 0x94, 0xa5, 0x1e, 0x0f,
+ 0xcc, 0xeb, 0x2f, 0x6f, 0xe7, 0xab, 0xb2, 0x1e,
+ 0x17, 0x04, 0x0c, 0x86, 0x51, 0xba, 0x62, 0xd6,
+ 0x9d, 0xec, 0xf7, 0x59, 0x8e, 0x8b, 0xcc, 0x5a,
+ 0xe3, 0x41, 0xf6, 0x11, 0xaa, 0x8d, 0xde, 0x9e,
+ 0x28, 0x47, 0xb1, 0xfa, 0x4e, 0xb6, 0x31, 0x75,
+ 0x6c, 0x67, 0x3b, 0x9c, 0x43, 0xd8, 0xf7, 0xee,
+ 0x99, 0x58, 0x94, 0x9e, 0xb0, 0x5d, 0xce, 0x99,
+ 0x0f, 0xcf, 0x76, 0x38, 0x2e, 0x77, 0x35, 0x8b,
+ 0x85, 0x0f, 0x40, 0xd9, 0xb1, 0xbf, 0x9d, 0x49,
+ 0x99, 0x73, 0xc5, 0xb2, 0x0d, 0x9b, 0x28, 0x62,
+ 0xeb, 0x26, 0xac, 0x78, 0x59, 0x3b, 0xdd, 0x88,
+ 0x7c, 0x2e, 0x12, 0x19, 0xba, 0x70, 0x90, 0xab,
+ 0x5a, 0x36, 0x61, 0xc5, 0xb2, 0x17, 0x90, 0x24,
+ 0xa8, 0x9c, 0x50, 0x16, 0x5e, 0x98, 0xe5, 0xb3,
+ 0x90, 0x53, 0xf9, 0x48, 0x82, 0x5c, 0xd5, 0x90,
+ 0x6e, 0x1b, 0xe4, 0x16, 0xb8, 0xa0, 0x78, 0x7b,
+ 0xb6, 0x71, 0xe1, 0xe6, 0x99, 0x42, 0x9e, 0x27,
+ 0x37, 0xf9, 0xc6, 0xc4, 0x23, 0x13, 0xcb, 0x24,
+ 0xac, 0xbd, 0xf8, 0x2d, 0x13, 0xe4, 0x34, 0x19,
+ 0x7a, 0x72, 0x48, 0xc2, 0x8a, 0xa6, 0x5f, 0x6a,
+ 0xd6, 0x7f, 0x18, 0xdb, 0xd9, 0xa9, 0xf2, 0xd9,
+ 0x39, 0xc7, 0xd5, 0x2e, 0x80, 0x5f, 0x9f, 0xe3,
+ 0xa0, 0x9d, 0xdd, 0xf3, 0xd7, 0x09, 0xfa, 0xda,
+ 0x96, 0xf6, 0x75, 0xc3, 0xa6, 0xb2, 0x78, 0x7a,
+ 0x7f, 0xa0, 0xe4, 0xa6, 0x96, 0xb0, 0xce, 0xc8,
+ 0x77, 0xcb, 0x3e, 0x42, 0x42, 0x7e, 0xaf, 0xc4,
+ 0x32, 0xc7, 0x19, 0xbf, 0x05, 0xdf, 0xe9, 0xfb,
+ 0xb2, 0xee, 0x56, 0xba, 0xff, 0xed, 0x08, 0x26,
+ 0xae, 0x07, 0x2e, 0x86, 0x2b, 0x2c, 0x1b, 0x36,
+ 0x8d, 0x8b, 0x0b, 0x7b, 0xe5, 0xa0, 0xe0, 0xe4,
+ 0x5f, 0x0e, 0x3c, 0x41, 0x43, 0x26, 0x0e, 0xc8,
+ 0x8d, 0x68, 0x4f, 0xee, 0x0c, 0xaf, 0x47, 0x82,
+ 0xb3, 0xa9, 0x7d, 0x96, 0x62, 0xbd, 0xb2, 0x78,
+ 0x79, 0x46, 0x3e, 0xcb, 0x95, 0x32, 0xf9, 0x8b,
+ 0xc4, 0xa1, 0xcd, 0x13, 0xab, 0x61, 0x14, 0xaa,
+ 0xd7, 0x65, 0x5b, 0xb5, 0xc4, 0xf3, 0x11, 0x89,
+ 0xbb, 0x8d, 0x66, 0x67, 0xf0, 0x45, 0x94, 0xbf,
+ 0xd9, 0x3c, 0xe4, 0xaa, 0x29, 0xf2, 0x3c, 0x5f,
+ 0xf3, 0x68, 0x38, 0x72, 0x4e, 0xcf, 0x49, 0xec,
+ 0xe4, 0xd6, 0xb3, 0xe4, 0xda, 0xcb, 0xb6, 0x01,
+ 0x14, 0xa9, 0xbf, 0x65, 0x34, 0xdb, 0x5c, 0x6c,
+ 0x52, 0x62, 0xc1, 0x45, 0x5b, 0xe9, 0x9e, 0xf9,
+ 0x8d, 0x86, 0x5c, 0x3c, 0x6d, 0x05, 0x25, 0x49,
+ 0x7d, 0x23, 0x5d, 0xed, 0x4b, 0xb4, 0xe0, 0x5f,
+ 0x26, 0x61, 0xa5, 0xa8, 0x98, 0x52, 0xb0, 0x5a,
+ 0x57, 0x2c, 0xf0, 0x1d, 0x13, 0x35, 0x34, 0xa0,
+ 0x3c, 0x25, 0xdb, 0xd8, 0xd5, 0xe9, 0x8f, 0x89,
+ 0xeb, 0x01, 0x2a, 0x27, 0x94, 0x33, 0x32, 0x29,
+ 0xeb, 0x6f, 0x38, 0xd9, 0xd3, 0xbd, 0x66, 0x9e,
+ 0x23, 0x13, 0xe5, 0x01, 0xf5, 0xda, 0x6c, 0x6f,
+ 0xa9, 0xba, 0xda, 0x15, 0xdd, 0x3d, 0xf1, 0xa8,
+ 0xd1, 0xec, 0x0c, 0xea, 0x74, 0xc8, 0xe9, 0x3d,
+ 0x24, 0x41, 0x71, 0xf7, 0xd1, 0x89, 0x13, 0x12,
+ 0xd4, 0xfd, 0x0e, 0x41, 0xb1, 0xf0, 0x18, 0x27,
+ 0x5b, 0x8a, 0xe2, 0x19, 0x83, 0x76, 0xd2, 0x40,
+ 0x2b, 0x27, 0x03, 0x12, 0x9b, 0xd7, 0x27, 0x6a,
+ 0x89, 0x30, 0x89, 0x1e, 0x27, 0x1b, 0xc6, 0xd9,
+ 0xa5, 0x0e, 0x96, 0xa2, 0x53, 0x72, 0xda, 0xb5,
+ 0x1c, 0x11, 0xee, 0x94, 0xf8, 0xb5, 0xd1, 0xec,
+ 0x48, 0xb6, 0x4f, 0x69, 0x00, 0xf5, 0xbd, 0x25,
+ 0xba, 0xb6, 0x90, 0x50, 0x92, 0x53, 0x20, 0x71,
+ 0xbf, 0x69, 0x82, 0x7e, 0xc2, 0xbd, 0xf5, 0x57,
+ 0xd9, 0x16, 0xf5, 0xb5, 0x2f, 0x48, 0xd4, 0x8e,
+ 0x71, 0x8a, 0xe4, 0x28, 0x5e, 0x24, 0xe7, 0xcd,
+ 0x08, 0x4b, 0x0f, 0x4d, 0xf0, 0x7f, 0xf1, 0x5d,
+ 0x96, 0x58, 0xff, 0x05, 0xd9, 0xde, 0xf8, 0x37,
+ 0xa7, 0x41, 0x1c, 0xf5, 0xbc, 0xe3, 0xa8, 0xb5,
+ 0x0e, 0x67, 0xa8, 0xc3, 0xee, 0x32, 0x65, 0x7c,
+ 0x2d, 0x51, 0xe2, 0x7f, 0x2c, 0x97, 0xfb, 0x60,
+ 0x62, 0xab, 0x6a, 0x17, 0x06, 0xa7, 0x66, 0x7f,
+ 0x2d, 0x8b, 0x44, 0x69, 0x43, 0x50, 0xa2, 0xfa,
+ 0x83, 0xfd, 0x7d, 0x11, 0xaa, 0xa2, 0x28, 0x2e,
+ 0x5f, 0x26, 0x6a, 0xfb, 0x03, 0xfb, 0xdb, 0xb1,
+ 0x95, 0xcf, 0xb4, 0x3f, 0xb0, 0x6f, 0x8d, 0x75,
+ 0x8f, 0x03, 0xe6, 0x1b, 0xd9, 0x17, 0x38, 0x4f,
+ 0x30, 0xb2, 0x16, 0xdd, 0xe8, 0xba, 0xb8, 0xf8,
+ 0x63, 0x3f, 0xa2, 0x94, 0x84, 0xe2, 0x7c, 0x8a,
+ 0x8c, 0x6f, 0x96, 0xa8, 0x8d, 0x6f, 0x4e, 0x15,
+ 0x12, 0x45, 0xc9, 0xbb, 0xd6, 0xb2, 0x45, 0x66,
+ 0x3b, 0x42, 0x5b, 0xe7, 0xfa, 0x2f, 0x09, 0x8a,
+ 0x36, 0x36, 0xe5, 0xac, 0x83, 0xde, 0x7a, 0x66,
+ 0x33, 0xca, 0xcb, 0x09, 0xa7, 0xee, 0x39, 0x29,
+ 0x93, 0x79, 0x77, 0x9d, 0x59, 0x87, 0x23, 0x4e,
+ 0x3c, 0xb2, 0xa9, 0xdf, 0x1c, 0x2c, 0x07, 0x41,
+ 0xb5, 0xce, 0x35, 0x07, 0x71, 0x33, 0x7e, 0x6f,
+ 0x5e, 0xa7, 0x45, 0x24, 0x09, 0x53, 0x17, 0xf5,
+ 0x32, 0x87, 0x65, 0x99, 0xea, 0x55, 0x67, 0xd6,
+ 0x21, 0x87, 0x4a, 0xc2, 0x30, 0x46, 0xa2, 0xc2,
+ 0x60, 0xfb, 0x67, 0xe4, 0x35, 0x4e, 0xc4, 0x6b,
+ 0xad, 0x73, 0xcd, 0x72, 0x14, 0x9f, 0x72, 0x21,
+ 0x50, 0x36, 0x80, 0x01, 0xf5, 0xbc, 0xe4, 0xa2,
+ 0x3f, 0x9f, 0xf5, 0x9a, 0x27, 0xc6, 0xb2, 0x1e,
+ 0x93, 0xdb, 0x24, 0x78, 0x5f, 0x06, 0xa7, 0x58,
+ 0x54, 0xe7, 0x0a, 0x56, 0x22, 0xa7, 0x47, 0xe2,
+ 0x3c, 0x6e, 0x78, 0xc4, 0x49, 0x82, 0xdf, 0x98,
+ 0x62, 0x6f, 0x2e, 0x3c, 0x6a, 0x37, 0x28, 0x20,
+ 0xe7, 0x4e, 0xa2, 0xfe, 0xc1, 0xca, 0xe7, 0x20,
+ 0xc1, 0xa4, 0xbe, 0x8f, 0xbb, 0x06, 0x95, 0x68,
+ 0x44, 0x76, 0x68, 0xd6, 0x61, 0xca, 0xb2, 0x9c,
+ 0x94, 0xca, 0x46, 0x3d, 0xb8, 0x59, 0x96, 0xa1,
+ 0xa1, 0xd1, 0x94, 0xf6, 0x7f, 0xa4, 0xb1, 0xd3,
+ 0xb9, 0xf3, 0xfa, 0xa4, 0xe4, 0x20, 0xcf, 0xf3,
+ 0x21, 0xf8, 0x6e, 0xf8, 0xff, 0x4b, 0xd4, 0x29,
+ 0xdf, 0x37, 0xcb, 0x4f, 0x9d, 0xc8, 0xdb, 0x6d,
+ 0x91, 0x80, 0x92, 0x83, 0xab, 0x75, 0xcb, 0xe2,
+ 0xa4, 0x79, 0xaf, 0xca, 0xff, 0x47, 0xd7, 0xae,
+ 0xa6, 0x0d, 0x42, 0xc7, 0x13, 0xb2, 0xdc, 0xd3,
+ 0xdb, 0xf9, 0x19, 0x59, 0x87, 0x61, 0x10, 0xcb,
+ 0x31, 0xa4, 0x69, 0xac, 0x53, 0x76, 0xed, 0xda,
+ 0x92, 0xbc, 0x0f, 0x7d, 0x70, 0xc9, 0x11, 0x96,
+ 0x45, 0x90, 0xfc, 0x1f, 0xfc, 0x3f, 0x13, 0xed,
+ 0x77, 0xc6, 0x7e, 0x76, 0xd5, 0xe6, 0x89, 0x1f,
+ 0x79, 0x4b, 0x96, 0xe5, 0xe2, 0x6e, 0xcb, 0xf2,
+ 0x1e, 0x24, 0x34, 0x5c, 0x34, 0x74, 0x1b, 0x92,
+ 0xe1, 0x49, 0x89, 0x13, 0xbb, 0xdf, 0x6d, 0x96,
+ 0xdd, 0x5f, 0x75, 0xae, 0x60, 0x67, 0x38, 0x39,
+ 0x41, 0x4e, 0xba, 0x7b, 0x1c, 0xf0, 0xbd, 0x71,
+ 0xa1, 0xc5, 0x10, 0x91, 0xaf, 0x6a, 0x9e, 0xfd,
+ 0x11, 0xce, 0x03, 0x34, 0xbe, 0x7b, 0x49, 0xf7,
+ 0xff, 0x40, 0x96, 0xe7, 0x09, 0x8e, 0x1f, 0x2e,
+ 0x10, 0xbb, 0xfe, 0x31, 0x71, 0xbd, 0x2c, 0x3f,
+ 0xa4, 0x34, 0x66, 0xc7, 0xd8, 0x6d, 0x39, 0x57,
+ 0x76, 0x8a, 0x9f, 0x4a, 0x50, 0xac, 0xb1, 0xa9,
+ 0xa0, 0x55, 0xdc, 0xd8, 0xaf, 0x27, 0x6a, 0xcb,
+ 0xac, 0x33, 0x7a, 0x07, 0x3c, 0x5f, 0x03, 0x12,
+ 0x5e, 0xae, 0xba, 0xbb, 0xb8, 0x1a, 0xad, 0x8e,
+ 0x50, 0x93, 0x83, 0x84, 0x5c, 0x13, 0x57, 0x9c,
+ 0x5d, 0xd4, 0xe7, 0xd1, 0xf8, 0x65, 0x53, 0xb8,
+ 0xe3, 0x4e, 0x2d, 0x61, 0x25, 0x91, 0x38, 0x2a,
+ 0x07, 0xe6, 0x4c, 0xc2, 0x0a, 0x9e, 0x4b, 0xd0,
+ 0xc8, 0x84, 0x7b, 0x8a, 0xd6, 0x72, 0x64, 0x35,
+ 0xe4, 0x34, 0x1f, 0x92, 0xf5, 0xbe, 0xdc, 0xae,
+ 0x4f, 0x7c, 0x2d, 0x41, 0xab, 0x4a, 0x4e, 0x00,
+ 0xb4, 0x9e, 0x2c, 0x91, 0x68, 0xdf, 0x31, 0xcb,
+ 0xcc, 0x24, 0xac, 0xc8, 0x73, 0xbc, 0x37, 0xc5,
+ 0xd9, 0xb5, 0x3a, 0xee, 0x83, 0x13, 0xdd, 0xab,
+ 0x77, 0x8a, 0xda, 0x4a, 0xe4, 0x9c, 0xab, 0xdf,
+ 0x2f, 0xef, 0x97, 0x78, 0x67, 0xa2, 0x2c, 0x92,
+ 0x67, 0x98, 0xbf, 0xda, 0xb0, 0x84, 0x24, 0xdc,
+ 0x77, 0xcf, 0xf2, 0x33, 0x27, 0xd5, 0x76, 0x5b,
+ 0xec, 0x6b, 0x3f, 0x97, 0xa0, 0xd5, 0x70, 0x89,
+ 0x04, 0x66, 0x61, 0xb1, 0xf9, 0x36, 0xc3, 0x45,
+ 0x60, 0x99, 0xb0, 0x92, 0x6b, 0x9f, 0x19, 0x62,
+ 0x33, 0xff, 0x3b, 0xe7, 0x8e, 0xa9, 0x04, 0xb7,
+ 0x75, 0xc7, 0xec, 0xf7, 0x5b, 0xbe, 0x58, 0x6f,
+ 0x13, 0x33, 0x72, 0x7b, 0x65, 0xc2, 0x4a, 0xe9,
+ 0xd1, 0xd3, 0xf8, 0xfe, 0xb7, 0x91, 0xdf, 0x4f,
+ 0xd4, 0x8e, 0x03, 0x12, 0x56, 0x3e, 0x68, 0xad,
+ 0x65, 0x34, 0x89, 0xf1, 0x4c, 0xc2, 0x8a, 0x3c,
+ 0xc7, 0x77, 0x4b, 0x89, 0x4e, 0xd9, 0x88, 0x89,
+ 0xd2, 0x95, 0xb2, 0xc8, 0x5e, 0xda, 0xfe, 0x72,
+ 0x20, 0xdc, 0x39, 0x51, 0x62, 0x98, 0xc1, 0x89,
+ 0x3c, 0x7e, 0xc6, 0xe8, 0xe9, 0x29, 0x6f, 0x6e,
+ 0x5f, 0x9e, 0x92, 0xe7, 0x9f, 0x3a, 0x7a, 0x79,
+ 0x0a, 0xc5, 0x8a, 0x8d, 0xcc, 0xd3, 0x1f, 0xf3,
+ 0x5b, 0xcd, 0xb3, 0xd3, 0x66, 0x06, 0x65, 0xcf,
+ 0x73, 0x4f, 0x18, 0xbd, 0x34, 0x85, 0x9c, 0xc3,
+ 0x44, 0x1e, 0xd3, 0x67, 0xee, 0x63, 0xcd, 0x2b,
+ 0xd3, 0xbe, 0x92, 0x28, 0x5b, 0x3a, 0x2f, 0x25,
+ 0xeb, 0x5d, 0xbe, 0xd9, 0xc2, 0xac, 0x2f, 0x24,
+ 0x7a, 0x87, 0xe4, 0xcb, 0x6b, 0x37, 0x6c, 0x96,
+ 0x9a, 0xf5, 0xac, 0x76, 0x91, 0xb9, 0xb2, 0xdc,
+ 0xa5, 0x12, 0xdf, 0x6e, 0xd6, 0x98, 0x46, 0x0e,
+ 0xb3, 0x91, 0xf9, 0xa3, 0x46, 0x4f, 0xcd, 0x18,
+ 0x34, 0x98, 0x7c, 0x96, 0x7f, 0xf6, 0x68, 0xb5,
+ 0x29, 0x3f, 0x48, 0x2c, 0xdb, 0xb5, 0xe4, 0xb8,
+ 0x66, 0x8d, 0x59, 0x33, 0x37, 0x79, 0xc8, 0x73,
+ 0x7c, 0x6f, 0x25, 0xea, 0xed, 0x7a, 0xe5, 0x75,
+ 0x1a, 0x4a, 0x95, 0xe6, 0xdd, 0xb2, 0x70, 0x25,
+ 0xd9, 0x66, 0xed, 0x7d, 0x5e, 0xd7, 0xbe, 0x3c,
+ 0x23, 0xaf, 0x5d, 0x23, 0xc1, 0xf7, 0x54, 0xe2,
+ 0x22, 0x7a, 0x65, 0x59, 0x9f, 0xe3, 0xe2, 0x4d,
+ 0xcd, 0x96, 0xa6, 0xb1, 0x1f, 0xd3, 0xc5, 0x6a,
+ 0x46, 0x9e, 0xff, 0x7e, 0xb3, 0xc4, 0xb4, 0x85,
+ 0x37, 0xd9, 0xc8, 0x32, 0x47, 0x8c, 0x16, 0x9d,
+ 0x31, 0x55, 0x84, 0x9b, 0xc7, 0xf4, 0x9b, 0xae,
+ 0x59, 0x74, 0x1c, 0xd4, 0xb6, 0xff, 0xdd, 0x44,
+ 0xed, 0x02, 0x78, 0x4a, 0x96, 0x79, 0x5b, 0xb3,
+ 0xf4, 0xb4, 0xa9, 0xaa, 0x91, 0xdd, 0x64, 0x5b,
+ 0x5d, 0x2e, 0x6d, 0xd9, 0x29, 0x67, 0xf3, 0xff,
+ 0xd0, 0xf0, 0xe5, 0xa0, 0xe6, 0xf1, 0x66, 0x7c,
+ 0x7d, 0xcf, 0x31, 0x07, 0x37, 0x7d, 0x31, 0x93,
+ 0x4c, 0x51, 0xaf, 0xd6, 0xad, 0xab, 0xdb, 0x84,
+ 0x27, 0xee, 0xbd, 0xfd, 0x9e, 0xff, 0x6a, 0xe7,
+ 0x07, 0xc9, 0x8e, 0x3b, 0xb7, 0x58, 0x18, 0x59,
+ 0x86, 0x06, 0x4c, 0xd4, 0xa3, 0x75, 0x8b, 0xa0,
+ 0xc8, 0x6d, 0xd1, 0x07, 0x90, 0xe2, 0xce, 0x46,
+ 0x96, 0xa3, 0x61, 0xc7, 0xbf, 0x25, 0xba, 0xb9,
+ 0x17, 0xea, 0xce, 0xe8, 0x1b, 0xdb, 0xe4, 0x0c,
+ 0xb3, 0xcc, 0x5a, 0x8b, 0x85, 0xb3, 0x0c, 0x39,
+ 0x65, 0x8a, 0xc4, 0xcb, 0x12, 0x96, 0xa7, 0x67,
+ 0x39, 0xd6, 0x1f, 0x2c, 0xdb, 0xec, 0x2b, 0x16,
+ 0x7e, 0x6e, 0xb6, 0x49, 0x63, 0xa2, 0xaa, 0xac,
+ 0x47, 0x1d, 0xe7, 0xef, 0x8e, 0x1e, 0x4d, 0x70,
+ 0x45, 0x7e, 0xad, 0xac, 0x47, 0x55, 0xc4, 0x42,
+ 0xd9, 0x06, 0xbf, 0x05, 0xbf, 0x49, 0x17, 0x45,
+ 0xc2, 0x74, 0x15, 0xfa, 0x5e, 0x5e, 0xe7, 0xe6,
+ 0xf6, 0x5c, 0x60, 0x94, 0xff, 0x2f, 0xb9, 0x63,
+ 0xbe, 0xbf, 0xe7, 0x65, 0x39, 0xee, 0x79, 0x3b,
+ 0x57, 0xb6, 0xf3, 0x77, 0x99, 0x5c, 0x7f, 0xf4,
+ 0x68, 0x82, 0xbe, 0xa7, 0xd7, 0xcf, 0xfa, 0x7c,
+ 0xe6, 0xb9, 0xb2, 0x3e, 0x63, 0x46, 0xd3, 0x72,
+ 0xb5, 0xcc, 0x65, 0xbd, 0x3c, 0xeb, 0x53, 0x92,
+ 0x30, 0x91, 0x65, 0xb7, 0x65, 0xb1, 0x70, 0xde,
+ 0x83, 0xc4, 0x84, 0xfe, 0x95, 0xe5, 0xff, 0x70,
+ 0xe7, 0xbc, 0x0f, 0x7d, 0x8e, 0x67, 0x64, 0x1d,
+ 0xce, 0x1f, 0x7c, 0x77, 0x34, 0xb8, 0xe9, 0xe2,
+ 0xb9, 0x1b, 0x2d, 0xf3, 0xdd, 0xd5, 0x64, 0xbb,
+ 0xb4, 0x07, 0xe0, 0x66, 0xf2, 0x5d, 0x94, 0x84,
+ 0x70, 0x7f, 0xdb, 0x49, 0xc3, 0xaa, 0xae, 0xac,
+ 0xb3, 0xbf, 0x8a, 0x85, 0xe9, 0x33, 0x4d, 0x17,
+ 0xb0, 0xaa, 0xac, 0x57, 0x3b, 0x6e, 0xb9, 0x40,
+ 0x3c, 0x32, 0xeb, 0x8d, 0x1e, 0xf5, 0xc8, 0xba,
+ 0x5c, 0x88, 0x96, 0xa5, 0x3f, 0x27, 0x65, 0x3d,
+ 0xea, 0xfc, 0x77, 0x9d, 0xdd, 0x98, 0xb8, 0x6e,
+ 0xbc, 0x9f, 0x6b, 0x12, 0xd7, 0xe6, 0x64, 0x92,
+ 0xc4, 0x75, 0x9f, 0xf4, 0x73, 0x4d, 0x52, 0xb8,
+ 0xd6, 0x7e, 0xae, 0xd9, 0x99, 0xa7, 0x4e, 0x6c,
+ 0x59, 0xee, 0x1d, 0x99, 0x94, 0xf7, 0x57, 0x7d,
+ 0x4c, 0x96, 0x9b, 0xe4, 0xca, 0xb2, 0x4c, 0xad,
+ 0x7e, 0x96, 0x93, 0xfd, 0xa4, 0x2e, 0x31, 0xcb,
+ 0xac, 0x3b, 0x71, 0xa5, 0x4f, 0x6b, 0x2d, 0x17,
+ 0x7d, 0xe3, 0x2c, 0x47, 0x57, 0x98, 0xc1, 0xb2,
+ 0xcd, 0xbe, 0xc4, 0x75, 0x6e, 0x1f, 0xdf, 0xac,
+ 0x47, 0x91, 0x1e, 0x0d, 0x95, 0xba, 0xb8, 0xe8,
+ 0xb9, 0x4c, 0xd6, 0x5b, 0xaa, 0xce, 0x28, 0xdb,
+ 0x20, 0x47, 0x47, 0xdf, 0xd8, 0x2e, 0x4e, 0xd8,
+ 0x57, 0xc8, 0x36, 0xc8, 0x31, 0xb0, 0xff, 0x72,
+ 0x62, 0xac, 0x76, 0xd4, 0x0f, 0x4e, 0x86, 0xe4,
+ 0xf0, 0x48, 0x88, 0xaa, 0xd5, 0x05, 0xd9, 0x06,
+ 0x17, 0x41, 0x5f, 0x4f, 0x94, 0xb9, 0x8f, 0xa9,
+ 0xdf, 0x6a, 0x91, 0x6c, 0x87, 0xfa, 0x30, 0x8a,
+ 0xed, 0xba, 0x3e, 0x90, 0x6d, 0x4c, 0xdd, 0xff,
+ 0x37, 0xcb, 0x6d, 0xd7, 0xc4, 0xf5, 0x71, 0x99,
+ 0x70, 0x63, 0x88, 0x2e, 0xea, 0x0f, 0xf9, 0xae,
+ 0x7b, 0xab, 0x09, 0xb2, 0x1e, 0x0d, 0xca, 0xe8,
+ 0x47, 0xdd, 0xc5, 0xef, 0x7b, 0x83, 0xac, 0xc7,
+ 0x05, 0xca, 0x20, 0xd9, 0x1e, 0xd5, 0x48, 0xd4,
+ 0x97, 0x97, 0xbf, 0x07, 0x55, 0x0d, 0x14, 0xbd,
+ 0x8e, 0x1e, 0x15, 0xb2, 0xde, 0xfe, 0x4a, 0x5c,
+ 0x17, 0x1d, 0x07, 0xdc, 0xec, 0xbe, 0xac, 0x83,
+ 0xa6, 0xc1, 0xd3, 0x3f, 0x8f, 0x66, 0xe7, 0xe2,
+ 0xd8, 0x2e, 0x7b, 0x23, 0xac, 0xad, 0x4e, 0x7b,
+ 0xbb, 0xd9, 0x6d, 0x75, 0xae, 0x5a, 0xcd, 0x4b,
+ 0xda, 0x69, 0xd7, 0xfd, 0x72, 0x20, 0x35, 0x47,
+ 0x7e, 0x3b, 0x2d, 0x47, 0xca, 0xe1, 0x84, 0xb3,
+ 0xd1, 0xbe, 0xad, 0x51, 0x6b, 0xe6, 0x4f, 0x43,
+ 0xab, 0x95, 0x2e, 0x36, 0x16, 0x20, 0x91, 0x98,
+ 0xa7, 0x56, 0x1f, 0xfa, 0xd9, 0x9c, 0x18, 0x96,
+ 0x4a, 0x58, 0x5b, 0xb5, 0x44, 0x9d, 0xef, 0xb6,
+ 0xa9, 0x17, 0xcc, 0xb6, 0x48, 0x68, 0xb9, 0xb2,
+ 0xef, 0x1b, 0x9f, 0x99, 0xa2, 0x70, 0xea, 0xbb,
+ 0x68, 0x3c, 0xf6, 0x9a, 0x44, 0xad, 0xbf, 0x2f,
+ 0xdb, 0xaa, 0x75, 0xbd, 0x19, 0x5a, 0x77, 0x4f,
+ 0x43, 0xa0, 0xd2, 0x8e, 0x18, 0x6f, 0xb7, 0xdd,
+ 0x5f, 0x6b, 0xad, 0xde, 0xb9, 0xe8, 0x38, 0x21,
+ 0xaf, 0x53, 0x15, 0x52, 0x8d, 0xbc, 0x5e, 0xab,
+ 0x03, 0xe4, 0x3c, 0x39, 0xf8, 0x3e, 0xaf, 0xd9,
+ 0x1e, 0xfd, 0x9a, 0x29, 0x86, 0x2e, 0x13, 0x56,
+ 0x5a, 0x79, 0x3f, 0x3a, 0xbf, 0xf7, 0xe8, 0xd1,
+ 0xf6, 0x52, 0xab, 0x6f, 0xef, 0xe2, 0xe2, 0xb4,
+ 0xc4, 0x7e, 0x48, 0xfd, 0xf6, 0xa2, 0xa8, 0x75,
+ 0xf3, 0x2b, 0x2f, 0xc4, 0x77, 0x0d, 0x13, 0x57,
+ 0x81, 0x06, 0x1e, 0x65, 0x17, 0x01, 0x06, 0x4a,
+ 0x18, 0x37, 0xcb, 0x3f, 0x3c, 0x31, 0x95, 0x63,
+ 0x09, 0xae, 0x8e, 0x27, 0xc3, 0x0a, 0x6e, 0x08,
+ 0x0d, 0x7e, 0x4a, 0x24, 0xae, 0xe4, 0x8e, 0xd7,
+ 0x6d, 0x51, 0xa3, 0xa7, 0xda, 0xa0, 0x0f, 0x43,
+ 0x3f, 0x47, 0x73, 0x3f, 0xd3, 0x8a, 0x49, 0x62,
+ 0x98, 0x13, 0x2e, 0x0d, 0xc4, 0x68, 0x9d, 0xcc,
+ 0xa8, 0x50, 0x7d, 0x28, 0xea, 0x24, 0x17, 0xfd,
+ 0xf1, 0x9c, 0xc0, 0xef, 0x93, 0x68, 0x9e, 0x6c,
+ 0xd1, 0x42, 0xb6, 0x76, 0x5c, 0x0f, 0x1d, 0x11,
+ 0xa7, 0x56, 0xfc, 0x5c, 0x16, 0xb1, 0x6e, 0x57,
+ 0xec, 0xb7, 0xb5, 0x91, 0xbe, 0x28, 0x76, 0x27,
+ 0x47, 0x3b, 0x2f, 0xfa, 0xfa, 0xf4, 0x0e, 0xea,
+ 0xf3, 0x9a, 0x65, 0x49, 0x39, 0x19, 0xca, 0x90,
+ 0x63, 0xa7, 0x8b, 0x01, 0x5c, 0xc8, 0x1d, 0x32,
+ 0xdd, 0x8e, 0x16, 0x7d, 0xae, 0xea, 0xe0, 0x27,
+ 0x9a, 0x65, 0xe2, 0x2a, 0x4e, 0xe8, 0x14, 0x41,
+ 0xd1, 0x07, 0xaf, 0x34, 0x6e, 0x3a, 0x7f, 0x5c,
+ 0xa2, 0x1c, 0xf0, 0xe0, 0xa5, 0xfb, 0xe0, 0xca,
+ 0xbb, 0x76, 0x32, 0x67, 0x9f, 0xdd, 0x1f, 0x27,
+ 0xf9, 0x5a, 0x0e, 0xb5, 0x2c, 0xb6, 0x5b, 0xa4,
+ 0xef, 0xe4, 0x3c, 0xd5, 0x47, 0x38, 0xdf, 0xeb,
+ 0x9f, 0x64, 0x42, 0xbd, 0x1f, 0x45, 0xe2, 0xf3,
+ 0x72, 0xc6, 0x9c, 0xe8, 0x18, 0x83, 0x76, 0xd2,
+ 0xa8, 0x2c, 0xfa, 0xea, 0x05, 0x87, 0x0e, 0x24,
+ 0x51, 0x8e, 0xc0, 0x85, 0x41, 0x77, 0x3c, 0xda,
+ 0x8f, 0x16, 0xf5, 0xd5, 0x5e, 0x05, 0x2d, 0xf7,
+ 0xcb, 0xaa, 0x93, 0x79, 0xf8, 0x4d, 0x6a, 0x09,
+ 0xf5, 0xa3, 0xf2, 0xfb, 0x2e, 0x1c, 0x52, 0x71,
+ 0x1b, 0x1b, 0x52, 0x52, 0x73, 0x40, 0x33, 0x71,
+ 0xd5, 0x18, 0x75, 0x39, 0x93, 0x8e, 0xe2, 0xad,
+ 0xa3, 0x73, 0x05, 0x4e, 0x2b, 0xc0, 0xb2, 0xae,
+ 0x91, 0x46, 0x38, 0xd5, 0x16, 0xc5, 0x6b, 0x56,
+ 0xcb, 0x6d, 0x71, 0xd2, 0xdf, 0x1f, 0xc5, 0x93,
+ 0x14, 0x29, 0x96, 0x86, 0x76, 0x4d, 0xe9, 0x1b,
+ 0x7c, 0xa2, 0xd6, 0x35, 0x86, 0x22, 0x67, 0xc6,
+ 0x99, 0xa5, 0xce, 0x8e, 0x6e, 0x0e, 0x7d, 0xb9,
+ 0x5e, 0x8e, 0xe1, 0xe7, 0xe5, 0x77, 0x1a, 0x8f,
+ 0xc1, 0x4b, 0x6e, 0xba, 0x76, 0x67, 0xa2, 0xa1,
+ 0xed, 0x10, 0x48, 0x4c, 0x4a, 0x2b, 0x35, 0xac,
+ 0xdb, 0x97, 0xf2, 0x3d, 0x90, 0x73, 0xa7, 0xcf,
+ 0xf1, 0x26, 0x1c, 0x9b, 0xed, 0xb7, 0xb3, 0xfd,
+ 0xb2, 0x0c, 0x7d, 0x65, 0x19, 0xc0, 0xa3, 0xbc,
+ 0xfa, 0xa4, 0xbe, 0xb2, 0x56, 0x05, 0xb3, 0x4e,
+ 0x9b, 0x3e, 0xa7, 0xd7, 0x8e, 0x49, 0x72, 0xe8,
+ 0xb4, 0x13, 0x58, 0x25, 0x7a, 0x1b, 0x4f, 0xed,
+ 0x74, 0x26, 0xae, 0x6a, 0xe4, 0x44, 0x4e, 0xb1,
+ 0x70, 0xd9, 0xff, 0x8f, 0x56, 0xd7, 0xd4, 0x19,
+ 0x35, 0x75, 0x82, 0x1d, 0x6f, 0xc8, 0xf2, 0x43,
+ 0x8b, 0x19, 0x57, 0x41, 0x43, 0x89, 0x12, 0xfb,
+ 0x2c, 0x77, 0xc2, 0xd9, 0xd7, 0x6a, 0x75, 0x96,
+ 0x57, 0xce, 0x89, 0xb4, 0x56, 0x74, 0xdd, 0xe7,
+ 0x3a, 0xed, 0xb4, 0x8b, 0x3b, 0x95, 0xf4, 0xde,
+ 0x29, 0x27, 0xdf, 0xf3, 0xe9, 0x09, 0xea, 0xbb,
+ 0xa9, 0x7f, 0xa6, 0xff, 0x21, 0xa5, 0x0c, 0x25,
+ 0x12, 0x56, 0x46, 0xa7, 0x02, 0x09, 0x75, 0xad,
+ 0xb8, 0xba, 0x6c, 0x3d, 0xdc, 0x2b, 0xff, 0x13,
+ 0x25, 0x03, 0x54, 0x0b, 0x94, 0xa6, 0xba, 0x4a,
+ 0x6d, 0x53, 0xdc, 0x6d, 0x69, 0xc8, 0x6f, 0x32,
+ 0x04, 0x7d, 0x80, 0xe7, 0xf6, 0x79, 0xcd, 0x77,
+ 0xc7, 0xc5, 0x1f, 0xc7, 0x4c, 0x79, 0x77, 0x24,
+ 0xf6, 0xe5, 0xe3, 0xf3, 0x5b, 0x2e, 0x4e, 0x9d,
+ 0xfb, 0x2d, 0x53, 0x24, 0xbb, 0xc9, 0x01, 0x74,
+ 0x50, 0xab, 0x8b, 0xbf, 0x50, 0xfe, 0xaf, 0xd3,
+ 0x56, 0x8c, 0x4d, 0xb4, 0x9f, 0xd8, 0x16, 0x4c,
+ 0x5c, 0xd5, 0x45, 0x0e, 0xa9, 0xc4, 0x78, 0xc3,
+ 0x5d, 0x9c, 0x1c, 0xe6, 0xb6, 0x58, 0x5c, 0x23,
+ 0x5a, 0x04, 0xd7, 0x8a, 0xa1, 0x1e, 0xb0, 0x4c,
+ 0x0e, 0x62, 0xcd, 0x3e, 0xda, 0x4e, 0xbb, 0x28,
+ 0x6a, 0x2d, 0xbb, 0xd6, 0x54, 0xe5, 0xf3, 0xb2,
+ 0x6c, 0x39, 0x00, 0x07, 0x3e, 0x94, 0x13, 0x4c,
+ 0x59, 0x62, 0x30, 0x23, 0xcb, 0xd0, 0xa1, 0x9f,
+ 0xc6, 0x4e, 0x0c, 0x3a, 0x51, 0xfb, 0x4e, 0x9a,
+ 0xee, 0x23, 0x59, 0x86, 0xd7, 0xe8, 0x3a, 0x52,
+ 0xba, 0x55, 0x3e, 0x43, 0x79, 0x91, 0xd4, 0x87,
+ 0xbb, 0xbc, 0xd4, 0x4e, 0xe4, 0xd4, 0x07, 0x6f,
+ 0xca, 0x96, 0x6e, 0x52, 0x80, 0x76, 0x9f, 0xa8,
+ 0x15, 0xc5, 0x92, 0xeb, 0xa7, 0x45, 0x33, 0xff,
+ 0xff, 0xb2, 0x41, 0xfd, 0x6b, 0x89, 0xdf, 0xb0,
+ 0x77, 0xc8, 0xbe, 0xf6, 0xfd, 0x19, 0x8d, 0xab,
+ 0x1c, 0xe1, 0x8a, 0x76, 0x02, 0x0c, 0x6f, 0x58,
+ 0x1b, 0xf6, 0xb1, 0x4f, 0xed, 0x02, 0xa9, 0x1c,
+ 0x3d, 0xaa, 0x66, 0xe8, 0x0d, 0x1a, 0x86, 0xaa,
+ 0xb5, 0x98, 0xbe, 0x5d, 0xfe, 0xf7, 0x9d, 0x52,
+ 0x1f, 0xbf, 0xcf, 0x98, 0xb8, 0xaa, 0x8b, 0xfe,
+ 0x6a, 0x8b, 0x5a, 0x95, 0x9e, 0x96, 0x18, 0x3a,
+ 0x6e, 0xef, 0xaa, 0xe8, 0xe3, 0x5a, 0xab, 0x9f,
+ 0x62, 0x58, 0xbf, 0x7b, 0xb7, 0x27, 0xb3, 0xb9,
+ 0xb2, 0x0c, 0x03, 0x51, 0xb4, 0x8f, 0xb6, 0x84,
+ 0x71, 0x83, 0x6b, 0xb9, 0x46, 0x06, 0xc3, 0xa0,
+ 0x28, 0xb2, 0x57, 0xfb, 0xfe, 0x74, 0x33, 0xa9,
+ 0x15, 0x0b, 0x4f, 0x8a, 0xd7, 0xb3, 0x1c, 0x83,
+ 0x0d, 0xb4, 0x8f, 0x7a, 0xb1, 0x7c, 0xad, 0xdb,
+ 0x43, 0xb7, 0x6f, 0x77, 0xad, 0x1f, 0x27, 0x89,
+ 0xe5, 0xe3, 0x16, 0x6d, 0x3f, 0xaf, 0x93, 0xc8,
+ 0xd5, 0x46, 0xe0, 0xa1, 0x81, 0x13, 0x5d, 0x68,
+ 0xd6, 0xa1, 0xf6, 0x21, 0x16, 0x0e, 0x42, 0xb0,
+ 0x04, 0x06, 0x64, 0x60, 0x44, 0xae, 0xd2, 0x3b,
+ 0x92, 0xb0, 0x71, 0xaf, 0x60, 0x46, 0x19, 0x5a,
+ 0x2a, 0xb2, 0x0e, 0xdd, 0xec, 0x6a, 0xc5, 0xeb,
+ 0x14, 0x0d, 0xf7, 0x35, 0x36, 0xe0, 0xde, 0xa7,
+ 0xb5, 0x62, 0xce, 0xa7, 0x66, 0x9b, 0x43, 0x2f,
+ 0x4c, 0x6a, 0xad, 0xd7, 0xef, 0x90, 0xf7, 0xee,
+ 0x4d, 0xc4, 0xf2, 0x1a, 0xfb, 0xe1, 0xe0, 0x56,
+ 0xcd, 0x03, 0x71, 0xd3, 0x8a, 0x12, 0x2d, 0x88,
+ 0xb9, 0x33, 0xce, 0xd2, 0xd8, 0x0f, 0x89, 0xdd,
+ 0xcc, 0xc4, 0x55, 0x13, 0x39, 0x01, 0x90, 0x83,
+ 0x5a, 0x94, 0x2b, 0x7d, 0x45, 0x96, 0xdb, 0x27,
+ 0x47, 0x45, 0xde, 0x87, 0x5c, 0x58, 0xd9, 0xf9,
+ 0x1e, 0x9c, 0xdc, 0xe8, 0x06, 0x44, 0x4b, 0xd9,
+ 0xde, 0x56, 0x55, 0x79, 0x8d, 0xa2, 0x4d, 0x12,
+ 0xa3, 0xde, 0x11, 0x67, 0x96, 0x95, 0xcf, 0x42,
+ 0xb1, 0x39, 0xfd, 0x81, 0x4b, 0xe4, 0x26, 0xb8,
+ 0xc3, 0x0d, 0xdd, 0x2e, 0xfa, 0x70, 0x31, 0x50,
+ 0x0e, 0x40, 0x01, 0x4e, 0xa0, 0xd4, 0xc3, 0x8d,
+ 0x51, 0xb4, 0xfb, 0xdc, 0x6c, 0x6b, 0x5e, 0xd1,
+ 0x1e, 0xff, 0x6f, 0xad, 0x21, 0xd5, 0x64, 0xc0,
+ 0x8f, 0xa0, 0x58, 0xb2, 0x96, 0xf3, 0xe1, 0xe6,
+ 0x07, 0x0f, 0xee, 0x3b, 0xa9, 0xe5, 0x79, 0x12,
+ 0x56, 0xfa, 0x78, 0x96, 0xa5, 0x15, 0xe0, 0x46,
+ 0xef, 0xcd, 0x18, 0xc8, 0x6b, 0x50, 0xdb, 0xce,
+ 0x4d, 0xf3, 0xfe, 0xe4, 0x18, 0xb7, 0x82, 0xb6,
+ 0x01, 0xb5, 0xc4, 0xa7, 0x36, 0xac, 0xe1, 0x22,
+ 0xf4, 0x97, 0x7f, 0xcf, 0x68, 0x76, 0x0a, 0x75,
+ 0xe0, 0xdd, 0x21, 0x50, 0x1b, 0xf9, 0xec, 0x24,
+ 0x30, 0xec, 0x93, 0xe5, 0xfe, 0xc8, 0x58, 0xc2,
+ 0xbd, 0x7d, 0x7e, 0xe7, 0xe0, 0x06, 0xfb, 0x25,
+ 0xba, 0xbc, 0x54, 0x07, 0x5c, 0xc8, 0xfb, 0x73,
+ 0x2e, 0xa7, 0xee, 0xb3, 0xd6, 0x65, 0x6c, 0x9d,
+ 0x28, 0x15, 0xa1, 0x0f, 0x74, 0xe9, 0x39, 0xf9,
+ 0x0c, 0xdd, 0x41, 0xff, 0x7b, 0x65, 0x39, 0x2e,
+ 0xa4, 0xc8, 0xe1, 0xef, 0xea, 0xf4, 0xc7, 0xc4,
+ 0x55, 0x25, 0x5a, 0x9f, 0xf6, 0x75, 0x4b, 0xe1,
+ 0x84, 0xbd, 0xca, 0x89, 0x6a, 0x2b, 0xf8, 0x3c,
+ 0xb5, 0x13, 0x0d, 0x75, 0x5b, 0x0c, 0x1e, 0xfe,
+ 0x9e, 0x1c, 0xac, 0xe4, 0x26, 0x0e, 0x4f, 0x1c,
+ 0x92, 0xa0, 0x1e, 0xf4, 0x1e, 0x09, 0x46, 0xbe,
+ 0xe1, 0x24, 0x50, 0x1d, 0x27, 0x79, 0x45, 0x0c,
+ 0x64, 0x5e, 0x6b, 0x31, 0x4b, 0x8e, 0xe5, 0xf4,
+ 0xbc, 0xe7, 0x23, 0x13, 0xd7, 0x49, 0xf0, 0x39,
+ 0x2e, 0x97, 0xb8, 0x6d, 0x82, 0x8b, 0x15, 0x72,
+ 0x7c, 0xb5, 0xfe, 0x7c, 0x8f, 0x4f, 0x82, 0xd5,
+ 0xed, 0xfa, 0x40, 0xa2, 0x49, 0xce, 0xe7, 0xd3,
+ 0x59, 0xef, 0xe4, 0xc4, 0x6d, 0x12, 0x4d, 0x8e,
+ 0x34, 0x53, 0x82, 0x44, 0xf7, 0xc9, 0x89, 0x5a,
+ 0x37, 0x93, 0x49, 0xce, 0x28, 0xdb, 0x64, 0x74,
+ 0x25, 0xc6, 0x49, 0x2e, 0x71, 0xbc, 0x33, 0x78,
+ 0x01, 0xc3, 0x02, 0xd2, 0x58, 0xed, 0x50, 0xb6,
+ 0x99, 0x38, 0x2c, 0x41, 0xc2, 0xc4, 0x5d, 0x68,
+ 0x18, 0x07, 0xb9, 0x44, 0xbd, 0xf0, 0xd4, 0x20,
+ 0x20, 0x5b, 0x54, 0xab, 0x67, 0xe3, 0xff, 0x64,
+ 0x78, 0xbc, 0x5b, 0x24, 0x18, 0x2a, 0xf2, 0x46,
+ 0x09, 0x46, 0x5b, 0x5b, 0x4a, 0x96, 0xe5, 0xc2,
+ 0xa0, 0x36, 0xa0, 0x0b, 0x09, 0x39, 0xa5, 0x0e,
+ 0x83, 0xe4, 0x3b, 0x64, 0x72, 0x4a, 0xf3, 0x60,
+ 0x1a, 0x2f, 0x4c, 0xe5, 0x0e, 0xf3, 0xde, 0x24,
+ 0xe8, 0x0c, 0x32, 0x52, 0x36, 0xb4, 0xe3, 0x2a,
+ 0x86, 0x2e, 0x6b, 0xc7, 0x67, 0x99, 0x87, 0x2c,
+ 0x11, 0xdd, 0x2a, 0x86, 0xda, 0x85, 0x1c, 0x9e,
+ 0x95, 0xe5, 0x9e, 0x99, 0xe0, 0xb7, 0x3b, 0x5f,
+ 0xe2, 0x82, 0x09, 0x6e, 0x08, 0x40, 0x7b, 0x89,
+ 0x72, 0x60, 0xfc, 0xb5, 0x6b, 0xbf, 0x17, 0x06,
+ 0x7f, 0x29, 0xaf, 0xd0, 0xa8, 0xe7, 0x7e, 0x6f,
+ 0x3e, 0x0b, 0x8d, 0xeb, 0xae, 0x9d, 0x98, 0x2a,
+ 0xe6, 0xcf, 0xe3, 0x0b, 0x25, 0xc6, 0xc7, 0x03,
+ 0xbf, 0x7f, 0xb7, 0x85, 0xfb, 0xae, 0x54, 0x5e,
+ 0x65, 0xed, 0x6c, 0x8e, 0xd0, 0x34, 0x25, 0x3b,
+ 0xf2, 0x52, 0x23, 0x34, 0x95, 0xb2, 0x1e, 0x77,
+ 0x46, 0xa9, 0xb5, 0xb8, 0x24, 0xd7, 0xda, 0x3b,
+ 0xbe, 0x69, 0xd6, 0xe3, 0xe4, 0x4d, 0x02, 0xbc,
+ 0xb6, 0xbb, 0xe2, 0x20, 0xcb, 0x92, 0x03, 0xe5,
+ 0x86, 0xd6, 0x0c, 0xcb, 0x37, 0x0f, 0xc5, 0x78,
+ 0x7c, 0x86, 0xee, 0x7e, 0xcd, 0xe7, 0x39, 0x24,
+ 0xdb, 0x5d, 0x74, 0x57, 0x9c, 0x9b, 0x64, 0x99,
+ 0xda, 0xc8, 0x36, 0x13, 0x59, 0x97, 0x09, 0xb9,
+ 0xbf, 0x5a, 0xc2, 0xd5, 0xc5, 0xe7, 0xe0, 0x33,
+ 0xcc, 0xbb, 0x78, 0x65, 0xdf, 0xe1, 0xee, 0x34,
+ 0x93, 0x93, 0x54, 0xb6, 0x4f, 0xff, 0xd6, 0xf2,
+ 0xd6, 0x67, 0x5c, 0xe8, 0xd0, 0x52, 0x99, 0x93,
+ 0x15, 0xff, 0x7f, 0x2d, 0x67, 0x46, 0x43, 0xa3,
+ 0xeb, 0x66, 0x5b, 0x93, 0x84, 0x3f, 0xdb, 0xa2,
+ 0x7e, 0x90, 0x62, 0xfe, 0x9b, 0x37, 0x4f, 0xd4,
+ 0xf1, 0xde, 0x7c, 0xd6, 0x79, 0x5d, 0x8a, 0x28,
+ 0xcd, 0x60, 0xb0, 0xff, 0x72, 0x3f, 0x6a, 0xe4,
+ 0x7d, 0x56, 0x19, 0xa1, 0x89, 0x3e, 0xd3, 0xe5,
+ 0xed, 0x0e, 0xbb, 0xf8, 0x4c, 0xfc, 0xbf, 0x67,
+ 0x67, 0x3b, 0xe3, 0x56, 0xd0, 0x73, 0x65, 0x9b,
+ 0x3f, 0x93, 0xc9, 0x5f, 0x25, 0xca, 0x73, 0xda,
+ 0x6b, 0xb2, 0x8d, 0x95, 0x8a, 0x4a, 0xb3, 0x4d,
+ 0x1a, 0x25, 0xf1, 0xff, 0x95, 0xa5, 0x12, 0xb4,
+ 0x9a, 0xbe, 0x52, 0xb6, 0x3b, 0x1e, 0xf6, 0xf3,
+ 0xc4, 0x4c, 0xd6, 0x71, 0x2f, 0xd6, 0x77, 0x65,
+ 0x9b, 0x4d, 0xbd, 0x7c, 0xb6, 0x49, 0x69, 0x0b,
+ 0xc3, 0x92, 0x56, 0xc7, 0x1e, 0x0e, 0x4a, 0x75,
+ 0xb8, 0x30, 0xe3, 0x7b, 0xea, 0x96, 0xcc, 0xf0,
+ 0x7b, 0xd5, 0x7e, 0xcf, 0x65, 0x47, 0x68, 0x5a,
+ 0x38, 0xfa, 0x59, 0xd6, 0xe5, 0x3b, 0xa6, 0xc4,
+ 0x85, 0x11, 0xd4, 0x6a, 0xd8, 0xaf, 0xd8, 0x36,
+ 0xe7, 0x62, 0xea, 0x9b, 0xd9, 0x6f, 0xd9, 0x47,
+ 0xba, 0x9f, 0x93, 0xef, 0x95, 0xcf, 0x54, 0x6b,
+ 0x3f, 0xb0, 0x2b, 0x98, 0x73, 0x55, 0x4d, 0xad,
+ 0x61, 0x13, 0x07, 0xcc, 0xda, 0x07, 0x57, 0x5f,
+ 0x46, 0x0e, 0x40, 0xc6, 0xee, 0xe5, 0x42, 0x61,
+ 0x51, 0x83, 0x10, 0x4e, 0x34, 0xe5, 0xc9, 0x75,
+ 0x6d, 0xf2, 0x39, 0x98, 0x70, 0xf3, 0x70, 0x46,
+ 0xf2, 0x99, 0x24, 0x8a, 0x15, 0x7c, 0x8e, 0x79,
+ 0xc7, 0x16, 0xc3, 0x48, 0x3e, 0x28, 0xdb, 0x9b,
+ 0xb7, 0x8d, 0x31, 0x72, 0xe8, 0x74, 0x8b, 0x21,
+ 0x57, 0x54, 0x4b, 0x58, 0xa9, 0x0b, 0xbd, 0x5f,
+ 0xb6, 0x35, 0x95, 0xa3, 0x6e, 0x1f, 0x73, 0xd3,
+ 0xf5, 0x79, 0x17, 0x0c, 0xfc, 0x43, 0xf3, 0x12,
+ 0x56, 0xb6, 0xc1, 0x90, 0x7b, 0xd5, 0x84, 0x75,
+ 0x0b, 0xb8, 0x50, 0xaa, 0x35, 0xba, 0x1a, 0xe3,
+ 0xfb, 0x1b, 0x8a, 0xbe, 0xad, 0xb5, 0xdf, 0xbe,
+ 0x76, 0x9f, 0xd6, 0xa5, 0xe4, 0xff, 0x66, 0x20,
+ 0x8f, 0xb2, 0x05, 0x3d, 0xb8, 0x78, 0x1f, 0x27,
+ 0x82, 0x24, 0x52, 0xcd, 0x58, 0xe3, 0xeb, 0x94,
+ 0xf7, 0xe6, 0x62, 0x90, 0x41, 0xed, 0xfb, 0x1a,
+ 0xbb, 0xb1, 0x7f, 0x91, 0xe8, 0x77, 0x13, 0x2c,
+ 0x7e, 0x2f, 0x6e, 0x97, 0xb8, 0x51, 0xf9, 0x6c,
+ 0xec, 0xb7, 0x8c, 0xab, 0x3e, 0x73, 0x1b, 0xc4,
+ 0x16, 0xbf, 0x03, 0xfb, 0x2b, 0x77, 0x28, 0xe3,
+ 0x0e, 0x4d, 0x8c, 0xcc, 0xb4, 0xe5, 0xaa, 0x99,
+ 0x9d, 0xc6, 0xc4, 0x55, 0x35, 0xef, 0x4b, 0x94,
+ 0xdd, 0x2e, 0x68, 0x58, 0x34, 0x37, 0x67, 0xb7,
+ 0x49, 0x39, 0xa0, 0x29, 0xb2, 0xe4, 0x26, 0x09,
+ 0x43, 0x6f, 0xa0, 0xbd, 0xd6, 0x2b, 0x63, 0x4e,
+ 0x2c, 0x09, 0xc6, 0x08, 0xa6, 0x01, 0x07, 0xc5,
+ 0xaf, 0x43, 0x90, 0x8b, 0xa6, 0xc5, 0x2f, 0xf7,
+ 0xc5, 0xac, 0xde, 0x2f, 0x77, 0x20, 0xba, 0x45,
+ 0xdc, 0x2e, 0xdb, 0xaa, 0xdd, 0x03, 0x96, 0xcf,
+ 0xca, 0xc5, 0x08, 0x2d, 0x7f, 0xa9, 0xb7, 0x5e,
+ 0xd8, 0x22, 0xb9, 0xc0, 0x05, 0xcd, 0xad, 0xb3,
+ 0x8d, 0xf2, 0xbe, 0x9d, 0x5b, 0x96, 0x6d, 0x92,
+ 0x33, 0xe5, 0xe4, 0x3c, 0xa4, 0xf5, 0x6c, 0xaf,
+ 0x24, 0x70, 0x24, 0x32, 0xb5, 0x92, 0x16, 0xba,
+ 0x38, 0xd5, 0xea, 0x4d, 0x87, 0xe8, 0x1b, 0x67,
+ 0x77, 0xdc, 0x2a, 0x99, 0x0b, 0x9e, 0x79, 0x17,
+ 0x28, 0x2b, 0xcb, 0xf7, 0x44, 0xc3, 0x34, 0x4a,
+ 0xc6, 0x6a, 0xf5, 0xe7, 0x25, 0x86, 0x2d, 0x64,
+ 0x90, 0x8b, 0x5a, 0x83, 0xa3, 0xb5, 0xcb, 0x67,
+ 0xa3, 0x2b, 0x1e, 0x37, 0x92, 0xa7, 0xdf, 0xee,
+ 0x2a, 0xc7, 0x18, 0xad, 0xef, 0x97, 0xb9, 0xb8,
+ 0xdc, 0xb1, 0x36, 0x76, 0x95, 0xbf, 0x5f, 0x58,
+ 0x2c, 0x3c, 0x25, 0x27, 0x1d, 0x8a, 0x04, 0xcb,
+ 0x22, 0xcc, 0x0f, 0xe7, 0xc0, 0x58, 0xd8, 0x71,
+ 0x3b, 0xeb, 0x72, 0xf7, 0x13, 0x46, 0x66, 0x1a,
+ 0x7b, 0xe1, 0xa2, 0x13, 0x6d, 0xd6, 0xe1, 0x62,
+ 0x8d, 0x84, 0xb9, 0x1c, 0xdd, 0xe7, 0xe4, 0xac,
+ 0x3b, 0xd5, 0x50, 0x2a, 0xcb, 0x52, 0x3f, 0x54,
+ 0x8e, 0x57, 0xfc, 0xb9, 0x2c, 0x37, 0x77, 0x00,
+ 0x80, 0xf6, 0x3d, 0x18, 0xa7, 0xf4, 0xf8, 0x04,
+ 0x2d, 0x43, 0x6b, 0x75, 0x99, 0x1c, 0xb4, 0x24,
+ 0x3c, 0x9c, 0x9c, 0x48, 0x58, 0xce, 0xc8, 0x76,
+ 0x33, 0x69, 0xd6, 0x67, 0xdf, 0x28, 0xef, 0x7f,
+ 0x0a, 0x72, 0x7f, 0xcb, 0x0c, 0x3e, 0x3e, 0x91,
+ 0x6d, 0x51, 0x4f, 0xc8, 0xf7, 0x44, 0x42, 0x4b,
+ 0x1f, 0xd6, 0xda, 0x49, 0x96, 0x84, 0x84, 0x0b,
+ 0x15, 0x8a, 0xda, 0x5f, 0x9c, 0xf7, 0xe8, 0x4d,
+ 0x90, 0xb3, 0x3d, 0xc6, 0x0e, 0xa6, 0x55, 0x31,
+ 0xff, 0x1f, 0x5d, 0x6b, 0x6a, 0x57, 0xfb, 0x6c,
+ 0x8f, 0xcf, 0xc9, 0xbe, 0xc7, 0xf7, 0xda, 0x37,
+ 0xb8, 0xc4, 0x44, 0xb6, 0xcb, 0x84, 0x61, 0xf8,
+ 0x68, 0x0c, 0x43, 0xfd, 0x70, 0x6d, 0x7c, 0x58,
+ 0x50, 0xcc, 0x48, 0xae, 0x92, 0xdf, 0xf9, 0x8d,
+ 0xd9, 0xf6, 0xc2, 0x04, 0x39, 0xdb, 0xe6, 0x3b,
+ 0x2e, 0x1b, 0x60, 0xbd, 0x28, 0xeb, 0xbe, 0xb2,
+ 0x9d, 0xef, 0x95, 0x75, 0xe9, 0xbb, 0xcb, 0xcd,
+ 0x21, 0x8e, 0x4a, 0x94, 0xa3, 0x57, 0xf1, 0xde,
+ 0xef, 0xcf, 0x76, 0x16, 0xd6, 0x99, 0x67, 0x3b,
+ 0xdc, 0xbb, 0xb6, 0xd6, 0x60, 0x8c, 0x7b, 0xdd,
+ 0x6e, 0x29, 0x27, 0x97, 0x6d, 0xb3, 0x2f, 0x53,
+ 0xff, 0x59, 0x16, 0x0d, 0x93, 0x4b, 0x24, 0x31,
+ 0xa3, 0xf8, 0x9d, 0xef, 0x60, 0x95, 0xdc, 0x76,
+ 0x89, 0x6e, 0x59, 0x33, 0x37, 0x57, 0xc8, 0x67,
+ 0xa0, 0x91, 0x12, 0xb7, 0xbd, 0xa3, 0xf4, 0xe6,
+ 0xd0, 0xc4, 0xf8, 0xbb, 0x22, 0x77, 0xcb, 0x45,
+ 0x2f, 0xed, 0x20, 0x18, 0x31, 0xed, 0x9b, 0x59,
+ 0x96, 0xb1, 0x91, 0x6b, 0xdf, 0xfd, 0x5d, 0xf2,
+ 0x7a, 0xf7, 0x2e, 0x57, 0x14, 0x79, 0x4f, 0x6e,
+ 0x77, 0xd8, 0x31, 0xe8, 0x38, 0xc8, 0x76, 0x98,
+ 0xd0, 0xf5, 0x88, 0xcf, 0x47, 0x3f, 0xe0, 0xbe,
+ 0x01, 0x5e, 0xf8, 0x3d, 0xb9, 0x2f, 0x31, 0x89,
+ 0x3f, 0x17, 0x2c, 0x1f, 0xcd, 0xfb, 0x64, 0xb2,
+ 0x7b, 0x99, 0xb8, 0x0e, 0xb7, 0x63, 0x12, 0xd7,
+ 0xdd, 0x2e, 0x07, 0x36, 0x5d, 0x0f, 0xa8, 0xa3,
+ 0xe5, 0xe4, 0xc3, 0xc9, 0x8f, 0xdc, 0x20, 0xb9,
+ 0x15, 0x6e, 0x35, 0x76, 0x56, 0x0e, 0x5e, 0x12,
+ 0xa2, 0x8d, 0xcb, 0xe7, 0x60, 0xbf, 0xa3, 0x6e,
+ 0x90, 0x96, 0xc3, 0x74, 0xb7, 0x21, 0x51, 0xa4,
+ 0x3e, 0x8e, 0xba, 0xb9, 0x4f, 0x26, 0xe8, 0xa3,
+ 0xba, 0xf4, 0x55, 0x7a, 0x7b, 0xc2, 0xe2, 0x7f,
+ 0xe3, 0x44, 0xca, 0xad, 0xd3, 0x48, 0xc4, 0xe9,
+ 0x06, 0xc4, 0xf6, 0x38, 0x41, 0x7d, 0x69, 0xc8,
+ 0xf6, 0xba, 0xb2, 0x6d, 0x12, 0x01, 0x12, 0x57,
+ 0x8a, 0xea, 0x28, 0xd2, 0xe4, 0x82, 0x80, 0xe2,
+ 0x4f, 0xea, 0xc0, 0x3e, 0x95, 0xed, 0x2e, 0xbc,
+ 0xa5, 0xdd, 0x3a, 0xb5, 0xff, 0x2b, 0x9f, 0x83,
+ 0x22, 0x44, 0x8e, 0x5b, 0x9e, 0xe0, 0x18, 0x26,
+ 0xe7, 0xfc, 0xd5, 0x55, 0xff, 0xcf, 0xdd, 0xa8,
+ 0xdd, 0xcf, 0xb8, 0x98, 0xa4, 0x5b, 0x15, 0xdf,
+ 0x0b, 0xb9, 0xc7, 0xef, 0xe4, 0x3b, 0xca, 0x64,
+ 0xff, 0xcb, 0xe7, 0x23, 0xd1, 0xa7, 0x45, 0x33,
+ 0x31, 0x1e, 0xc8, 0x83, 0xcf, 0x48, 0xa2, 0x4e,
+ 0x17, 0xbf, 0xaf, 0x1f, 0x48, 0xbf, 0xa7, 0x89,
+ 0xeb, 0x70, 0x26, 0xae, 0x92, 0xa4, 0xb9, 0xac,
+ 0x73, 0x95, 0x24, 0x69, 0xcd, 0x4c, 0x5c, 0x25,
+ 0x49, 0x5a, 0x33, 0x13, 0x57, 0x49, 0x92, 0xd6,
+ 0xcc, 0xc4, 0x55, 0x92, 0xa4, 0x35, 0x33, 0x71,
+ 0x95, 0x24, 0x69, 0xcd, 0x4c, 0x5c, 0x25, 0x49,
+ 0x5a, 0x33, 0x13, 0x57, 0x49, 0x92, 0xd6, 0xcc,
+ 0xc4, 0x55, 0x92, 0xa4, 0x35, 0xdb, 0x6d, 0x83,
+ 0x48, 0xf0, 0x97, 0x7b, 0x0a, 0x96, 0x43, 0xa9,
+ 0xad, 0xd3, 0x77, 0xf7, 0x1c, 0x73, 0x70, 0x33,
+ 0xc6, 0xee, 0x39, 0xef, 0x6a, 0x46, 0x07, 0xda,
+ 0xe4, 0x80, 0x15, 0xf8, 0xc8, 0xde, 0xdb, 0x37,
+ 0xc3, 0x9c, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24,
+ 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92,
+ 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49,
+ 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24,
+ 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92,
+ 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49,
+ 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24,
+ 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92,
+ 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49,
+ 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24,
+ 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92,
+ 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49,
+ 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24,
+ 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92,
+ 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49,
+ 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24,
+ 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92,
+ 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49,
+ 0x5b, 0xb7, 0x67, 0xcf, 0xff, 0x03, 0x27, 0xa6,
+ 0xaa, 0x9c, 0x80, 0xec, 0x5b, 0x07, 0x00, 0x00,
+ 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42,
+ 0x60, 0x82,
+};
+
+unsigned int mslogo_jpg_size = sizeof(mslogo_jpg);
+
+const unsigned char nxlogo_png[] = {
+ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00,
+ 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x01, 0x34, 0x00, 0x00,
+ 0x00, 0x55, 0x08, 0x06, 0x00, 0x00, 0x00, 0xc7, 0x5e, 0x18, 0xd4,
+ 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x2e,
+ 0x23, 0x00, 0x00, 0x2e, 0x23, 0x01, 0x78, 0xa5, 0x3f, 0x76, 0x00,
+ 0x00, 0x0a, 0x4f, 0x69, 0x43, 0x43, 0x50, 0x50, 0x68, 0x6f, 0x74,
+ 0x6f, 0x73, 0x68, 0x6f, 0x70, 0x20, 0x49, 0x43, 0x43, 0x20, 0x70,
+ 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x78, 0xda, 0x9d,
+ 0x53, 0x67, 0x54, 0x53, 0xe9, 0x16, 0x3d, 0xf7, 0xde, 0xf4, 0x42,
+ 0x4b, 0x88, 0x80, 0x94, 0x4b, 0x6f, 0x52, 0x15, 0x08, 0x20, 0x52,
+ 0x42, 0x8b, 0x80, 0x14, 0x91, 0x26, 0x2a, 0x21, 0x09, 0x10, 0x4a,
+ 0x88, 0x21, 0xa1, 0xd9, 0x15, 0x51, 0xc1, 0x11, 0x45, 0x45, 0x04,
+ 0x1b, 0xc8, 0xa0, 0x88, 0x03, 0x8e, 0x8e, 0x80, 0x8c, 0x15, 0x51,
+ 0x2c, 0x0c, 0x8a, 0x0a, 0xd8, 0x07, 0xe4, 0x21, 0xa2, 0x8e, 0x83,
+ 0xa3, 0x88, 0x8a, 0xca, 0xfb, 0xe1, 0x7b, 0xa3, 0x6b, 0xd6, 0xbc,
+ 0xf7, 0xe6, 0xcd, 0xfe, 0xb5, 0xd7, 0x3e, 0xe7, 0xac, 0xf3, 0x9d,
+ 0xb3, 0xcf, 0x07, 0xc0, 0x08, 0x0c, 0x96, 0x48, 0x33, 0x51, 0x35,
+ 0x80, 0x0c, 0xa9, 0x42, 0x1e, 0x11, 0xe0, 0x83, 0xc7, 0xc4, 0xc6,
+ 0xe1, 0xe4, 0x2e, 0x40, 0x81, 0x0a, 0x24, 0x70, 0x00, 0x10, 0x08,
+ 0xb3, 0x64, 0x21, 0x73, 0xfd, 0x23, 0x01, 0x00, 0xf8, 0x7e, 0x3c,
+ 0x3c, 0x2b, 0x22, 0xc0, 0x07, 0xbe, 0x00, 0x01, 0x78, 0xd3, 0x0b,
+ 0x08, 0x00, 0xc0, 0x4d, 0x9b, 0xc0, 0x30, 0x1c, 0x87, 0xff, 0x0f,
+ 0xea, 0x42, 0x99, 0x5c, 0x01, 0x80, 0x84, 0x01, 0xc0, 0x74, 0x91,
+ 0x38, 0x4b, 0x08, 0x80, 0x14, 0x00, 0x40, 0x7a, 0x8e, 0x42, 0xa6,
+ 0x00, 0x40, 0x46, 0x01, 0x80, 0x9d, 0x98, 0x26, 0x53, 0x00, 0xa0,
+ 0x04, 0x00, 0x60, 0xcb, 0x63, 0x62, 0xe3, 0x00, 0x50, 0x2d, 0x00,
+ 0x60, 0x27, 0x7f, 0xe6, 0xd3, 0x00, 0x80, 0x9d, 0xf8, 0x99, 0x7b,
+ 0x01, 0x00, 0x5b, 0x94, 0x21, 0x15, 0x01, 0xa0, 0x91, 0x00, 0x20,
+ 0x13, 0x65, 0x88, 0x44, 0x00, 0x68, 0x3b, 0x00, 0xac, 0xcf, 0x56,
+ 0x8a, 0x45, 0x00, 0x58, 0x30, 0x00, 0x14, 0x66, 0x4b, 0xc4, 0x39,
+ 0x00, 0xd8, 0x2d, 0x00, 0x30, 0x49, 0x57, 0x66, 0x48, 0x00, 0xb0,
+ 0xb7, 0x00, 0xc0, 0xce, 0x10, 0x0b, 0xb2, 0x00, 0x08, 0x0c, 0x00,
+ 0x30, 0x51, 0x88, 0x85, 0x29, 0x00, 0x04, 0x7b, 0x00, 0x60, 0xc8,
+ 0x23, 0x23, 0x78, 0x00, 0x84, 0x99, 0x00, 0x14, 0x46, 0xf2, 0x57,
+ 0x3c, 0xf1, 0x2b, 0xae, 0x10, 0xe7, 0x2a, 0x00, 0x00, 0x78, 0x99,
+ 0xb2, 0x3c, 0xb9, 0x24, 0x39, 0x45, 0x81, 0x5b, 0x08, 0x2d, 0x71,
+ 0x07, 0x57, 0x57, 0x2e, 0x1e, 0x28, 0xce, 0x49, 0x17, 0x2b, 0x14,
+ 0x36, 0x61, 0x02, 0x61, 0x9a, 0x40, 0x2e, 0xc2, 0x79, 0x99, 0x19,
+ 0x32, 0x81, 0x34, 0x0f, 0xe0, 0xf3, 0xcc, 0x00, 0x00, 0xa0, 0x91,
+ 0x15, 0x11, 0xe0, 0x83, 0xf3, 0xfd, 0x78, 0xce, 0x0e, 0xae, 0xce,
+ 0xce, 0x36, 0x8e, 0xb6, 0x0e, 0x5f, 0x2d, 0xea, 0xbf, 0x06, 0xff,
+ 0x22, 0x62, 0x62, 0xe3, 0xfe, 0xe5, 0xcf, 0xab, 0x70, 0x40, 0x00,
+ 0x00, 0xe1, 0x74, 0x7e, 0xd1, 0xfe, 0x2c, 0x2f, 0xb3, 0x1a, 0x80,
+ 0x3b, 0x06, 0x80, 0x6d, 0xfe, 0xa2, 0x25, 0xee, 0x04, 0x68, 0x5e,
+ 0x0b, 0xa0, 0x75, 0xf7, 0x8b, 0x66, 0xb2, 0x0f, 0x40, 0xb5, 0x00,
+ 0xa0, 0xe9, 0xda, 0x57, 0xf3, 0x70, 0xf8, 0x7e, 0x3c, 0x3c, 0x45,
+ 0xa1, 0x90, 0xb9, 0xd9, 0xd9, 0xe5, 0xe4, 0xe4, 0xd8, 0x4a, 0xc4,
+ 0x42, 0x5b, 0x61, 0xca, 0x57, 0x7d, 0xfe, 0x67, 0xc2, 0x5f, 0xc0,
+ 0x57, 0xfd, 0x6c, 0xf9, 0x7e, 0x3c, 0xfc, 0xf7, 0xf5, 0xe0, 0xbe,
+ 0xe2, 0x24, 0x81, 0x32, 0x5d, 0x81, 0x47, 0x04, 0xf8, 0xe0, 0xc2,
+ 0xcc, 0xf4, 0x4c, 0xa5, 0x1c, 0xcf, 0x92, 0x09, 0x84, 0x62, 0xdc,
+ 0xe6, 0x8f, 0x47, 0xfc, 0xb7, 0x0b, 0xff, 0xfc, 0x1d, 0xd3, 0x22,
+ 0xc4, 0x49, 0x62, 0xb9, 0x58, 0x2a, 0x14, 0xe3, 0x51, 0x12, 0x71,
+ 0x8e, 0x44, 0x9a, 0x8c, 0xf3, 0x32, 0xa5, 0x22, 0x89, 0x42, 0x92,
+ 0x29, 0xc5, 0x25, 0xd2, 0xff, 0x64, 0xe2, 0xdf, 0x2c, 0xfb, 0x03,
+ 0x3e, 0xdf, 0x35, 0x00, 0xb0, 0x6a, 0x3e, 0x01, 0x7b, 0x91, 0x2d,
+ 0xa8, 0x5d, 0x63, 0x03, 0xf6, 0x4b, 0x27, 0x10, 0x58, 0x74, 0xc0,
+ 0xe2, 0xf7, 0x00, 0x00, 0xf2, 0xbb, 0x6f, 0xc1, 0xd4, 0x28, 0x08,
+ 0x03, 0x80, 0x68, 0x83, 0xe1, 0xcf, 0x77, 0xff, 0xef, 0x3f, 0xfd,
+ 0x47, 0xa0, 0x25, 0x00, 0x80, 0x66, 0x49, 0x92, 0x71, 0x00, 0x00,
+ 0x5e, 0x44, 0x24, 0x2e, 0x54, 0xca, 0xb3, 0x3f, 0xc7, 0x08, 0x00,
+ 0x00, 0x44, 0xa0, 0x81, 0x2a, 0xb0, 0x41, 0x1b, 0xf4, 0xc1, 0x18,
+ 0x2c, 0xc0, 0x06, 0x1c, 0xc1, 0x05, 0xdc, 0xc1, 0x0b, 0xfc, 0x60,
+ 0x36, 0x84, 0x42, 0x24, 0xc4, 0xc2, 0x42, 0x10, 0x42, 0x0a, 0x64,
+ 0x80, 0x1c, 0x72, 0x60, 0x29, 0xac, 0x82, 0x42, 0x28, 0x86, 0xcd,
+ 0xb0, 0x1d, 0x2a, 0x60, 0x2f, 0xd4, 0x40, 0x1d, 0x34, 0xc0, 0x51,
+ 0x68, 0x86, 0x93, 0x70, 0x0e, 0x2e, 0xc2, 0x55, 0xb8, 0x0e, 0x3d,
+ 0x70, 0x0f, 0xfa, 0x61, 0x08, 0x9e, 0xc1, 0x28, 0xbc, 0x81, 0x09,
+ 0x04, 0x41, 0xc8, 0x08, 0x13, 0x61, 0x21, 0xda, 0x88, 0x01, 0x62,
+ 0x8a, 0x58, 0x23, 0x8e, 0x08, 0x17, 0x99, 0x85, 0xf8, 0x21, 0xc1,
+ 0x48, 0x04, 0x12, 0x8b, 0x24, 0x20, 0xc9, 0x88, 0x14, 0x51, 0x22,
+ 0x4b, 0x91, 0x35, 0x48, 0x31, 0x52, 0x8a, 0x54, 0x20, 0x55, 0x48,
+ 0x1d, 0xf2, 0x3d, 0x72, 0x02, 0x39, 0x87, 0x5c, 0x46, 0xba, 0x91,
+ 0x3b, 0xc8, 0x00, 0x32, 0x82, 0xfc, 0x86, 0xbc, 0x47, 0x31, 0x94,
+ 0x81, 0xb2, 0x51, 0x3d, 0xd4, 0x0c, 0xb5, 0x43, 0xb9, 0xa8, 0x37,
+ 0x1a, 0x84, 0x46, 0xa2, 0x0b, 0xd0, 0x64, 0x74, 0x31, 0x9a, 0x8f,
+ 0x16, 0xa0, 0x9b, 0xd0, 0x72, 0xb4, 0x1a, 0x3d, 0x8c, 0x36, 0xa1,
+ 0xe7, 0xd0, 0xab, 0x68, 0x0f, 0xda, 0x8f, 0x3e, 0x43, 0xc7, 0x30,
+ 0xc0, 0xe8, 0x18, 0x07, 0x33, 0xc4, 0x6c, 0x30, 0x2e, 0xc6, 0xc3,
+ 0x42, 0xb1, 0x38, 0x2c, 0x09, 0x93, 0x63, 0xcb, 0xb1, 0x22, 0xac,
+ 0x0c, 0xab, 0xc6, 0x1a, 0xb0, 0x56, 0xac, 0x03, 0xbb, 0x89, 0xf5,
+ 0x63, 0xcf, 0xb1, 0x77, 0x04, 0x12, 0x81, 0x45, 0xc0, 0x09, 0x36,
+ 0x04, 0x77, 0x42, 0x20, 0x61, 0x1e, 0x41, 0x48, 0x58, 0x4c, 0x58,
+ 0x4e, 0xd8, 0x48, 0xa8, 0x20, 0x1c, 0x24, 0x34, 0x11, 0xda, 0x09,
+ 0x37, 0x09, 0x03, 0x84, 0x51, 0xc2, 0x27, 0x22, 0x93, 0xa8, 0x4b,
+ 0xb4, 0x26, 0xba, 0x11, 0xf9, 0xc4, 0x18, 0x62, 0x32, 0x31, 0x87,
+ 0x58, 0x48, 0x2c, 0x23, 0xd6, 0x12, 0x8f, 0x13, 0x2f, 0x10, 0x7b,
+ 0x88, 0x43, 0xc4, 0x37, 0x24, 0x12, 0x89, 0x43, 0x32, 0x27, 0xb9,
+ 0x90, 0x02, 0x49, 0xb1, 0xa4, 0x54, 0xd2, 0x12, 0xd2, 0x46, 0xd2,
+ 0x6e, 0x52, 0x23, 0xe9, 0x2c, 0xa9, 0x9b, 0x34, 0x48, 0x1a, 0x23,
+ 0x93, 0xc9, 0xda, 0x64, 0x6b, 0xb2, 0x07, 0x39, 0x94, 0x2c, 0x20,
+ 0x2b, 0xc8, 0x85, 0xe4, 0x9d, 0xe4, 0xc3, 0xe4, 0x33, 0xe4, 0x1b,
+ 0xe4, 0x21, 0xf2, 0x5b, 0x0a, 0x9d, 0x62, 0x40, 0x71, 0xa4, 0xf8,
+ 0x53, 0xe2, 0x28, 0x52, 0xca, 0x6a, 0x4a, 0x19, 0xe5, 0x10, 0xe5,
+ 0x34, 0xe5, 0x06, 0x65, 0x98, 0x32, 0x41, 0x55, 0xa3, 0x9a, 0x52,
+ 0xdd, 0xa8, 0xa1, 0x54, 0x11, 0x35, 0x8f, 0x5a, 0x42, 0xad, 0xa1,
+ 0xb6, 0x52, 0xaf, 0x51, 0x87, 0xa8, 0x13, 0x34, 0x75, 0x9a, 0x39,
+ 0xcd, 0x83, 0x16, 0x49, 0x4b, 0xa5, 0xad, 0xa2, 0x95, 0xd3, 0x1a,
+ 0x68, 0x17, 0x68, 0xf7, 0x69, 0xaf, 0xe8, 0x74, 0xba, 0x11, 0xdd,
+ 0x95, 0x1e, 0x4e, 0x97, 0xd0, 0x57, 0xd2, 0xcb, 0xe9, 0x47, 0xe8,
+ 0x97, 0xe8, 0x03, 0xf4, 0x77, 0x0c, 0x0d, 0x86, 0x15, 0x83, 0xc7,
+ 0x88, 0x67, 0x28, 0x19, 0x9b, 0x18, 0x07, 0x18, 0x67, 0x19, 0x77,
+ 0x18, 0xaf, 0x98, 0x4c, 0xa6, 0x19, 0xd3, 0x8b, 0x19, 0xc7, 0x54,
+ 0x30, 0x37, 0x31, 0xeb, 0x98, 0xe7, 0x99, 0x0f, 0x99, 0x6f, 0x55,
+ 0x58, 0x2a, 0xb6, 0x2a, 0x7c, 0x15, 0x91, 0xca, 0x0a, 0x95, 0x4a,
+ 0x95, 0x26, 0x95, 0x1b, 0x2a, 0x2f, 0x54, 0xa9, 0xaa, 0xa6, 0xaa,
+ 0xde, 0xaa, 0x0b, 0x55, 0xf3, 0x55, 0xcb, 0x54, 0x8f, 0xa9, 0x5e,
+ 0x53, 0x7d, 0xae, 0x46, 0x55, 0x33, 0x53, 0xe3, 0xa9, 0x09, 0xd4,
+ 0x96, 0xab, 0x55, 0xaa, 0x9d, 0x50, 0xeb, 0x53, 0x1b, 0x53, 0x67,
+ 0xa9, 0x3b, 0xa8, 0x87, 0xaa, 0x67, 0xa8, 0x6f, 0x54, 0x3f, 0xa4,
+ 0x7e, 0x59, 0xfd, 0x89, 0x06, 0x59, 0xc3, 0x4c, 0xc3, 0x4f, 0x43,
+ 0xa4, 0x51, 0xa0, 0xb1, 0x5f, 0xe3, 0xbc, 0xc6, 0x20, 0x0b, 0x63,
+ 0x19, 0xb3, 0x78, 0x2c, 0x21, 0x6b, 0x0d, 0xab, 0x86, 0x75, 0x81,
+ 0x35, 0xc4, 0x26, 0xb1, 0xcd, 0xd9, 0x7c, 0x76, 0x2a, 0xbb, 0x98,
+ 0xfd, 0x1d, 0xbb, 0x8b, 0x3d, 0xaa, 0xa9, 0xa1, 0x39, 0x43, 0x33,
+ 0x4a, 0x33, 0x57, 0xb3, 0x52, 0xf3, 0x94, 0x66, 0x3f, 0x07, 0xe3,
+ 0x98, 0x71, 0xf8, 0x9c, 0x74, 0x4e, 0x09, 0xe7, 0x28, 0xa7, 0x97,
+ 0xf3, 0x7e, 0x8a, 0xde, 0x14, 0xef, 0x29, 0xe2, 0x29, 0x1b, 0xa6,
+ 0x34, 0x4c, 0xb9, 0x31, 0x65, 0x5c, 0x6b, 0xaa, 0x96, 0x97, 0x96,
+ 0x58, 0xab, 0x48, 0xab, 0x51, 0xab, 0x47, 0xeb, 0xbd, 0x36, 0xae,
+ 0xed, 0xa7, 0x9d, 0xa6, 0xbd, 0x45, 0xbb, 0x59, 0xfb, 0x81, 0x0e,
+ 0x41, 0xc7, 0x4a, 0x27, 0x5c, 0x27, 0x47, 0x67, 0x8f, 0xce, 0x05,
+ 0x9d, 0xe7, 0x53, 0xd9, 0x53, 0xdd, 0xa7, 0x0a, 0xa7, 0x16, 0x4d,
+ 0x3d, 0x3a, 0xf5, 0xae, 0x2e, 0xaa, 0x6b, 0xa5, 0x1b, 0xa1, 0xbb,
+ 0x44, 0x77, 0xbf, 0x6e, 0xa7, 0xee, 0x98, 0x9e, 0xbe, 0x5e, 0x80,
+ 0x9e, 0x4c, 0x6f, 0xa7, 0xde, 0x79, 0xbd, 0xe7, 0xfa, 0x1c, 0x7d,
+ 0x2f, 0xfd, 0x54, 0xfd, 0x6d, 0xfa, 0xa7, 0xf5, 0x47, 0x0c, 0x58,
+ 0x06, 0xb3, 0x0c, 0x24, 0x06, 0xdb, 0x0c, 0xce, 0x18, 0x3c, 0xc5,
+ 0x35, 0x71, 0x6f, 0x3c, 0x1d, 0x2f, 0xc7, 0xdb, 0xf1, 0x51, 0x43,
+ 0x5d, 0xc3, 0x40, 0x43, 0xa5, 0x61, 0x95, 0x61, 0x97, 0xe1, 0x84,
+ 0x91, 0xb9, 0xd1, 0x3c, 0xa3, 0xd5, 0x46, 0x8d, 0x46, 0x0f, 0x8c,
+ 0x69, 0xc6, 0x5c, 0xe3, 0x24, 0xe3, 0x6d, 0xc6, 0x6d, 0xc6, 0xa3,
+ 0x26, 0x06, 0x26, 0x21, 0x26, 0x4b, 0x4d, 0xea, 0x4d, 0xee, 0x9a,
+ 0x52, 0x4d, 0xb9, 0xa6, 0x29, 0xa6, 0x3b, 0x4c, 0x3b, 0x4c, 0xc7,
+ 0xcd, 0xcc, 0xcd, 0xa2, 0xcd, 0xd6, 0x99, 0x35, 0x9b, 0x3d, 0x31,
+ 0xd7, 0x32, 0xe7, 0x9b, 0xe7, 0x9b, 0xd7, 0x9b, 0xdf, 0xb7, 0x60,
+ 0x5a, 0x78, 0x5a, 0x2c, 0xb6, 0xa8, 0xb6, 0xb8, 0x65, 0x49, 0xb2,
+ 0xe4, 0x5a, 0xa6, 0x59, 0xee, 0xb6, 0xbc, 0x6e, 0x85, 0x5a, 0x39,
+ 0x59, 0xa5, 0x58, 0x55, 0x5a, 0x5d, 0xb3, 0x46, 0xad, 0x9d, 0xad,
+ 0x25, 0xd6, 0xbb, 0xad, 0xbb, 0xa7, 0x11, 0xa7, 0xb9, 0x4e, 0x93,
+ 0x4e, 0xab, 0x9e, 0xd6, 0x67, 0xc3, 0xb0, 0xf1, 0xb6, 0xc9, 0xb6,
+ 0xa9, 0xb7, 0x19, 0xb0, 0xe5, 0xd8, 0x06, 0xdb, 0xae, 0xb6, 0x6d,
+ 0xb6, 0x7d, 0x61, 0x67, 0x62, 0x17, 0x67, 0xb7, 0xc5, 0xae, 0xc3,
+ 0xee, 0x93, 0xbd, 0x93, 0x7d, 0xba, 0x7d, 0x8d, 0xfd, 0x3d, 0x07,
+ 0x0d, 0x87, 0xd9, 0x0e, 0xab, 0x1d, 0x5a, 0x1d, 0x7e, 0x73, 0xb4,
+ 0x72, 0x14, 0x3a, 0x56, 0x3a, 0xde, 0x9a, 0xce, 0x9c, 0xee, 0x3f,
+ 0x7d, 0xc5, 0xf4, 0x96, 0xe9, 0x2f, 0x67, 0x58, 0xcf, 0x10, 0xcf,
+ 0xd8, 0x33, 0xe3, 0xb6, 0x13, 0xcb, 0x29, 0xc4, 0x69, 0x9d, 0x53,
+ 0x9b, 0xd3, 0x47, 0x67, 0x17, 0x67, 0xb9, 0x73, 0x83, 0xf3, 0x88,
+ 0x8b, 0x89, 0x4b, 0x82, 0xcb, 0x2e, 0x97, 0x3e, 0x2e, 0x9b, 0x1b,
+ 0xc6, 0xdd, 0xc8, 0xbd, 0xe4, 0x4a, 0x74, 0xf5, 0x71, 0x5d, 0xe1,
+ 0x7a, 0xd2, 0xf5, 0x9d, 0x9b, 0xb3, 0x9b, 0xc2, 0xed, 0xa8, 0xdb,
+ 0xaf, 0xee, 0x36, 0xee, 0x69, 0xee, 0x87, 0xdc, 0x9f, 0xcc, 0x34,
+ 0x9f, 0x29, 0x9e, 0x59, 0x33, 0x73, 0xd0, 0xc3, 0xc8, 0x43, 0xe0,
+ 0x51, 0xe5, 0xd1, 0x3f, 0x0b, 0x9f, 0x95, 0x30, 0x6b, 0xdf, 0xac,
+ 0x7e, 0x4f, 0x43, 0x4f, 0x81, 0x67, 0xb5, 0xe7, 0x23, 0x2f, 0x63,
+ 0x2f, 0x91, 0x57, 0xad, 0xd7, 0xb0, 0xb7, 0xa5, 0x77, 0xaa, 0xf7,
+ 0x61, 0xef, 0x17, 0x3e, 0xf6, 0x3e, 0x72, 0x9f, 0xe3, 0x3e, 0xe3,
+ 0x3c, 0x37, 0xde, 0x32, 0xde, 0x59, 0x5f, 0xcc, 0x37, 0xc0, 0xb7,
+ 0xc8, 0xb7, 0xcb, 0x4f, 0xc3, 0x6f, 0x9e, 0x5f, 0x85, 0xdf, 0x43,
+ 0x7f, 0x23, 0xff, 0x64, 0xff, 0x7a, 0xff, 0xd1, 0x00, 0xa7, 0x80,
+ 0x25, 0x01, 0x67, 0x03, 0x89, 0x81, 0x41, 0x81, 0x5b, 0x02, 0xfb,
+ 0xf8, 0x7a, 0x7c, 0x21, 0xbf, 0x8e, 0x3f, 0x3a, 0xdb, 0x65, 0xf6,
+ 0xb2, 0xd9, 0xed, 0x41, 0x8c, 0xa0, 0xb9, 0x41, 0x15, 0x41, 0x8f,
+ 0x82, 0xad, 0x82, 0xe5, 0xc1, 0xad, 0x21, 0x68, 0xc8, 0xec, 0x90,
+ 0xad, 0x21, 0xf7, 0xe7, 0x98, 0xce, 0x91, 0xce, 0x69, 0x0e, 0x85,
+ 0x50, 0x7e, 0xe8, 0xd6, 0xd0, 0x07, 0x61, 0xe6, 0x61, 0x8b, 0xc3,
+ 0x7e, 0x0c, 0x27, 0x85, 0x87, 0x85, 0x57, 0x86, 0x3f, 0x8e, 0x70,
+ 0x88, 0x58, 0x1a, 0xd1, 0x31, 0x97, 0x35, 0x77, 0xd1, 0xdc, 0x43,
+ 0x73, 0xdf, 0x44, 0xfa, 0x44, 0x96, 0x44, 0xde, 0x9b, 0x67, 0x31,
+ 0x4f, 0x39, 0xaf, 0x2d, 0x4a, 0x35, 0x2a, 0x3e, 0xaa, 0x2e, 0x6a,
+ 0x3c, 0xda, 0x37, 0xba, 0x34, 0xba, 0x3f, 0xc6, 0x2e, 0x66, 0x59,
+ 0xcc, 0xd5, 0x58, 0x9d, 0x58, 0x49, 0x6c, 0x4b, 0x1c, 0x39, 0x2e,
+ 0x2a, 0xae, 0x36, 0x6e, 0x6c, 0xbe, 0xdf, 0xfc, 0xed, 0xf3, 0x87,
+ 0xe2, 0x9d, 0xe2, 0x0b, 0xe3, 0x7b, 0x17, 0x98, 0x2f, 0xc8, 0x5d,
+ 0x70, 0x79, 0xa1, 0xce, 0xc2, 0xf4, 0x85, 0xa7, 0x16, 0xa9, 0x2e,
+ 0x12, 0x2c, 0x3a, 0x96, 0x40, 0x4c, 0x88, 0x4e, 0x38, 0x94, 0xf0,
+ 0x41, 0x10, 0x2a, 0xa8, 0x16, 0x8c, 0x25, 0xf2, 0x13, 0x77, 0x25,
+ 0x8e, 0x0a, 0x79, 0xc2, 0x1d, 0xc2, 0x67, 0x22, 0x2f, 0xd1, 0x36,
+ 0xd1, 0x88, 0xd8, 0x43, 0x5c, 0x2a, 0x1e, 0x4e, 0xf2, 0x48, 0x2a,
+ 0x4d, 0x7a, 0x92, 0xec, 0x91, 0xbc, 0x35, 0x79, 0x24, 0xc5, 0x33,
+ 0xa5, 0x2c, 0xe5, 0xb9, 0x84, 0x27, 0xa9, 0x90, 0xbc, 0x4c, 0x0d,
+ 0x4c, 0xdd, 0x9b, 0x3a, 0x9e, 0x16, 0x9a, 0x76, 0x20, 0x6d, 0x32,
+ 0x3d, 0x3a, 0xbd, 0x31, 0x83, 0x92, 0x91, 0x90, 0x71, 0x42, 0xaa,
+ 0x21, 0x4d, 0x93, 0xb6, 0x67, 0xea, 0x67, 0xe6, 0x66, 0x76, 0xcb,
+ 0xac, 0x65, 0x85, 0xb2, 0xfe, 0xc5, 0x6e, 0x8b, 0xb7, 0x2f, 0x1e,
+ 0x95, 0x07, 0xc9, 0x6b, 0xb3, 0x90, 0xac, 0x05, 0x59, 0x2d, 0x0a,
+ 0xb6, 0x42, 0xa6, 0xe8, 0x54, 0x5a, 0x28, 0xd7, 0x2a, 0x07, 0xb2,
+ 0x67, 0x65, 0x57, 0x66, 0xbf, 0xcd, 0x89, 0xca, 0x39, 0x96, 0xab,
+ 0x9e, 0x2b, 0xcd, 0xed, 0xcc, 0xb3, 0xca, 0xdb, 0x90, 0x37, 0x9c,
+ 0xef, 0x9f, 0xff, 0xed, 0x12, 0xc2, 0x12, 0xe1, 0x92, 0xb6, 0xa5,
+ 0x86, 0x4b, 0x57, 0x2d, 0x1d, 0x58, 0xe6, 0xbd, 0xac, 0x6a, 0x39,
+ 0xb2, 0x3c, 0x71, 0x79, 0xdb, 0x0a, 0xe3, 0x15, 0x05, 0x2b, 0x86,
+ 0x56, 0x06, 0xac, 0x3c, 0xb8, 0x8a, 0xb6, 0x2a, 0x6d, 0xd5, 0x4f,
+ 0xab, 0xed, 0x57, 0x97, 0xae, 0x7e, 0xbd, 0x26, 0x7a, 0x4d, 0x6b,
+ 0x81, 0x5e, 0xc1, 0xca, 0x82, 0xc1, 0xb5, 0x01, 0x6b, 0xeb, 0x0b,
+ 0x55, 0x0a, 0xe5, 0x85, 0x7d, 0xeb, 0xdc, 0xd7, 0xed, 0x5d, 0x4f,
+ 0x58, 0x2f, 0x59, 0xdf, 0xb5, 0x61, 0xfa, 0x86, 0x9d, 0x1b, 0x3e,
+ 0x15, 0x89, 0x8a, 0xae, 0x14, 0xdb, 0x17, 0x97, 0x15, 0x7f, 0xd8,
+ 0x28, 0xdc, 0x78, 0xe5, 0x1b, 0x87, 0x6f, 0xca, 0xbf, 0x99, 0xdc,
+ 0x94, 0xb4, 0xa9, 0xab, 0xc4, 0xb9, 0x64, 0xcf, 0x66, 0xd2, 0x66,
+ 0xe9, 0xe6, 0xde, 0x2d, 0x9e, 0x5b, 0x0e, 0x96, 0xaa, 0x97, 0xe6,
+ 0x97, 0x0e, 0x6e, 0x0d, 0xd9, 0xda, 0xb4, 0x0d, 0xdf, 0x56, 0xb4,
+ 0xed, 0xf5, 0xf6, 0x45, 0xdb, 0x2f, 0x97, 0xcd, 0x28, 0xdb, 0xbb,
+ 0x83, 0xb6, 0x43, 0xb9, 0xa3, 0xbf, 0x3c, 0xb8, 0xbc, 0x65, 0xa7,
+ 0xc9, 0xce, 0xcd, 0x3b, 0x3f, 0x54, 0xa4, 0x54, 0xf4, 0x54, 0xfa,
+ 0x54, 0x36, 0xee, 0xd2, 0xdd, 0xb5, 0x61, 0xd7, 0xf8, 0x6e, 0xd1,
+ 0xee, 0x1b, 0x7b, 0xbc, 0xf6, 0x34, 0xec, 0xd5, 0xdb, 0x5b, 0xbc,
+ 0xf7, 0xfd, 0x3e, 0xc9, 0xbe, 0xdb, 0x55, 0x01, 0x55, 0x4d, 0xd5,
+ 0x66, 0xd5, 0x65, 0xfb, 0x49, 0xfb, 0xb3, 0xf7, 0x3f, 0xae, 0x89,
+ 0xaa, 0xe9, 0xf8, 0x96, 0xfb, 0x6d, 0x5d, 0xad, 0x4e, 0x6d, 0x71,
+ 0xed, 0xc7, 0x03, 0xd2, 0x03, 0xfd, 0x07, 0x23, 0x0e, 0xb6, 0xd7,
+ 0xb9, 0xd4, 0xd5, 0x1d, 0xd2, 0x3d, 0x54, 0x52, 0x8f, 0xd6, 0x2b,
+ 0xeb, 0x47, 0x0e, 0xc7, 0x1f, 0xbe, 0xfe, 0x9d, 0xef, 0x77, 0x2d,
+ 0x0d, 0x36, 0x0d, 0x55, 0x8d, 0x9c, 0xc6, 0xe2, 0x23, 0x70, 0x44,
+ 0x79, 0xe4, 0xe9, 0xf7, 0x09, 0xdf, 0xf7, 0x1e, 0x0d, 0x3a, 0xda,
+ 0x76, 0x8c, 0x7b, 0xac, 0xe1, 0x07, 0xd3, 0x1f, 0x76, 0x1d, 0x67,
+ 0x1d, 0x2f, 0x6a, 0x42, 0x9a, 0xf2, 0x9a, 0x46, 0x9b, 0x53, 0x9a,
+ 0xfb, 0x5b, 0x62, 0x5b, 0xba, 0x4f, 0xcc, 0x3e, 0xd1, 0xd6, 0xea,
+ 0xde, 0x7a, 0xfc, 0x47, 0xdb, 0x1f, 0x0f, 0x9c, 0x34, 0x3c, 0x59,
+ 0x79, 0x4a, 0xf3, 0x54, 0xc9, 0x69, 0xda, 0xe9, 0x82, 0xd3, 0x93,
+ 0x67, 0xf2, 0xcf, 0x8c, 0x9d, 0x95, 0x9d, 0x7d, 0x7e, 0x2e, 0xf9,
+ 0xdc, 0x60, 0xdb, 0xa2, 0xb6, 0x7b, 0xe7, 0x63, 0xce, 0xdf, 0x6a,
+ 0x0f, 0x6f, 0xef, 0xba, 0x10, 0x74, 0xe1, 0xd2, 0x45, 0xff, 0x8b,
+ 0xe7, 0x3b, 0xbc, 0x3b, 0xce, 0x5c, 0xf2, 0xb8, 0x74, 0xf2, 0xb2,
+ 0xdb, 0xe5, 0x13, 0x57, 0xb8, 0x57, 0x9a, 0xaf, 0x3a, 0x5f, 0x6d,
+ 0xea, 0x74, 0xea, 0x3c, 0xfe, 0x93, 0xd3, 0x4f, 0xc7, 0xbb, 0x9c,
+ 0xbb, 0x9a, 0xae, 0xb9, 0x5c, 0x6b, 0xb9, 0xee, 0x7a, 0xbd, 0xb5,
+ 0x7b, 0x66, 0xf7, 0xe9, 0x1b, 0x9e, 0x37, 0xce, 0xdd, 0xf4, 0xbd,
+ 0x79, 0xf1, 0x16, 0xff, 0xd6, 0xd5, 0x9e, 0x39, 0x3d, 0xdd, 0xbd,
+ 0xf3, 0x7a, 0x6f, 0xf7, 0xc5, 0xf7, 0xf5, 0xdf, 0x16, 0xdd, 0x7e,
+ 0x72, 0x27, 0xfd, 0xce, 0xcb, 0xbb, 0xd9, 0x77, 0x27, 0xee, 0xad,
+ 0xbc, 0x4f, 0xbc, 0x5f, 0xf4, 0x40, 0xed, 0x41, 0xd9, 0x43, 0xdd,
+ 0x87, 0xd5, 0x3f, 0x5b, 0xfe, 0xdc, 0xd8, 0xef, 0xdc, 0x7f, 0x6a,
+ 0xc0, 0x77, 0xa0, 0xf3, 0xd1, 0xdc, 0x47, 0xf7, 0x06, 0x85, 0x83,
+ 0xcf, 0xfe, 0x91, 0xf5, 0x8f, 0x0f, 0x43, 0x05, 0x8f, 0x99, 0x8f,
+ 0xcb, 0x86, 0x0d, 0x86, 0xeb, 0x9e, 0x38, 0x3e, 0x39, 0x39, 0xe2,
+ 0x3f, 0x72, 0xfd, 0xe9, 0xfc, 0xa7, 0x43, 0xcf, 0x64, 0xcf, 0x26,
+ 0x9e, 0x17, 0xfe, 0xa2, 0xfe, 0xcb, 0xae, 0x17, 0x16, 0x2f, 0x7e,
+ 0xf8, 0xd5, 0xeb, 0xd7, 0xce, 0xd1, 0x98, 0xd1, 0xa1, 0x97, 0xf2,
+ 0x97, 0x93, 0xbf, 0x6d, 0x7c, 0xa5, 0xfd, 0xea, 0xc0, 0xeb, 0x19,
+ 0xaf, 0xdb, 0xc6, 0xc2, 0xc6, 0x1e, 0xbe, 0xc9, 0x78, 0x33, 0x31,
+ 0x5e, 0xf4, 0x56, 0xfb, 0xed, 0xc1, 0x77, 0xdc, 0x77, 0x1d, 0xef,
+ 0xa3, 0xdf, 0x0f, 0x4f, 0xe4, 0x7c, 0x20, 0x7f, 0x28, 0xff, 0x68,
+ 0xf9, 0xb1, 0xf5, 0x53, 0xd0, 0xa7, 0xfb, 0x93, 0x19, 0x93, 0x93,
+ 0xff, 0x04, 0x03, 0x98, 0xf3, 0xfc, 0x63, 0x33, 0x2d, 0xdb, 0x00,
+ 0x00, 0x00, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x25,
+ 0x00, 0x00, 0x80, 0x83, 0x00, 0x00, 0xf9, 0xff, 0x00, 0x00, 0x80,
+ 0xe9, 0x00, 0x00, 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00,
+ 0x3a, 0x98, 0x00, 0x00, 0x17, 0x6f, 0x92, 0x5f, 0xc5, 0x46, 0x00,
+ 0x00, 0x25, 0xa0, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xec, 0x9d,
+ 0x79, 0x94, 0x25, 0x55, 0x9d, 0xe7, 0xbf, 0xbf, 0x1b, 0xf1, 0xf6,
+ 0xf7, 0x72, 0xad, 0x5c, 0xaa, 0xa8, 0x3d, 0x6b, 0x2f, 0x76, 0x41,
+ 0x60, 0x4a, 0xb4, 0xb1, 0x65, 0x5c, 0xda, 0xb6, 0x15, 0x6c, 0x04,
+ 0xec, 0xd1, 0x43, 0xab, 0xad, 0x07, 0x41, 0x1a, 0xa4, 0x6d, 0x9d,
+ 0x46, 0xa4, 0x68, 0xa8, 0xee, 0x39, 0x72, 0xa6, 0xad, 0xee, 0x71,
+ 0x10, 0x97, 0x71, 0x03, 0xb4, 0x61, 0x46, 0x4b, 0xc7, 0x6d, 0xc0,
+ 0x06, 0x51, 0xb1, 0x9a, 0x62, 0x69, 0x4a, 0xaa, 0x84, 0xda, 0xf7,
+ 0x25, 0x2b, 0xf7, 0xcc, 0x97, 0x6f, 0x8d, 0xb8, 0x77, 0xfe, 0x78,
+ 0x2f, 0x5f, 0x46, 0xc6, 0x8b, 0xe5, 0xde, 0xb7, 0x64, 0x15, 0x95,
+ 0xf1, 0xcb, 0x13, 0xe7, 0x45, 0xdc, 0xb8, 0xb1, 0x64, 0x44, 0xdc,
+ 0x4f, 0x7c, 0x7f, 0xbf, 0x7b, 0xe3, 0x5e, 0x12, 0x42, 0x20, 0xb0,
+ 0xc0, 0x02, 0x0b, 0xec, 0x6c, 0x30, 0xbd, 0x32, 0xf7, 0x4a, 0x28,
+ 0xb8, 0x1a, 0x73, 0xdb, 0xe8, 0x2c, 0xfb, 0x7f, 0x82, 0x37, 0xf5,
+ 0x9c, 0x06, 0x5a, 0x60, 0x73, 0x11, 0x4a, 0xf4, 0x3a, 0xfa, 0xbf,
+ 0x44, 0x8d, 0xff, 0x5b, 0x3d, 0x60, 0x0b, 0xa0, 0x18, 0x00, 0x2d,
+ 0xb0, 0x26, 0x00, 0x85, 0x9a, 0xb0, 0xcf, 0x66, 0xc0, 0x8d, 0x6c,
+ 0x30, 0x20, 0x17, 0x40, 0xf8, 0x1d, 0x4b, 0x34, 0x00, 0x68, 0x6e,
+ 0xe7, 0xa0, 0x02, 0x32, 0xd5, 0xf3, 0x0c, 0xc0, 0x18, 0x00, 0x6d,
+ 0x4e, 0x82, 0xaa, 0x11, 0x20, 0xa3, 0x1a, 0xd3, 0x65, 0x0b, 0xf9,
+ 0xeb, 0xd1, 0x05, 0x15, 0x75, 0xae, 0xf7, 0xcb, 0x27, 0x6a, 0x54,
+ 0x81, 0xd4, 0xa0, 0xe3, 0x07, 0x16, 0x00, 0xed, 0x8c, 0x51, 0x54,
+ 0xb2, 0x70, 0xaa, 0x15, 0x54, 0x8d, 0x06, 0x2a, 0x35, 0xf1, 0xfa,
+ 0x34, 0xa3, 0x40, 0x37, 0x1a, 0x56, 0x32, 0xfb, 0x15, 0x8a, 0x69,
+ 0xd4, 0x60, 0x70, 0x05, 0xe0, 0x0b, 0x80, 0x36, 0x6b, 0xa0, 0x22,
+ 0xc5, 0xe5, 0x46, 0xe4, 0x21, 0x0f, 0x05, 0x56, 0x0f, 0xe4, 0xfc,
+ 0xd6, 0x89, 0x3a, 0xae, 0x6d, 0xb3, 0x63, 0x5c, 0x42, 0x61, 0x3b,
+ 0xe1, 0xf2, 0xff, 0xd4, 0xbb, 0x2c, 0x9b, 0x26, 0x0b, 0x3e, 0x31,
+ 0x0b, 0xd7, 0x36, 0x00, 0xda, 0xeb, 0x14, 0x5e, 0x24, 0xe1, 0x86,
+ 0x91, 0x02, 0x50, 0x6a, 0x9d, 0xf7, 0x5a, 0xb6, 0x9e, 0x1f, 0x29,
+ 0x9c, 0x5b, 0xbd, 0x10, 0x6e, 0x94, 0x02, 0xa3, 0x1a, 0x0b, 0x9c,
+ 0x4a, 0xec, 0xac, 0x56, 0xa8, 0xd8, 0xd3, 0x6b, 0x81, 0x91, 0xdf,
+ 0xb1, 0xb9, 0x87, 0xdb, 0xe9, 0xb4, 0x1f, 0xbf, 0x3c, 0xf5, 0x54,
+ 0x78, 0x38, 0xc1, 0xf0, 0xac, 0x01, 0xdf, 0xd9, 0x08, 0x34, 0x55,
+ 0xa5, 0x41, 0x92, 0xb0, 0x80, 0x4b, 0x3e, 0xf2, 0x59, 0x2f, 0xb3,
+ 0x9d, 0xca, 0xbe, 0x6b, 0x85, 0x62, 0xbd, 0x8a, 0xd2, 0x0d, 0xb0,
+ 0xb3, 0x61, 0xa2, 0xce, 0x3c, 0x2a, 0x8a, 0xaa, 0x96, 0x75, 0x7e,
+ 0x79, 0x34, 0x8f, 0x3c, 0x2a, 0x40, 0x13, 0x8a, 0xe7, 0xe5, 0xf4,
+ 0x42, 0x70, 0x4b, 0xf3, 0x52, 0xa8, 0x01, 0xd0, 0xce, 0x40, 0x17,
+ 0xb1, 0x1e, 0x65, 0x45, 0x35, 0x02, 0x8d, 0x1a, 0xb8, 0x4f, 0x55,
+ 0x78, 0xd6, 0x0b, 0xbe, 0x7a, 0x94, 0xdc, 0x6c, 0x83, 0x4d, 0x36,
+ 0x5d, 0x45, 0x55, 0x89, 0x1a, 0xe0, 0xd3, 0x88, 0x34, 0xfb, 0x7a,
+ 0xd9, 0xe3, 0xab, 0x9c, 0xa7, 0x9b, 0x5b, 0x4d, 0x75, 0x2a, 0xea,
+ 0x00, 0x68, 0x0a, 0x50, 0x12, 0x35, 0xa8, 0x0b, 0xbf, 0x02, 0xed,
+ 0x07, 0x1c, 0xaa, 0x03, 0x54, 0xcc, 0x03, 0x2c, 0x2a, 0x80, 0x53,
+ 0x01, 0x9a, 0xaa, 0x02, 0x54, 0x51, 0x70, 0xf5, 0xac, 0x6b, 0x86,
+ 0x22, 0x53, 0x8d, 0x4b, 0xc9, 0xaa, 0x23, 0x15, 0xd7, 0x4f, 0x16,
+ 0x32, 0x42, 0x72, 0x1b, 0x51, 0xc3, 0x7e, 0x54, 0x20, 0x57, 0x8b,
+ 0xbb, 0xeb, 0xe4, 0xa6, 0x8a, 0x1a, 0x42, 0x02, 0x73, 0x1a, 0x68,
+ 0x7e, 0x6a, 0xa1, 0x96, 0xc2, 0x2e, 0x03, 0x18, 0xaa, 0x01, 0x68,
+ 0xaa, 0xeb, 0x64, 0xd2, 0x1a, 0x01, 0xba, 0x7a, 0x21, 0x56, 0x4f,
+ 0xcd, 0xab, 0x4a, 0x9e, 0x46, 0x34, 0x65, 0x10, 0x75, 0x02, 0x4d,
+ 0x46, 0x9d, 0x71, 0x87, 0x02, 0x2c, 0x24, 0xe0, 0x21, 0x0b, 0x23,
+ 0x2e, 0x01, 0x39, 0x21, 0x09, 0x41, 0xaf, 0x63, 0x92, 0xe5, 0x58,
+ 0x4e, 0xe7, 0xac, 0x0a, 0xa9, 0x46, 0xd7, 0xdc, 0x9e, 0x15, 0x40,
+ 0x93, 0xa9, 0x9d, 0x53, 0x71, 0xf3, 0xfc, 0xd2, 0x54, 0xd6, 0xcb,
+ 0x6c, 0xe7, 0xb6, 0xec, 0x96, 0xa7, 0x51, 0xc0, 0x54, 0x01, 0x7d,
+ 0xbd, 0x95, 0x09, 0xcd, 0xaa, 0x48, 0x68, 0x26, 0xd0, 0xbc, 0xd4,
+ 0x46, 0xa3, 0xd5, 0x96, 0x97, 0x6a, 0x72, 0xcb, 0xa3, 0x9a, 0xae,
+ 0x9a, 0xc7, 0x29, 0xff, 0xd4, 0xcb, 0x5d, 0xe5, 0x3c, 0x49, 0xe1,
+ 0x85, 0x41, 0xa7, 0x53, 0xc1, 0xe9, 0xa7, 0x11, 0x60, 0x2a, 0xe0,
+ 0x52, 0x2d, 0xf8, 0xa4, 0xb8, 0xae, 0x96, 0x3c, 0xaa, 0xfb, 0xf3,
+ 0xdb, 0x4e, 0x15, 0x7e, 0x32, 0xea, 0x4e, 0x45, 0xd9, 0x9d, 0x89,
+ 0x71, 0x35, 0x51, 0x47, 0x5a, 0x2d, 0x6e, 0x96, 0x1f, 0xe4, 0xb8,
+ 0xc7, 0xbe, 0x65, 0x41, 0x63, 0xcf, 0xeb, 0x97, 0x66, 0xdf, 0x07,
+ 0x57, 0x84, 0x98, 0xa8, 0x21, 0xbf, 0xd7, 0xf9, 0x93, 0xc3, 0xb2,
+ 0xd7, 0x3d, 0x98, 0xd5, 0xda, 0x54, 0xfd, 0x34, 0x43, 0x4c, 0x36,
+ 0xae, 0x54, 0x0b, 0xb4, 0x98, 0x0b, 0x64, 0xbc, 0x00, 0x44, 0x3e,
+ 0xdb, 0xc8, 0x82, 0x4c, 0x45, 0xf1, 0x35, 0x5a, 0xdd, 0xb9, 0xb9,
+ 0xd7, 0x24, 0x79, 0xcd, 0x9d, 0xe2, 0x96, 0xcd, 0x6a, 0xbc, 0xab,
+ 0xaa, 0xd6, 0x54, 0x9a, 0x66, 0xa8, 0xa8, 0xad, 0x46, 0x2a, 0x30,
+ 0x19, 0xd5, 0xa5, 0x02, 0x34, 0xbf, 0x6d, 0x55, 0xd6, 0x73, 0x17,
+ 0x40, 0x3a, 0xad, 0x93, 0x85, 0x20, 0x24, 0x5c, 0xd5, 0x59, 0x6b,
+ 0x2a, 0xa2, 0x9f, 0x06, 0x80, 0xc9, 0x2a, 0x30, 0x2f, 0xf5, 0x62,
+ 0x2f, 0xe8, 0x4e, 0xf0, 0x62, 0x12, 0x70, 0x52, 0x99, 0x9c, 0xf6,
+ 0x55, 0x0b, 0x34, 0x6b, 0x49, 0x53, 0x75, 0x9f, 0xa1, 0xb0, 0x5e,
+ 0xc6, 0x05, 0x55, 0x6d, 0xd2, 0x51, 0x0f, 0xd0, 0xfc, 0xdc, 0x94,
+ 0x7a, 0x63, 0x64, 0x8d, 0x70, 0x25, 0x9d, 0x00, 0x81, 0x1a, 0x81,
+ 0x04, 0x05, 0x28, 0x35, 0x62, 0x72, 0x3b, 0x86, 0x17, 0xd8, 0x84,
+ 0x24, 0x70, 0xdd, 0xd2, 0xc8, 0xe1, 0xda, 0x35, 0x25, 0xf6, 0xa6,
+ 0x9f, 0x81, 0x10, 0xb3, 0x17, 0x42, 0xbb, 0xda, 0x60, 0x92, 0x00,
+ 0x62, 0x0a, 0xdb, 0xb0, 0x06, 0x82, 0x4f, 0x55, 0x11, 0xaa, 0xa8,
+ 0x36, 0x15, 0xc0, 0xc1, 0x27, 0x7d, 0x36, 0x9a, 0x77, 0x34, 0x22,
+ 0x86, 0xa6, 0xda, 0x18, 0xb6, 0xd6, 0x66, 0x16, 0xaa, 0x2a, 0xab,
+ 0x16, 0x80, 0x41, 0x41, 0x3d, 0xc9, 0x4c, 0xbc, 0x46, 0xa8, 0xf1,
+ 0x06, 0xec, 0x4b, 0xe6, 0x9c, 0xfd, 0x62, 0x6c, 0x4e, 0x80, 0x13,
+ 0x67, 0x0a, 0xd0, 0x64, 0xe2, 0x62, 0xb2, 0xae, 0x17, 0x73, 0x98,
+ 0x67, 0x92, 0x10, 0x62, 0x1e, 0xdb, 0x31, 0x8f, 0xed, 0xdd, 0xf2,
+ 0x63, 0x16, 0xa0, 0x67, 0x3d, 0x2e, 0x6a, 0x80, 0x9c, 0x9f, 0xcb,
+ 0x5a, 0x6b, 0xe5, 0x01, 0x29, 0x42, 0xac, 0xd9, 0xdf, 0x72, 0xaa,
+ 0x36, 0xc1, 0x90, 0x49, 0x53, 0x8d, 0x79, 0xf9, 0xc5, 0xc2, 0xb8,
+ 0xa4, 0x22, 0xe3, 0x0a, 0xca, 0x8c, 0x37, 0x00, 0x52, 0xdc, 0x76,
+ 0x7e, 0xc2, 0x63, 0xde, 0x2d, 0xcd, 0xbe, 0xcc, 0x6a, 0x50, 0x85,
+ 0x7e, 0xf7, 0xb5, 0x2e, 0xb7, 0x54, 0x6f, 0x22, 0xc4, 0x64, 0x00,
+ 0xa6, 0xaa, 0x9a, 0x98, 0x07, 0x98, 0xfc, 0xd2, 0x9c, 0xd2, 0xfd,
+ 0x00, 0x47, 0x35, 0xa6, 0x91, 0xe2, 0xff, 0xd9, 0x58, 0xd7, 0x94,
+ 0x2c, 0xf7, 0xa0, 0x1a, 0x69, 0x24, 0xa1, 0xff, 0x08, 0x64, 0x79,
+ 0x73, 0x7a, 0x37, 0xb7, 0x24, 0x4b, 0xa8, 0x9c, 0x2c, 0x8f, 0x20,
+ 0xd9, 0x1e, 0x59, 0x72, 0xd8, 0xb2, 0x1a, 0x38, 0x54, 0x4e, 0x17,
+ 0xe5, 0x73, 0x20, 0x97, 0x87, 0x7a, 0xba, 0x78, 0x88, 0xca, 0x16,
+ 0x53, 0xc7, 0x99, 0x9a, 0xf3, 0xd6, 0x5f, 0xc2, 0x56, 0xc4, 0x84,
+ 0x65, 0x7f, 0xb2, 0xc1, 0x7c, 0xa1, 0x00, 0x37, 0x37, 0xd0, 0x71,
+ 0x1b, 0xe4, 0xa0, 0x00, 0x1c, 0xbf, 0x3c, 0xdc, 0x07, 0x56, 0x7e,
+ 0x70, 0xe3, 0x12, 0xfb, 0xf2, 0x02, 0xa1, 0x4c, 0x8c, 0x4e, 0x06,
+ 0x6e, 0x62, 0x36, 0x80, 0xa6, 0xda, 0x8c, 0x82, 0x24, 0xd4, 0x8e,
+ 0x1b, 0x68, 0x64, 0x97, 0x99, 0x47, 0x9a, 0xdb, 0x7a, 0x37, 0x55,
+ 0xe7, 0x04, 0x38, 0xbb, 0x62, 0xf3, 0x53, 0x8f, 0xf0, 0xf9, 0x5f,
+ 0xdd, 0x01, 0x4f, 0x16, 0x38, 0x4d, 0xef, 0xa9, 0x34, 0xa7, 0x01,
+ 0x60, 0x65, 0x44, 0xd0, 0x0c, 0xec, 0x94, 0x96, 0x8a, 0xd0, 0x60,
+ 0x82, 0x81, 0x43, 0x33, 0x0b, 0xd0, 0x8a, 0x26, 0x34, 0xd3, 0x84,
+ 0x56, 0x28, 0x42, 0x2b, 0x1a, 0x60, 0x86, 0x09, 0x8d, 0x73, 0x68,
+ 0x99, 0x9c, 0xd0, 0xf3, 0x05, 0x68, 0x86, 0x01, 0xdd, 0xe0, 0xd0,
+ 0x0a, 0x05, 0x68, 0xb9, 0x02, 0xb4, 0xa2, 0x01, 0xcd, 0x30, 0xc1,
+ 0x4c, 0x0e, 0x56, 0x28, 0x40, 0x1f, 0x1a, 0x15, 0xe1, 0x4c, 0x0e,
+ 0xa1, 0x6c, 0x0e, 0x7a, 0xae, 0x80, 0x90, 0x61, 0x42, 0x2b, 0x16,
+ 0x11, 0x32, 0x38, 0x34, 0xce, 0x41, 0x99, 0x1c, 0x34, 0x02, 0xc0,
+ 0x05, 0xa8, 0x50, 0x84, 0x66, 0x7f, 0x50, 0x0c, 0x43, 0x30, 0x2e,
+ 0x66, 0x84, 0x0e, 0x00, 0x00, 0x21, 0x9d, 0x4c, 0xb2, 0x00, 0x4b,
+ 0x08, 0x40, 0xd7, 0xc1, 0x43, 0x1a, 0xb8, 0x00, 0x28, 0xa4, 0x83,
+ 0x47, 0xc2, 0x30, 0x09, 0x40, 0x24, 0x8c, 0x3c, 0x63, 0x10, 0xb1,
+ 0x08, 0xf2, 0x21, 0x1d, 0x66, 0x32, 0x8e, 0x42, 0x5b, 0x0a, 0xc5,
+ 0x64, 0x82, 0x8a, 0x1a, 0x81, 0x6b, 0x1a, 0xb8, 0xae, 0xc3, 0x8c,
+ 0x84, 0x60, 0xc6, 0x22, 0x30, 0x35, 0x0d, 0xa6, 0xae, 0xc1, 0x08,
+ 0x87, 0x60, 0xc6, 0xa2, 0x64, 0x84, 0x42, 0x30, 0x35, 0x02, 0x0f,
+ 0xe9, 0x30, 0x23, 0x61, 0x98, 0x1a, 0x2b, 0xe5, 0x09, 0x87, 0x61,
+ 0x42, 0x07, 0x07, 0x83, 0x09, 0x1d, 0x26, 0x58, 0xb9, 0xb0, 0x89,
+ 0x19, 0xa8, 0x2b, 0x15, 0x47, 0xb3, 0x0c, 0x4b, 0x6b, 0x0e, 0x2b,
+ 0x36, 0x85, 0x2f, 0xe4, 0xb8, 0x43, 0x21, 0x97, 0x55, 0x45, 0x70,
+ 0x80, 0x90, 0x90, 0x54, 0x5c, 0x6e, 0x80, 0xe2, 0x0e, 0xeb, 0xb9,
+ 0x07, 0xf0, 0x64, 0xf7, 0xc9, 0x2c, 0xff, 0x23, 0xd9, 0x62, 0xa3,
+ 0xf6, 0x89, 0xe0, 0x5f, 0x1b, 0x2d, 0xad, 0xda, 0xf4, 0x06, 0x83,
+ 0xcc, 0xad, 0x86, 0xce, 0x4b, 0xd5, 0x30, 0x05, 0x30, 0xd9, 0xe7,
+ 0xfd, 0x96, 0xc9, 0x63, 0x9f, 0x4c, 0x42, 0xb9, 0x31, 0x45, 0xc5,
+ 0xe7, 0xfe, 0xbf, 0x52, 0x05, 0x39, 0xd3, 0xbf, 0xd5, 0x67, 0x59,
+ 0xd2, 0x24, 0x26, 0x34, 0x70, 0x30, 0x70, 0x30, 0x18, 0xd0, 0x72,
+ 0x39, 0x84, 0x0a, 0x05, 0xe8, 0xd9, 0x02, 0x42, 0x85, 0x02, 0x42,
+ 0x27, 0x07, 0x45, 0x6c, 0x60, 0x14, 0xc9, 0xf1, 0x34, 0x62, 0x63,
+ 0x69, 0x11, 0xc9, 0xe5, 0x11, 0x1e, 0x4f, 0x23, 0x9c, 0xce, 0x22,
+ 0x92, 0xc9, 0x22, 0x7c, 0xfc, 0x94, 0x88, 0x0f, 0x8e, 0x21, 0x91,
+ 0xc9, 0x22, 0x9a, 0xc9, 0x41, 0x2f, 0x14, 0xa1, 0x1b, 0x86, 0xd0,
+ 0x72, 0x05, 0x68, 0x65, 0x80, 0x69, 0x06, 0x87, 0x66, 0x18, 0x20,
+ 0x93, 0x83, 0x38, 0xaf, 0x86, 0xcd, 0xec, 0x58, 0x73, 0x6b, 0xf1,
+ 0x89, 0x20, 0x34, 0x06, 0xa1, 0x6b, 0x65, 0xe0, 0x95, 0x01, 0x16,
+ 0x0b, 0xc3, 0xd4, 0x75, 0x98, 0x21, 0x9d, 0xcc, 0x58, 0x14, 0x46,
+ 0x3c, 0x86, 0x7c, 0x5b, 0x12, 0x93, 0xf3, 0xe7, 0x51, 0xb6, 0xb5,
+ 0x05, 0xb9, 0x78, 0x04, 0x85, 0xd6, 0x24, 0x0a, 0xb1, 0x18, 0x0a,
+ 0xa9, 0x38, 0xf2, 0x6d, 0x29, 0xca, 0xb5, 0x26, 0x31, 0x79, 0x4e,
+ 0x37, 0x26, 0x13, 0x71, 0xca, 0x47, 0x42, 0x30, 0x23, 0x11, 0x14,
+ 0xa3, 0x61, 0x14, 0xb5, 0x30, 0x8c, 0xd2, 0xab, 0xa3, 0xfc, 0x0a,
+ 0x61, 0xe0, 0x15, 0xb4, 0xcd, 0x2c, 0xf2, 0xc2, 0x52, 0xf4, 0xed,
+ 0xf0, 0x53, 0x71, 0x1b, 0xfd, 0x54, 0x96, 0x53, 0x7e, 0xd3, 0x05,
+ 0x44, 0x32, 0x40, 0xe3, 0x35, 0x6c, 0x23, 0x3c, 0x7e, 0x9d, 0x20,
+ 0x4d, 0x0e, 0x80, 0x23, 0xc8, 0x7f, 0xb6, 0x55, 0x13, 0xd0, 0x64,
+ 0xaa, 0xfd, 0xdd, 0x9a, 0x4f, 0xc8, 0x42, 0x8c, 0xf9, 0xa4, 0xb9,
+ 0x4d, 0x24, 0xb1, 0xad, 0x0c, 0xf8, 0x54, 0x80, 0xc6, 0x2c, 0x6a,
+ 0x8a, 0xcd, 0x98, 0xd3, 0x20, 0xa0, 0xcd, 0xd0, 0x5a, 0x84, 0x02,
+ 0x74, 0xe4, 0x11, 0xce, 0xe4, 0x10, 0xce, 0xe4, 0x10, 0xca, 0x64,
+ 0x11, 0x19, 0x4d, 0x8b, 0x68, 0x09, 0x4a, 0x88, 0xf4, 0x0f, 0x89,
+ 0xc4, 0xde, 0x23, 0x68, 0x1f, 0x1c, 0x46, 0xcb, 0x58, 0x5a, 0x44,
+ 0xc6, 0xd3, 0x88, 0x8e, 0xa6, 0x11, 0xc9, 0x64, 0x11, 0x99, 0xcc,
+ 0x22, 0x94, 0xcb, 0x8b, 0xd0, 0x64, 0x16, 0xa1, 0x7c, 0x11, 0x7a,
+ 0x36, 0x07, 0x1d, 0x67, 0xdf, 0x18, 0x00, 0x8d, 0xc7, 0xa5, 0x00,
+ 0x19, 0x26, 0xc8, 0x30, 0xdd, 0x80, 0x2d, 0x94, 0x00, 0x1b, 0xd2,
+ 0x61, 0x46, 0x23, 0x30, 0xe2, 0x51, 0x14, 0x63, 0x51, 0x14, 0xe3,
+ 0x11, 0x2a, 0x26, 0xe2, 0x28, 0x24, 0x63, 0xc8, 0xb7, 0xb5, 0x20,
+ 0x9f, 0x8a, 0x23, 0xd7, 0xd9, 0x46, 0x99, 0x85, 0x3d, 0x18, 0x59,
+ 0xbe, 0x90, 0xc6, 0x5a, 0x92, 0xc8, 0xb5, 0x24, 0x91, 0x6b, 0x4d,
+ 0x52, 0x2e, 0x19, 0x47, 0x3e, 0x11, 0x43, 0x21, 0x16, 0x41, 0x21,
+ 0x14, 0x45, 0x11, 0x11, 0x14, 0x2a, 0xf0, 0x43, 0x19, 0x39, 0x46,
+ 0xd9, 0x75, 0xe6, 0x16, 0x87, 0x58, 0xf8, 0xaa, 0x2d, 0x2f, 0xc0,
+ 0x08, 0x0f, 0x28, 0xb9, 0x81, 0xc8, 0x94, 0x48, 0xf3, 0x9a, 0xdc,
+ 0x8e, 0x61, 0xdd, 0x0f, 0xb3, 0xe4, 0x23, 0x17, 0x77, 0xdd, 0xab,
+ 0xe6, 0xdb, 0xd5, 0x15, 0xa5, 0xca, 0xa8, 0x4f, 0xde, 0x83, 0xa4,
+ 0xf8, 0xa9, 0x32, 0x7b, 0xf3, 0x09, 0x37, 0x77, 0x4d, 0x15, 0x54,
+ 0xf6, 0x49, 0xab, 0x63, 0x5b, 0x52, 0x4c, 0x9b, 0x5e, 0x37, 0x05,
+ 0x25, 0xcd, 0x72, 0x06, 0x5a, 0x19, 0x56, 0x26, 0x74, 0x18, 0xd0,
+ 0x50, 0x40, 0x28, 0x9d, 0x41, 0x38, 0x9d, 0x43, 0xe4, 0xe4, 0x80,
+ 0x48, 0xee, 0x3b, 0x82, 0xce, 0xfe, 0x21, 0x91, 0x1c, 0x1c, 0x45,
+ 0x62, 0x70, 0x04, 0xc9, 0x5d, 0x87, 0x44, 0xfb, 0x89, 0x53, 0x68,
+ 0x9b, 0xc8, 0x88, 0x48, 0x7a, 0x12, 0xe1, 0xc9, 0x2c, 0x22, 0xb9,
+ 0x02, 0x34, 0x21, 0x02, 0x30, 0x9d, 0xed, 0x16, 0xd2, 0x61, 0xc6,
+ 0xa2, 0x28, 0xb6, 0x24, 0x90, 0x4f, 0xc4, 0xa9, 0xd0, 0xd1, 0x82,
+ 0xc9, 0x95, 0x4b, 0x30, 0x34, 0xbf, 0x9b, 0x26, 0x7a, 0xda, 0x30,
+ 0xd9, 0xd5, 0x89, 0xc9, 0x45, 0xbd, 0x34, 0xbc, 0xfc, 0x1c, 0x1a,
+ 0x4b, 0xc6, 0x91, 0x4f, 0xc6, 0x91, 0x0b, 0x45, 0x51, 0x84, 0x0e,
+ 0x03, 0x7a, 0x19, 0x73, 0x1c, 0x02, 0x66, 0x19, 0x01, 0x46, 0xa5,
+ 0xe8, 0xbb, 0xc1, 0x4c, 0x46, 0x71, 0xc9, 0xac, 0xe3, 0x15, 0x67,
+ 0x7b, 0x26, 0xdc, 0xb8, 0xe4, 0x64, 0x4a, 0x9c, 0x8f, 0x9b, 0xf2,
+ 0x74, 0x8b, 0xb7, 0x79, 0xbe, 0x85, 0x64, 0x80, 0x26, 0xf3, 0x01,
+ 0x37, 0xb9, 0x00, 0xcc, 0x0e, 0x07, 0xcd, 0x07, 0x52, 0x9a, 0x0f,
+ 0xc0, 0x54, 0xf2, 0xaa, 0xc1, 0x6e, 0x4a, 0x65, 0x31, 0x10, 0x74,
+ 0x00, 0x7a, 0x25, 0x2c, 0xcd, 0x60, 0x40, 0x47, 0x01, 0xa1, 0x53,
+ 0x83, 0x48, 0xf5, 0x0f, 0x89, 0xd4, 0xa9, 0x51, 0x24, 0x0f, 0x1f,
+ 0x13, 0xad, 0xaf, 0xec, 0x41, 0xef, 0xf1, 0x01, 0xd1, 0xda, 0x3f,
+ 0x8c, 0xc4, 0xd0, 0x28, 0x12, 0x63, 0x13, 0x22, 0x3a, 0x96, 0x46,
+ 0x64, 0x7c, 0x02, 0x51, 0x11, 0x28, 0xa8, 0xc0, 0x14, 0x2d, 0x16,
+ 0x45, 0xb1, 0xb5, 0xac, 0xe8, 0xda, 0x5b, 0x91, 0xed, 0xe9, 0x40,
+ 0xba, 0xab, 0x83, 0x26, 0x57, 0x2f, 0x45, 0xff, 0x9a, 0xe5, 0x34,
+ 0xd4, 0xdd, 0x8e, 0x74, 0x57, 0x3b, 0xa5, 0x17, 0x74, 0x63, 0x3c,
+ 0x92, 0x44, 0x0e, 0x3a, 0x0c, 0x30, 0x98, 0x65, 0x55, 0x27, 0x60,
+ 0x80, 0xca, 0x08, 0x71, 0x72, 0x7a, 0xeb, 0x81, 0x96, 0xe9, 0x91,
+ 0x5f, 0x65, 0x9d, 0x69, 0x3b, 0x27, 0x53, 0xc2, 0x3d, 0xf5, 0xaa,
+ 0xa4, 0xa9, 0x82, 0x9a, 0x17, 0xd0, 0x54, 0x02, 0xfd, 0x5e, 0x71,
+ 0x2a, 0x3f, 0x20, 0x59, 0x7f, 0x9d, 0xe6, 0xdd, 0x96, 0xfd, 0x00,
+ 0xe7, 0x9c, 0x46, 0x60, 0x65, 0x68, 0x09, 0x68, 0xe5, 0x38, 0x16,
+ 0x81, 0x50, 0x40, 0xb8, 0x50, 0x72, 0xf3, 0xe2, 0x07, 0x8f, 0x89,
+ 0xb6, 0x3f, 0xec, 0x17, 0xbd, 0x47, 0x4e, 0xa2, 0xf5, 0xd8, 0x29,
+ 0xb4, 0x1e, 0xeb, 0x17, 0xa9, 0x13, 0x03, 0x48, 0x1d, 0x38, 0x26,
+ 0xda, 0x47, 0x26, 0x10, 0x17, 0x3c, 0x80, 0x55, 0x60, 0xa7, 0xc7,
+ 0xa2, 0x61, 0x14, 0x17, 0xf6, 0xd2, 0xd8, 0x92, 0x05, 0x18, 0x9b,
+ 0xdf, 0x85, 0xf1, 0x73, 0xba, 0x69, 0x7c, 0x51, 0x0f, 0xc6, 0x96,
+ 0x2d, 0xa4, 0xc1, 0xf5, 0x7d, 0x34, 0xd0, 0xd9, 0x86, 0xc9, 0x64,
+ 0x12, 0x59, 0xc4, 0x90, 0x07, 0x81, 0x97, 0x95, 0x9d, 0x80, 0x09,
+ 0x82, 0x31, 0x03, 0x74, 0x66, 0x1d, 0xf0, 0xaa, 0xe7, 0xd7, 0x4f,
+ 0xe1, 0x09, 0x97, 0xca, 0x0f, 0x3f, 0xb0, 0x89, 0x5a, 0x81, 0xe6,
+ 0x57, 0x3b, 0xe9, 0xa5, 0x9e, 0x34, 0x0f, 0x70, 0xe9, 0x0e, 0xeb,
+ 0x75, 0x1f, 0x80, 0x79, 0x83, 0x8e, 0x55, 0xdc, 0x44, 0x2a, 0xbb,
+ 0x88, 0x0c, 0x45, 0x84, 0x26, 0xc7, 0x10, 0x3f, 0x78, 0x4c, 0x74,
+ 0x1e, 0x3d, 0x85, 0xd6, 0x43, 0xc7, 0x45, 0xdb, 0xc1, 0xe3, 0xe8,
+ 0x78, 0xf9, 0x35, 0xd1, 0xbb, 0xf7, 0x30, 0xe6, 0x0d, 0x8e, 0x8a,
+ 0xf8, 0xc8, 0x18, 0xe2, 0x41, 0xd1, 0x09, 0xec, 0xf5, 0x66, 0xf1,
+ 0x28, 0x0a, 0xf3, 0xda, 0x91, 0x99, 0xdf, 0x45, 0x63, 0x17, 0xaf,
+ 0xc5, 0x89, 0xbe, 0xc5, 0x34, 0xb4, 0x74, 0x3e, 0x8d, 0x2e, 0xea,
+ 0xc5, 0xc8, 0xe2, 0xf9, 0x34, 0xda, 0xdb, 0x83, 0x31, 0x84, 0x51,
+ 0x80, 0x06, 0xa3, 0x1c, 0xb3, 0x03, 0xcc, 0xb2, 0xba, 0x13, 0x8e,
+ 0x10, 0x73, 0x52, 0x5a, 0xa6, 0x0b, 0xa0, 0x0c, 0x5b, 0x9a, 0xe9,
+ 0x92, 0xd7, 0x94, 0x50, 0x70, 0x6e, 0x8a, 0x0d, 0xf0, 0x6e, 0xb8,
+ 0x2b, 0xdc, 0x80, 0x26, 0x0b, 0x33, 0xe6, 0x01, 0x33, 0x27, 0x88,
+ 0x59, 0x27, 0xdd, 0x65, 0x99, 0xd9, 0xd2, 0xbc, 0xf6, 0x31, 0x7d,
+ 0x1c, 0x02, 0x83, 0x06, 0x42, 0xa8, 0xbc, 0x15, 0x87, 0x66, 0x8c,
+ 0x23, 0x3e, 0x38, 0x82, 0xd4, 0x91, 0x53, 0xa2, 0x75, 0xef, 0x61,
+ 0x74, 0xfe, 0xf6, 0x25, 0xb1, 0x64, 0xf7, 0x61, 0xd1, 0xb5, 0xe7,
+ 0xa0, 0xe8, 0x3c, 0x72, 0x12, 0xed, 0x3c, 0x50, 0x5a, 0x81, 0xcd,
+ 0x11, 0x6b, 0x6f, 0x41, 0x66, 0xcd, 0x32, 0x1a, 0x58, 0xb6, 0x10,
+ 0x23, 0x17, 0xaf, 0xa5, 0xa3, 0x17, 0xae, 0xa5, 0x13, 0x4b, 0xe6,
+ 0xd3, 0x68, 0x6f, 0x27, 0xc6, 0x93, 0x6d, 0x48, 0x23, 0x8c, 0x02,
+ 0x38, 0x80, 0x02, 0xc8, 0xe2, 0xc4, 0x72, 0x17, 0x20, 0xf1, 0x4a,
+ 0x35, 0x86, 0x33, 0xac, 0x0c, 0xc9, 0x34, 0xa7, 0x7d, 0x0b, 0x07,
+ 0xf7, 0xd7, 0x2b, 0xbe, 0x66, 0x85, 0x9a, 0x23, 0xd0, 0x54, 0x61,
+ 0xe6, 0xe4, 0xe6, 0xb9, 0xc1, 0x4b, 0xb7, 0xa5, 0x79, 0x2d, 0x3b,
+ 0x41, 0x6f, 0x5a, 0x6f, 0x4d, 0xc5, 0xba, 0x42, 0xe5, 0x38, 0x57,
+ 0x0e, 0xd1, 0xe1, 0x51, 0x24, 0x5f, 0xdd, 0x27, 0xba, 0xb7, 0xed,
+ 0x14, 0x8b, 0x5e, 0x7e, 0x55, 0xf4, 0x6e, 0xdb, 0x81, 0xc5, 0x27,
+ 0x06, 0x44, 0xcb, 0xd8, 0x04, 0xa2, 0xc1, 0x23, 0x1d, 0x58, 0x60,
+ 0x33, 0x2d, 0x1c, 0x86, 0xd1, 0xdb, 0x89, 0xf4, 0x9a, 0xe5, 0xd4,
+ 0x7f, 0xf9, 0x05, 0x74, 0xe4, 0xdc, 0x15, 0x74, 0xf2, 0xb2, 0x73,
+ 0xe9, 0xe8, 0xfc, 0x2e, 0x8c, 0x85, 0x12, 0xc8, 0x42, 0x47, 0x11,
+ 0x26, 0x84, 0x45, 0xc9, 0xb9, 0x29, 0x30, 0x27, 0x68, 0x19, 0x96,
+ 0x65, 0xb7, 0x5f, 0xfb, 0x76, 0x4e, 0x6e, 0xa9, 0xa9, 0xa0, 0xd6,
+ 0xe0, 0x05, 0x34, 0xa7, 0x56, 0xe8, 0x5e, 0x31, 0x32, 0x37, 0x10,
+ 0xe9, 0x36, 0xa0, 0x39, 0x4d, 0x1a, 0x50, 0xd1, 0x56, 0xce, 0x00,
+ 0x64, 0x60, 0x08, 0x97, 0x73, 0x15, 0x11, 0x1a, 0x1b, 0x42, 0xcb,
+ 0xc1, 0xe3, 0xa2, 0x73, 0xfb, 0x2e, 0xcc, 0xff, 0xb7, 0xad, 0x7c,
+ 0xc5, 0xab, 0x07, 0xd1, 0x7d, 0xe8, 0xb8, 0x68, 0x3b, 0x35, 0x84,
+ 0x54, 0xf0, 0xa8, 0x06, 0x16, 0x58, 0x6d, 0x96, 0x8c, 0xa3, 0x70,
+ 0x4e, 0x0f, 0x8d, 0xad, 0x58, 0x8c, 0xc1, 0xcb, 0xcf, 0xa7, 0x43,
+ 0x57, 0x5e, 0x42, 0x07, 0x57, 0x2c, 0xa4, 0xa1, 0x05, 0xdd, 0x18,
+ 0xa5, 0x24, 0x32, 0x30, 0x21, 0x50, 0x28, 0x03, 0x4e, 0x54, 0x41,
+ 0xc9, 0xb0, 0xcd, 0x3b, 0x2d, 0x1b, 0x2e, 0xeb, 0x9d, 0xe0, 0xe8,
+ 0x04, 0x35, 0xaf, 0xd8, 0x9a, 0x2f, 0xd0, 0x54, 0x5d, 0x4c, 0x2f,
+ 0x50, 0x59, 0xa7, 0x90, 0x6d, 0xbe, 0x3a, 0x1f, 0x41, 0x43, 0x08,
+ 0x84, 0x30, 0x04, 0x4c, 0x84, 0xb2, 0xe3, 0x25, 0xf5, 0xf5, 0xd4,
+ 0xf3, 0x62, 0xc5, 0x6f, 0x5e, 0x10, 0xcb, 0x5e, 0xd8, 0x29, 0x16,
+ 0x9e, 0x18, 0x40, 0x4b, 0xd0, 0xec, 0x21, 0xb0, 0xc0, 0x9a, 0x6b,
+ 0x2d, 0x49, 0xe4, 0x56, 0x2e, 0xa1, 0x81, 0xb7, 0x5d, 0x46, 0xfb,
+ 0xae, 0xb8, 0x88, 0x0e, 0x6d, 0xb8, 0x90, 0x0e, 0xce, 0xeb, 0xc4,
+ 0x38, 0xa2, 0xc8, 0x96, 0x01, 0x47, 0x30, 0x7d, 0xc1, 0x55, 0xf4,
+ 0x59, 0x76, 0x02, 0xa0, 0x5b, 0x25, 0x85, 0x6b, 0x4d, 0xa8, 0x0a,
+ 0xd0, 0xbc, 0x5c, 0x4c, 0x27, 0x05, 0x16, 0xb2, 0xfc, 0x7a, 0xcd,
+ 0x4f, 0x2f, 0x97, 0x54, 0x18, 0x21, 0x04, 0x42, 0x1e, 0xd1, 0x3d,
+ 0xfb, 0x45, 0xef, 0xd3, 0xcf, 0xa1, 0xef, 0xa7, 0xbf, 0xe6, 0x6b,
+ 0x77, 0xec, 0x45, 0xef, 0x81, 0xa3, 0xa2, 0x23, 0x00, 0x58, 0x60,
+ 0x5e, 0xa6, 0x31, 0xc0, 0xe4, 0xcd, 0x3d, 0x06, 0x51, 0xe9, 0x33,
+ 0xad, 0xb9, 0x6a, 0x5d, 0xed, 0x48, 0xaf, 0x5a, 0x4a, 0x83, 0x57,
+ 0xbe, 0x81, 0xf6, 0xff, 0xc9, 0x9b, 0xe9, 0xb5, 0x4b, 0xd6, 0xd1,
+ 0x91, 0x68, 0x07, 0xc6, 0x21, 0x60, 0x22, 0x0f, 0xc0, 0xa8, 0x54,
+ 0x12, 0x58, 0xc1, 0x55, 0xb0, 0xcc, 0x5b, 0x7f, 0xed, 0xf3, 0x76,
+ 0xb5, 0x67, 0x3a, 0xb8, 0xa1, 0x6e, 0x1f, 0xde, 0x57, 0x01, 0x4d,
+ 0x36, 0x66, 0xe6, 0x14, 0xbc, 0xd7, 0x5d, 0x60, 0x65, 0x9f, 0xc2,
+ 0x33, 0x96, 0x19, 0x74, 0x44, 0x40, 0xd0, 0x41, 0xc5, 0x71, 0xa4,
+ 0x5e, 0xd8, 0x21, 0x96, 0xfc, 0xe4, 0x19, 0xb1, 0xee, 0x77, 0x2f,
+ 0x8b, 0xa5, 0xcf, 0x6d, 0x17, 0x8b, 0xb3, 0x79, 0x84, 0x82, 0x62,
+ 0x1a, 0x98, 0xac, 0xad, 0x5c, 0x4c, 0xf8, 0xf2, 0xdd, 0x0c, 0xcc,
+ 0xda, 0x73, 0x3e, 0xa6, 0x03, 0x26, 0x79, 0x03, 0xf8, 0xe4, 0x46,
+ 0x8e, 0x83, 0xc7, 0x9d, 0x89, 0xc4, 0x08, 0x78, 0xe8, 0x6e, 0x0d,
+ 0xcb, 0x96, 0x95, 0x8b, 0xd7, 0x0c, 0x92, 0x01, 0xa1, 0x30, 0x70,
+ 0xf3, 0xbd, 0x1c, 0x3b, 0xf7, 0x06, 0x83, 0x96, 0x4f, 0xd9, 0xaa,
+ 0xa5, 0x34, 0xb0, 0xe1, 0x22, 0x3a, 0xf0, 0xd6, 0xcb, 0x68, 0xef,
+ 0x3b, 0xdf, 0x44, 0xaf, 0x75, 0xf6, 0x62, 0x08, 0x0c, 0x05, 0xe4,
+ 0x40, 0x96, 0xfa, 0xd4, 0x82, 0x05, 0x5a, 0xd6, 0xf9, 0xa9, 0x65,
+ 0xc3, 0xf2, 0x6b, 0x38, 0x40, 0xcd, 0x80, 0x7b, 0x33, 0x8f, 0xca,
+ 0x24, 0x0b, 0x34, 0xb7, 0x78, 0x99, 0x55, 0x99, 0xb9, 0x81, 0x2b,
+ 0xec, 0x38, 0x1f, 0x02, 0x43, 0x04, 0x84, 0x0c, 0x92, 0x5b, 0xb7,
+ 0x8b, 0x65, 0x4f, 0x3c, 0x2b, 0xd6, 0x3c, 0xfe, 0xa4, 0xb8, 0x60,
+ 0xe7, 0x1e, 0x31, 0x3f, 0x78, 0x44, 0x02, 0xab, 0x47, 0x3d, 0x3d,
+ 0x74, 0xb7, 0x86, 0x8f, 0x7d, 0x92, 0x80, 0x31, 0x87, 0x0c, 0x09,
+ 0xe0, 0x5f, 0xbf, 0x2b, 0x70, 0xfd, 0xdf, 0x9a, 0x8e, 0xdb, 0xbf,
+ 0xf7, 0x2a, 0xc2, 0x0f, 0xbf, 0xa9, 0x4d, 0xeb, 0x01, 0xab, 0xa5,
+ 0x80, 0x1f, 0x7d, 0x5f, 0xe0, 0xba, 0xbf, 0x31, 0x51, 0x28, 0x06,
+ 0xd7, 0xda, 0xc9, 0xba, 0x3b, 0x90, 0x7e, 0xfb, 0x9b, 0xd8, 0xab,
+ 0x7f, 0x7a, 0x15, 0xed, 0xbc, 0xea, 0x52, 0xda, 0x3d, 0xef, 0x1c,
+ 0x0c, 0xa0, 0x08, 0x8e, 0x3c, 0x04, 0x44, 0x05, 0x5e, 0x05, 0x0b,
+ 0xc8, 0x0a, 0x2e, 0x90, 0x2b, 0xba, 0xc4, 0xd9, 0x3c, 0xdd, 0x4f,
+ 0x19, 0xa0, 0x4d, 0xc5, 0xcc, 0x9c, 0x9a, 0x61, 0xd8, 0x5d, 0xcc,
+ 0xb0, 0xcb, 0x14, 0x01, 0xca, 0x11, 0xb1, 0x08, 0x18, 0x34, 0x68,
+ 0x47, 0x0f, 0x63, 0xfe, 0x4f, 0x9e, 0xe6, 0xe7, 0x7f, 0xe7, 0xc7,
+ 0xe2, 0x8d, 0x5b, 0x5f, 0x16, 0xcb, 0x82, 0x47, 0x21, 0xb0, 0x46,
+ 0x59, 0x6b, 0x12, 0xd8, 0xf6, 0x7d, 0x0d, 0xab, 0x56, 0x11, 0x90,
+ 0xab, 0x56, 0x69, 0x82, 0x01, 0x1b, 0x6e, 0x30, 0xb1, 0x75, 0xfb,
+ 0x4c, 0x95, 0x95, 0x88, 0x03, 0x2f, 0x7e, 0x5f, 0xc3, 0xea, 0x35,
+ 0x0e, 0xdb, 0x45, 0x80, 0x63, 0x47, 0x81, 0xf3, 0xde, 0x67, 0x60,
+ 0x64, 0x3c, 0xb8, 0xc6, 0x32, 0xb6, 0xa0, 0x1b, 0xa3, 0xd7, 0x5c,
+ 0xcd, 0xb6, 0x7f, 0xe8, 0x3d, 0xb4, 0xed, 0xd2, 0x73, 0xe9, 0x00,
+ 0x62, 0x48, 0x23, 0x03, 0x02, 0x9f, 0x01, 0xb3, 0x7c, 0x19, 0x5e,
+ 0x79, 0x17, 0xb8, 0x39, 0xa9, 0x35, 0x57, 0xa8, 0x79, 0x01, 0xcd,
+ 0xad, 0x46, 0x53, 0x77, 0x71, 0x33, 0xad, 0x4a, 0x2c, 0x62, 0x99,
+ 0xc2, 0x20, 0x84, 0x11, 0x05, 0x03, 0x10, 0xfe, 0xfd, 0x0e, 0xb1,
+ 0xfc, 0x5f, 0x1e, 0x11, 0x57, 0x3d, 0xfe, 0xff, 0xf8, 0x1b, 0xc6,
+ 0x26, 0x82, 0x06, 0xac, 0x81, 0x35, 0xc7, 0x36, 0x5c, 0x48, 0xf8,
+ 0xcd, 0xf7, 0x34, 0x90, 0x93, 0xd2, 0x8a, 0x03, 0xcf, 0x6f, 0x13,
+ 0xd8, 0xf0, 0x21, 0x13, 0x45, 0x63, 0x3a, 0xf9, 0xb6, 0x0f, 0x32,
+ 0x7c, 0xe9, 0x7e, 0x06, 0x8c, 0x57, 0x43, 0x10, 0x61, 0xe0, 0xbd,
+ 0x1f, 0x37, 0xf1, 0xa3, 0xa7, 0x03, 0x57, 0xb3, 0x16, 0x7b, 0xf3,
+ 0x1b, 0x68, 0xf7, 0x2d, 0x7f, 0xc1, 0x7e, 0xf5, 0x67, 0x6f, 0xa5,
+ 0x97, 0xc2, 0x29, 0x8c, 0x21, 0x0b, 0xc0, 0x84, 0x61, 0x01, 0x59,
+ 0xde, 0x32, 0x5f, 0x70, 0x50, 0x6a, 0x45, 0x97, 0x78, 0x1a, 0x77,
+ 0x53, 0x68, 0xf6, 0xf6, 0x67, 0x4e, 0xdf, 0x60, 0x3a, 0xc5, 0xcc,
+ 0x42, 0x0e, 0xea, 0x2c, 0x5a, 0x01, 0x5a, 0x04, 0x0c, 0x84, 0xf0,
+ 0x73, 0x2f, 0x8a, 0xb5, 0xff, 0xf8, 0x75, 0xfe, 0x27, 0x3f, 0xff,
+ 0xb5, 0x38, 0x2f, 0x5f, 0x9c, 0x5b, 0x71, 0xb1, 0x68, 0x34, 0x0a,
+ 0xc6, 0x18, 0x4c, 0xd3, 0x44, 0x3e, 0x9f, 0x97, 0xce, 0x2f, 0x84,
+ 0x40, 0x36, 0x9b, 0x6d, 0xca, 0x39, 0xc5, 0xe3, 0x71, 0x44, 0xa3,
+ 0x51, 0x14, 0x8b, 0x45, 0x18, 0x86, 0x01, 0xd3, 0x2c, 0xb9, 0x60,
+ 0x9a, 0x56, 0xea, 0xce, 0x4c, 0xd7, 0x75, 0x70, 0xce, 0x31, 0x39,
+ 0x39, 0xd9, 0x90, 0xe3, 0xa5, 0x52, 0x29, 0x68, 0x9a, 0x36, 0xe3,
+ 0x58, 0xa6, 0x69, 0x82, 0x73, 0x0e, 0x4d, 0xd3, 0xc0, 0x18, 0xab,
+ 0x1c, 0x57, 0xd7, 0x75, 0x64, 0x32, 0x19, 0xa9, 0x6b, 0xe5, 0x65,
+ 0x5f, 0xbc, 0x83, 0xe1, 0xce, 0x5b, 0x19, 0x30, 0xe1, 0xb0, 0x32,
+ 0x09, 0xdc, 0x74, 0x3b, 0xc7, 0xb7, 0x7e, 0x54, 0xa2, 0xdd, 0xc2,
+ 0x1e, 0xe0, 0xc5, 0xc7, 0x75, 0x74, 0x77, 0x39, 0xc4, 0xce, 0x5a,
+ 0x80, 0x6f, 0x7c, 0x8b, 0xe3, 0xa3, 0xf7, 0xf0, 0x80, 0x4c, 0x75,
+ 0xda, 0xb9, 0x2b, 0xe9, 0xd8, 0x2d, 0x37, 0xb2, 0x7f, 0xfb, 0x8b,
+ 0xf7, 0xd0, 0x6f, 0x13, 0xed, 0x18, 0xc6, 0x24, 0x50, 0x6e, 0x08,
+ 0x92, 0x47, 0x49, 0x17, 0xdb, 0x95, 0x9b, 0x75, 0x32, 0x3d, 0x94,
+ 0x9a, 0x2b, 0xd0, 0xbc, 0x2a, 0x02, 0xa6, 0x26, 0x7b, 0xf0, 0x3f,
+ 0x5c, 0x51, 0x63, 0xa5, 0xdf, 0x28, 0x08, 0x11, 0x24, 0xc1, 0xf7,
+ 0xef, 0xc1, 0xd2, 0xbb, 0x37, 0xf3, 0x0f, 0x3c, 0xfa, 0x33, 0xfe,
+ 0x9f, 0xe6, 0x6a, 0x0d, 0xe5, 0x6d, 0xb7, 0xdd, 0x86, 0xdb, 0x6f,
+ 0xbf, 0x1d, 0xe9, 0x74, 0x1a, 0xd7, 0x5f, 0x7f, 0x3d, 0x76, 0xec,
+ 0xd8, 0xe1, 0x99, 0xff, 0xa6, 0x9b, 0x6e, 0xc2, 0x17, 0xbe, 0xf0,
+ 0x05, 0xfc, 0xe0, 0x07, 0x3f, 0xc0, 0x1d, 0x77, 0xdc, 0xd1, 0x94,
+ 0x73, 0xfa, 0xf8, 0xc7, 0x3f, 0x8e, 0x8d, 0x1b, 0x37, 0xa2, 0x50,
+ 0x28, 0xc0, 0x34, 0x4d, 0x68, 0x9a, 0x56, 0x01, 0x8b, 0x69, 0x9a,
+ 0x60, 0x8c, 0x61, 0xcb, 0x96, 0x2d, 0xb8, 0xf9, 0xe6, 0x9b, 0x1b,
+ 0x72, 0xbc, 0x07, 0x1f, 0x7c, 0x10, 0xd7, 0x5e, 0x7b, 0x2d, 0x84,
+ 0x10, 0xe0, 0x9c, 0x83, 0x73, 0x8e, 0x6c, 0x36, 0x0b, 0xd3, 0x34,
+ 0xa1, 0xeb, 0x3a, 0xe2, 0xf1, 0x92, 0x58, 0x67, 0x8c, 0x81, 0x88,
+ 0x70, 0xfd, 0xf5, 0xd7, 0xe3, 0xa9, 0xa7, 0x9e, 0xaa, 0xeb, 0x98,
+ 0xe1, 0x10, 0xf0, 0xfc, 0xf7, 0x35, 0x9c, 0x7f, 0x01, 0x01, 0x19,
+ 0xfb, 0x4a, 0xe0, 0xe4, 0x49, 0xe0, 0x82, 0x6b, 0x0c, 0x9c, 0x1a,
+ 0x06, 0x1e, 0xbc, 0x4b, 0xc3, 0x27, 0x3e, 0x4a, 0xd5, 0xea, 0x2c,
+ 0x0a, 0xec, 0xde, 0x0d, 0xbc, 0xf1, 0x06, 0x03, 0x63, 0x13, 0x01,
+ 0x90, 0x1a, 0x65, 0x6b, 0x97, 0xd3, 0xd1, 0xfb, 0xff, 0x9a, 0x3d,
+ 0xf6, 0xbe, 0x77, 0xd0, 0xef, 0xc0, 0x51, 0x44, 0x1e, 0x26, 0x08,
+ 0x39, 0x8b, 0x52, 0xcb, 0x7b, 0xb8, 0x9f, 0xf6, 0x2f, 0x0b, 0x2a,
+ 0x50, 0x93, 0xed, 0xd8, 0x4f, 0xa6, 0x82, 0x60, 0x5a, 0xb9, 0xe9,
+ 0x60, 0x88, 0xc3, 0xfc, 0xf2, 0x37, 0xf8, 0xbb, 0x2f, 0xbb, 0xce,
+ 0xfc, 0xfb, 0x47, 0x7e, 0xca, 0x37, 0xcc, 0xe5, 0xe6, 0x16, 0xd1,
+ 0x68, 0x14, 0x4b, 0x96, 0x2c, 0xc1, 0xfa, 0xf5, 0xeb, 0xf1, 0xc3,
+ 0x1f, 0xfe, 0x10, 0x8b, 0x16, 0x2d, 0xf2, 0xcc, 0x6f, 0x9a, 0x26,
+ 0x96, 0x2c, 0x59, 0x82, 0x48, 0x24, 0xd2, 0xb4, 0x73, 0xca, 0xe5,
+ 0x72, 0xe8, 0xe9, 0xe9, 0xc1, 0xa2, 0x45, 0x8b, 0xb0, 0x74, 0xe9,
+ 0x52, 0x68, 0x9a, 0x86, 0xf1, 0xf1, 0x71, 0xe4, 0xf3, 0x79, 0xc4,
+ 0xe3, 0x71, 0xf4, 0xf6, 0xf6, 0xa2, 0xb3, 0xb3, 0xb3, 0x61, 0xc7,
+ 0x6b, 0x6b, 0x6b, 0x43, 0x2a, 0x95, 0x42, 0x3e, 0x9f, 0xc7, 0xc8,
+ 0xc8, 0x08, 0x88, 0x08, 0x7d, 0x7d, 0x7d, 0x58, 0xb5, 0x6a, 0x15,
+ 0x96, 0x2f, 0x5f, 0x8e, 0x89, 0x89, 0x09, 0x8c, 0x8f, 0x8f, 0xc3,
+ 0x34, 0x4d, 0xcc, 0x9b, 0x37, 0x0f, 0xd1, 0x68, 0xfd, 0x1f, 0x77,
+ 0x14, 0x8a, 0xc0, 0x27, 0x36, 0x72, 0x14, 0x26, 0xcb, 0x4f, 0xe7,
+ 0x8c, 0x95, 0x40, 0xef, 0x32, 0xe0, 0x96, 0x1b, 0x18, 0x56, 0x2d,
+ 0x25, 0xdc, 0xf4, 0x7e, 0x02, 0x26, 0x1d, 0x5c, 0x4d, 0x0e, 0xdc,
+ 0x72, 0xbf, 0x19, 0xc0, 0xac, 0xc1, 0xf6, 0xea, 0x7e, 0xb1, 0xf0,
+ 0x9a, 0x4f, 0x99, 0x77, 0x7c, 0xe0, 0x53, 0xe6, 0xed, 0x03, 0xc3,
+ 0x68, 0x47, 0x12, 0x26, 0xaa, 0x1b, 0xd7, 0xdb, 0xbf, 0xdf, 0x76,
+ 0xea, 0x93, 0xd0, 0xca, 0x28, 0xcf, 0x9e, 0x4a, 0x65, 0xfa, 0xc2,
+ 0xaf, 0xfe, 0xd4, 0x29, 0x04, 0xe4, 0x0b, 0x08, 0xff, 0xe5, 0xa7,
+ 0xf9, 0xa7, 0x6e, 0xb9, 0x8f, 0xff, 0xd5, 0xe0, 0xa8, 0x68, 0x9d,
+ 0xeb, 0x37, 0xcf, 0xea, 0x36, 0xae, 0x58, 0xb1, 0x02, 0x5b, 0xb6,
+ 0x6c, 0x41, 0x5b, 0x5b, 0x9b, 0x6b, 0xfe, 0xb1, 0xb1, 0xb1, 0x19,
+ 0xbf, 0xcd, 0xb0, 0xe1, 0xe1, 0xe1, 0x2a, 0xc5, 0xb6, 0x76, 0xed,
+ 0x5a, 0xf4, 0xf5, 0xf5, 0x61, 0xf9, 0xf2, 0xe5, 0x58, 0xb1, 0x62,
+ 0x05, 0xee, 0xbc, 0xf3, 0xce, 0x86, 0x1d, 0xef, 0xb3, 0x9f, 0xfd,
+ 0x2c, 0x56, 0xac, 0x58, 0x81, 0xbe, 0xbe, 0x3e, 0xac, 0x5b, 0xb7,
+ 0x0e, 0x9f, 0xf9, 0xcc, 0x67, 0x66, 0xc0, 0xf5, 0x1d, 0xef, 0x78,
+ 0x07, 0x56, 0xaf, 0x5e, 0x8d, 0xbe, 0xbe, 0x3e, 0xac, 0x5c, 0xb9,
+ 0x12, 0x5b, 0xb7, 0x6e, 0x6d, 0xc8, 0x71, 0xb7, 0xfe, 0x5e, 0xe0,
+ 0x8b, 0x5f, 0xe3, 0x40, 0xd2, 0x61, 0x65, 0x1a, 0xb8, 0xf5, 0x46,
+ 0x86, 0x1f, 0xfc, 0x93, 0x86, 0x48, 0xb4, 0xfc, 0xbe, 0xb7, 0xb9,
+ 0xa5, 0xff, 0xfd, 0xeb, 0x1c, 0x4f, 0x6e, 0x0d, 0xe2, 0x66, 0xcd,
+ 0xb2, 0xc7, 0x7e, 0x21, 0x36, 0xbc, 0xe5, 0x83, 0xc6, 0xbd, 0xcf,
+ 0x3d, 0x2f, 0xd6, 0x21, 0x85, 0x02, 0xaa, 0x3f, 0x81, 0x74, 0xeb,
+ 0x65, 0xda, 0xb1, 0x8f, 0x46, 0xd5, 0xae, 0x97, 0xbd, 0x7b, 0xd9,
+ 0xd0, 0x40, 0x06, 0x87, 0xf6, 0xc1, 0x3b, 0xcd, 0x3b, 0xbe, 0xb9,
+ 0x85, 0x5f, 0x1d, 0xdc, 0xae, 0x92, 0xd9, 0x63, 0x41, 0x17, 0x5f,
+ 0x7c, 0x31, 0x1e, 0x7b, 0xec, 0x31, 0xc4, 0x62, 0x31, 0x69, 0x10,
+ 0x36, 0xda, 0xd2, 0xe9, 0xf4, 0x8c, 0xe5, 0x4c, 0x26, 0x53, 0x51,
+ 0x87, 0xa3, 0xa3, 0xa3, 0xd8, 0xbf, 0x7f, 0x3f, 0x8e, 0x1c, 0x39,
+ 0xd2, 0xb0, 0xe3, 0x1d, 0x3a, 0x74, 0x08, 0xc7, 0x8e, 0x1d, 0x43,
+ 0xb1, 0x58, 0x0a, 0x50, 0x15, 0x0a, 0x85, 0xca, 0x3a, 0xce, 0x79,
+ 0x25, 0xae, 0x96, 0xcd, 0x66, 0xb1, 0x6f, 0xdf, 0x3e, 0x8c, 0x8c,
+ 0x8c, 0x34, 0xec, 0xd8, 0xf7, 0x7f, 0x9d, 0x63, 0xdb, 0xb3, 0x40,
+ 0x55, 0x15, 0x94, 0x09, 0xb4, 0xb5, 0x01, 0xeb, 0xd7, 0x96, 0x1d,
+ 0x1c, 0x9b, 0xab, 0xb9, 0x6b, 0x07, 0xb0, 0xf1, 0x2b, 0x41, 0xdc,
+ 0xac, 0xe9, 0x6a, 0xed, 0x00, 0x16, 0xbf, 0xfb, 0x13, 0xe6, 0x5d,
+ 0x5b, 0xb7, 0x8a, 0xf3, 0x10, 0x47, 0x11, 0xee, 0x1d, 0xb4, 0x7a,
+ 0x8d, 0x9a, 0xe6, 0x09, 0x34, 0x99, 0xb1, 0x01, 0xaa, 0xfb, 0x19,
+ 0x8b, 0xc0, 0xf8, 0xbb, 0x2f, 0xf2, 0x0f, 0xff, 0x9f, 0x5f, 0x8a,
+ 0x2b, 0x83, 0xdb, 0xe4, 0x6d, 0x57, 0x5f, 0x7d, 0x35, 0xbe, 0xf1,
+ 0x8d, 0x6f, 0x40, 0xd7, 0xab, 0x7b, 0x41, 0x9f, 0x82, 0x4b, 0x2e,
+ 0x97, 0x6b, 0xaa, 0xcb, 0x69, 0x77, 0x73, 0x67, 0xd3, 0x84, 0xad,
+ 0xa9, 0xfd, 0x54, 0xa5, 0x40, 0x53, 0x14, 0x72, 0x0e, 0xb8, 0x75,
+ 0x93, 0x89, 0x42, 0xd6, 0xc1, 0xf5, 0x34, 0xcb, 0x51, 0x1a, 0xdb,
+ 0xb8, 0xf3, 0x42, 0x00, 0x7f, 0xfd, 0x0f, 0x26, 0xc6, 0xd3, 0xc1,
+ 0xb3, 0x3a, 0x1b, 0x36, 0x38, 0x8a, 0xf6, 0x1b, 0xef, 0xe4, 0x7f,
+ 0x3b, 0xd4, 0x8f, 0x0e, 0x84, 0x2a, 0xdd, 0x74, 0xfb, 0x8d, 0xcc,
+ 0x56, 0xc5, 0x2a, 0xbf, 0xa7, 0xc8, 0x0b, 0x6c, 0x33, 0xd3, 0xc3,
+ 0x30, 0x5e, 0xdb, 0x29, 0xfa, 0x1e, 0xf8, 0x0e, 0xbf, 0x2e, 0xb8,
+ 0x3d, 0xb6, 0x8b, 0x48, 0xa5, 0xcb, 0xb5, 0x69, 0xd3, 0x26, 0xf4,
+ 0xf7, 0xf7, 0x57, 0xd2, 0x6f, 0xb8, 0xe1, 0x06, 0x6c, 0xde, 0xbc,
+ 0xb9, 0x3a, 0xf6, 0x53, 0x56, 0x2f, 0xcd, 0x04, 0xda, 0xd4, 0x39,
+ 0xcd, 0x86, 0x1a, 0x3c, 0x13, 0x6c, 0xdb, 0x0e, 0x81, 0x7f, 0xfa,
+ 0xba, 0x8b, 0xeb, 0x89, 0x6a, 0x57, 0x73, 0xf3, 0xd7, 0x39, 0x7e,
+ 0xf1, 0x6c, 0xe0, 0x6a, 0xce, 0xa6, 0x1d, 0x3c, 0x2e, 0xe6, 0xdf,
+ 0xf3, 0x3f, 0xf8, 0x07, 0x11, 0x82, 0x01, 0xe7, 0x91, 0xd1, 0x7c,
+ 0xcd, 0x2f, 0x86, 0x26, 0xef, 0x7e, 0x86, 0x60, 0x3c, 0xfc, 0x53,
+ 0xf1, 0x16, 0xce, 0xab, 0x87, 0x31, 0x0b, 0x80, 0x56, 0xba, 0x94,
+ 0x5b, 0xb6, 0x6c, 0xc1, 0xb5, 0xd7, 0x5e, 0x3b, 0xc3, 0xdd, 0xbb,
+ 0xf9, 0xe6, 0x9b, 0xb1, 0x69, 0xd3, 0x26, 0xc7, 0xfc, 0xf5, 0x36,
+ 0x5b, 0x50, 0xb1, 0xbe, 0xbe, 0x3e, 0xac, 0x59, 0xb3, 0x06, 0xe7,
+ 0x9f, 0x7f, 0x3e, 0x2e, 0xbd, 0xf4, 0x52, 0xbc, 0xf9, 0xcd, 0x6f,
+ 0xc6, 0xea, 0xd5, 0xab, 0xcf, 0xaa, 0xfb, 0x70, 0xef, 0x43, 0x1c,
+ 0xcf, 0x3d, 0x2b, 0xe0, 0xd9, 0x99, 0x54, 0x04, 0x78, 0xed, 0xf7,
+ 0x02, 0xf7, 0x3c, 0x18, 0xb8, 0x9a, 0xa7, 0xc3, 0x1e, 0x7f, 0x82,
+ 0xbf, 0x65, 0x62, 0x10, 0x1d, 0xd0, 0x2b, 0x83, 0xa3, 0x78, 0x29,
+ 0xb2, 0x2a, 0x5e, 0x79, 0x01, 0xcd, 0x3a, 0xac, 0x94, 0xd7, 0x70,
+ 0x75, 0xe5, 0x40, 0x08, 0x68, 0xcf, 0x21, 0xb1, 0x38, 0xb8, 0x25,
+ 0xd5, 0x16, 0x0e, 0x87, 0x01, 0x00, 0x2d, 0x2d, 0x2d, 0x78, 0xf6,
+ 0xd9, 0x67, 0x71, 0xdd, 0x75, 0xd7, 0xc1, 0x30, 0xa6, 0x5b, 0x74,
+ 0x7e, 0xee, 0x73, 0x9f, 0xc3, 0x2d, 0xb7, 0xdc, 0x52, 0xb5, 0x9d,
+ 0x35, 0x4f, 0xb3, 0xed, 0xd1, 0x47, 0x1f, 0xc5, 0xab, 0xaf, 0xbe,
+ 0x8a, 0xed, 0xdb, 0xb7, 0x63, 0xdb, 0xb6, 0x6d, 0x78, 0xe6, 0x99,
+ 0x67, 0xf0, 0x91, 0x8f, 0x7c, 0xe4, 0xac, 0xba, 0x0f, 0x99, 0x1c,
+ 0xf0, 0xa9, 0x4d, 0x1c, 0xbc, 0xe8, 0x52, 0x2c, 0x18, 0x50, 0x2c,
+ 0x02, 0x7f, 0xf9, 0x79, 0x8e, 0xb1, 0xc0, 0xd5, 0x3c, 0x2d, 0x96,
+ 0xce, 0x22, 0x39, 0x99, 0x45, 0x0c, 0xb0, 0x0c, 0x74, 0x5d, 0xcd,
+ 0x25, 0x57, 0xb1, 0xe5, 0x37, 0x8c, 0x9d, 0xd3, 0x20, 0xa0, 0xce,
+ 0xa3, 0x1e, 0x33, 0x88, 0x05, 0xdd, 0x34, 0xd0, 0xec, 0xb1, 0x16,
+ 0x5f, 0x8f, 0x66, 0x8f, 0x93, 0xfd, 0xfc, 0xe7, 0x3f, 0xc7, 0x87,
+ 0x3f, 0xfc, 0x61, 0x3c, 0xf2, 0xc8, 0x23, 0x95, 0xb4, 0xcd, 0x9b,
+ 0x37, 0x63, 0x62, 0x62, 0x02, 0xdf, 0xfe, 0xf6, 0xb7, 0xab, 0x5c,
+ 0xcf, 0x59, 0x79, 0x33, 0x3e, 0xfe, 0x38, 0x8e, 0x1e, 0x3d, 0x8a,
+ 0x44, 0x22, 0x81, 0x78, 0x3c, 0x8e, 0x54, 0x2a, 0x85, 0xdd, 0xbb,
+ 0x77, 0x9f, 0x75, 0xf7, 0x62, 0xc3, 0x45, 0x04, 0x0a, 0xa1, 0xfa,
+ 0xd3, 0xa6, 0xf2, 0x93, 0xad, 0x85, 0x81, 0xab, 0xaf, 0xa0, 0xaa,
+ 0xcf, 0xa2, 0x02, 0x9b, 0x1d, 0x8b, 0x86, 0x91, 0x8b, 0x85, 0x91,
+ 0xaf, 0xd5, 0x73, 0x54, 0x1d, 0x68, 0xd8, 0x09, 0x6c, 0xa5, 0xc9,
+ 0x84, 0x76, 0xfd, 0xdb, 0xe9, 0xd7, 0x5f, 0xfa, 0x2e, 0x3e, 0x10,
+ 0xdc, 0x16, 0x9b, 0x17, 0xe3, 0xd0, 0x9e, 0xec, 0xd1, 0x47, 0x1f,
+ 0x45, 0x57, 0x57, 0x17, 0xbe, 0xf4, 0xa5, 0x2f, 0x95, 0xde, 0x07,
+ 0x8c, 0xe1, 0xc1, 0x07, 0x1f, 0xc4, 0x89, 0x13, 0x27, 0x66, 0xc4,
+ 0xd9, 0x66, 0xcb, 0x36, 0x6d, 0xda, 0x84, 0x97, 0x5f, 0x7e, 0xf9,
+ 0xac, 0xbe, 0x0f, 0x97, 0xac, 0x27, 0xdc, 0xf7, 0x69, 0x06, 0x2a,
+ 0xba, 0x3f, 0xdd, 0xcc, 0x00, 0xee, 0xbe, 0x95, 0xe1, 0x89, 0x67,
+ 0x05, 0xfe, 0xfd, 0x95, 0x00, 0x6a, 0xb3, 0x6d, 0x57, 0x5f, 0x41,
+ 0xcf, 0xb7, 0x76, 0x61, 0x18, 0xf9, 0xca, 0xd8, 0x9d, 0x5e, 0x83,
+ 0xa4, 0xc0, 0x96, 0xee, 0xdb, 0x6c, 0xc3, 0x6d, 0xc3, 0x6a, 0xb0,
+ 0xe5, 0x10, 0x7a, 0xe3, 0x25, 0xf4, 0x87, 0xeb, 0xfe, 0x33, 0x3d,
+ 0x1d, 0xdc, 0x16, 0xdb, 0x5b, 0xc7, 0xa5, 0x91, 0xe8, 0xe6, 0xcd,
+ 0x9b, 0x71, 0xff, 0xfd, 0xf7, 0x57, 0x96, 0x63, 0xb1, 0x18, 0x1e,
+ 0x7e, 0xf8, 0x61, 0xbc, 0xfb, 0xdd, 0xef, 0x06, 0x30, 0xbb, 0x31,
+ 0xb4, 0x64, 0x32, 0x39, 0xab, 0xd7, 0x24, 0x14, 0x9a, 0xdd, 0xaf,
+ 0xdf, 0x22, 0x61, 0xe0, 0x5f, 0x3e, 0xc7, 0x10, 0x4f, 0xa1, 0xba,
+ 0xbd, 0x99, 0xd5, 0xcc, 0x92, 0x4a, 0x7b, 0xe8, 0x1e, 0x86, 0x54,
+ 0x22, 0x78, 0x76, 0x67, 0xd3, 0xda, 0x52, 0x98, 0xb8, 0xf7, 0x16,
+ 0xed, 0xe1, 0xca, 0x10, 0xcb, 0x70, 0x9c, 0x9c, 0xd8, 0x64, 0x8d,
+ 0x1a, 0xf8, 0x82, 0xac, 0x8a, 0x82, 0x96, 0xf9, 0xe9, 0x6f, 0xa9,
+ 0x04, 0x04, 0x09, 0xe0, 0xab, 0xf7, 0x69, 0xff, 0x7c, 0xe9, 0x7a,
+ 0xda, 0x15, 0xdc, 0x1e, 0x7f, 0xa0, 0x01, 0xc0, 0x5d, 0x77, 0xdd,
+ 0x85, 0xaf, 0x7e, 0xf5, 0xab, 0x95, 0xe5, 0xae, 0xae, 0x2e, 0xdc,
+ 0x77, 0xdf, 0x7d, 0x00, 0x4a, 0xed, 0xb3, 0x9a, 0x65, 0xe2, 0x34,
+ 0xf7, 0x50, 0x68, 0x6d, 0xa6, 0xa1, 0x69, 0x9a, 0x63, 0xf3, 0x95,
+ 0x46, 0xda, 0xad, 0x37, 0x30, 0x5c, 0xbe, 0xc1, 0xe1, 0x6b, 0x00,
+ 0xa7, 0x88, 0x70, 0x16, 0x38, 0xff, 0x12, 0xc2, 0xe7, 0x3e, 0xc2,
+ 0x82, 0x87, 0x77, 0xb6, 0x5e, 0x70, 0x3a, 0x8a, 0x0f, 0xdd, 0xa3,
+ 0x6d, 0x5e, 0xb9, 0x16, 0x07, 0x90, 0x2f, 0x0f, 0x73, 0xe4, 0xdc,
+ 0xdd, 0xb6, 0x80, 0x7b, 0x5c, 0x4b, 0xea, 0xd3, 0x27, 0xe1, 0xf0,
+ 0xeb, 0xd4, 0x75, 0x87, 0x89, 0x22, 0xa8, 0xb5, 0x0d, 0x13, 0x3f,
+ 0x79, 0x48, 0xbb, 0x77, 0xc3, 0x85, 0xb4, 0x33, 0xb8, 0x4d, 0xd3,
+ 0xca, 0xcb, 0xcb, 0x3e, 0xf9, 0xc9, 0x4f, 0xe2, 0x89, 0x27, 0x9e,
+ 0x98, 0xd5, 0x73, 0x9a, 0xfa, 0x08, 0xfd, 0x4c, 0x30, 0x22, 0xaa,
+ 0x6a, 0x46, 0xd2, 0x48, 0xbb, 0x68, 0x2d, 0xe1, 0xde, 0xdb, 0x59,
+ 0xf5, 0xf7, 0x9c, 0x5e, 0xf5, 0x66, 0x69, 0xe0, 0x6f, 0x3e, 0xc6,
+ 0x70, 0xe9, 0xfa, 0xa0, 0x83, 0xe4, 0x66, 0x5b, 0x4b, 0x02, 0x93,
+ 0xdf, 0x7f, 0x40, 0xfb, 0xe2, 0x75, 0xd7, 0xd0, 0xd3, 0x48, 0x23,
+ 0x0a, 0xff, 0x8e, 0x1c, 0xe1, 0xe2, 0x2d, 0x92, 0x4c, 0x2d, 0xa7,
+ 0x7d, 0x08, 0x29, 0xfb, 0x60, 0xa0, 0x33, 0x07, 0x36, 0xc8, 0x82,
+ 0x75, 0x77, 0x61, 0xf8, 0x97, 0xdf, 0xd2, 0x36, 0x7e, 0xfa, 0x26,
+ 0xf6, 0xa3, 0x90, 0x0e, 0x63, 0xae, 0xdf, 0xb0, 0x44, 0x22, 0xe1,
+ 0xe9, 0x66, 0x19, 0x86, 0x81, 0x1b, 0x6f, 0xbc, 0x11, 0x2f, 0xbc,
+ 0xf0, 0xc2, 0xec, 0x3d, 0x44, 0x2d, 0x2d, 0x33, 0x96, 0xed, 0x6d,
+ 0xde, 0x18, 0x63, 0x0d, 0xf9, 0x9e, 0xd2, 0xd5, 0x05, 0xb4, 0xc4,
+ 0x15, 0x19, 0x63, 0x4d, 0x53, 0x68, 0x91, 0x30, 0xf0, 0x3f, 0xff,
+ 0x8e, 0x21, 0xe6, 0xe4, 0x6a, 0x26, 0x80, 0x7f, 0xf8, 0x1a, 0xc7,
+ 0x33, 0xdb, 0x04, 0x10, 0xab, 0x76, 0x3d, 0xf5, 0x68, 0xc9, 0xf5,
+ 0x4c, 0x04, 0x9d, 0x5c, 0x35, 0xcd, 0xae, 0xb8, 0x80, 0x76, 0x3d,
+ 0xf3, 0x5d, 0xed, 0xf3, 0xd7, 0xbc, 0x87, 0x7e, 0x8d, 0x09, 0x84,
+ 0xe1, 0xdd, 0xf7, 0x99, 0x5d, 0x4c, 0x55, 0xb1, 0x8a, 0xf9, 0xb8,
+ 0x9b, 0xc2, 0x05, 0x6e, 0xf6, 0xfe, 0xbc, 0xa7, 0xa1, 0x46, 0x30,
+ 0x90, 0x07, 0x45, 0xc3, 0xc8, 0x3f, 0xf0, 0x79, 0xf6, 0xbf, 0x9e,
+ 0xfe, 0xb6, 0xf6, 0xf7, 0x6f, 0xba, 0x98, 0x5e, 0x9b, 0xd3, 0x6f,
+ 0xa0, 0x32, 0x3c, 0xbc, 0xe2, 0x46, 0x43, 0x43, 0x43, 0x78, 0xff,
+ 0xfb, 0xdf, 0x8f, 0xc3, 0x87, 0x0f, 0xcf, 0x50, 0x2e, 0xcd, 0xb2,
+ 0xd6, 0xd6, 0x99, 0x9f, 0xd8, 0x6e, 0xdc, 0xb8, 0x11, 0xdf, 0xfc,
+ 0xe6, 0x37, 0xf1, 0xe8, 0xa3, 0x8f, 0xe2, 0x67, 0x3f, 0xfb, 0x19,
+ 0x76, 0xee, 0xdc, 0x89, 0x07, 0x1e, 0x78, 0x60, 0x56, 0x54, 0xab,
+ 0xae, 0xeb, 0x95, 0xa6, 0x2d, 0x8d, 0xb6, 0xbb, 0x3f, 0xce, 0x70,
+ 0xf9, 0x9b, 0x1c, 0x5c, 0xcd, 0x30, 0x70, 0x64, 0x5f, 0xa9, 0x6d,
+ 0xda, 0xe7, 0xbf, 0xcc, 0x21, 0x0c, 0x67, 0xd7, 0xf3, 0xa2, 0x37,
+ 0x12, 0xee, 0xfa, 0x58, 0xe0, 0x7a, 0x36, 0xda, 0x3a, 0x5a, 0x90,
+ 0xfe, 0xe2, 0x9d, 0xec, 0x91, 0x5f, 0x3f, 0xac, 0x6d, 0xbc, 0xf0,
+ 0x3c, 0xda, 0x8b, 0x34, 0x42, 0x1e, 0x30, 0x73, 0x1a, 0xf1, 0x09,
+ 0x4e, 0xae, 0xa7, 0xee, 0xa1, 0xce, 0xc8, 0x47, 0xa9, 0x99, 0x98,
+ 0xf9, 0xf9, 0x93, 0x01, 0xeb, 0x97, 0xf1, 0x06, 0x18, 0xd2, 0x88,
+ 0x6c, 0xb8, 0x8c, 0x76, 0xfc, 0xea, 0x3b, 0xda, 0x3f, 0xfe, 0xf0,
+ 0x97, 0xe2, 0x92, 0xfb, 0x1e, 0xe4, 0xef, 0xd9, 0xbe, 0x6b, 0xee,
+ 0xb5, 0x55, 0x8b, 0xc7, 0xe3, 0xe0, 0x9c, 0xfb, 0x2a, 0x9e, 0x43,
+ 0x87, 0x0e, 0xe1, 0x9a, 0x6b, 0xae, 0xc1, 0x93, 0x4f, 0x3e, 0x89,
+ 0xb6, 0xb6, 0xb6, 0xa6, 0xc6, 0xb9, 0xba, 0xba, 0xba, 0x00, 0x94,
+ 0xe2, 0x74, 0x42, 0x08, 0xbc, 0xeb, 0x5d, 0xef, 0xaa, 0xca, 0xf3,
+ 0xca, 0x2b, 0xaf, 0x34, 0xf5, 0x9a, 0x4c, 0x75, 0x25, 0xa4, 0x69,
+ 0x5a, 0xa5, 0xfb, 0xa0, 0x46, 0xda, 0x65, 0xe7, 0x11, 0xee, 0xfc,
+ 0x18, 0xab, 0x86, 0x59, 0x19, 0x68, 0x7f, 0xb7, 0x99, 0x23, 0x97,
+ 0x07, 0x7e, 0xf3, 0xa2, 0xc0, 0x63, 0x3f, 0x16, 0xf8, 0xc0, 0x75,
+ 0x54, 0xdd, 0x77, 0x5a, 0x1a, 0xb8, 0xf3, 0xaf, 0x18, 0x9e, 0xdc,
+ 0x2a, 0xf0, 0xd4, 0xb6, 0xa0, 0xd6, 0xb3, 0xee, 0x17, 0x69, 0x12,
+ 0x99, 0x8f, 0xfe, 0x39, 0x7b, 0xe6, 0xb6, 0x0f, 0xb1, 0x27, 0x16,
+ 0x2d, 0xc1, 0x51, 0x64, 0x21, 0x90, 0x05, 0xa1, 0xba, 0x9b, 0x20,
+ 0xa7, 0x01, 0x52, 0x5c, 0x87, 0xaf, 0xab, 0x88, 0x00, 0x89, 0x0e,
+ 0x1e, 0xed, 0x9d, 0x3c, 0x3a, 0xf5, 0x58, 0xeb, 0xd4, 0xfd, 0xf6,
+ 0x74, 0x8f, 0xb5, 0x0c, 0x61, 0xc4, 0x21, 0xb2, 0xa3, 0x68, 0xff,
+ 0xbf, 0xbf, 0x12, 0x17, 0x7d, 0xed, 0x71, 0x7e, 0xe5, 0x2f, 0xb7,
+ 0x8a, 0xb5, 0x73, 0xe5, 0x26, 0xf6, 0xf5, 0xf5, 0x21, 0x1a, 0x8d,
+ 0xe2, 0xe4, 0xc9, 0x93, 0x18, 0x1a, 0x1a, 0xf2, 0xcd, 0xbf, 0x6c,
+ 0xd9, 0x32, 0x24, 0x12, 0x09, 0x1c, 0x3b, 0x76, 0xac, 0xa1, 0x1f,
+ 0x69, 0x5b, 0x6d, 0xc1, 0x82, 0x05, 0xe8, 0xe9, 0xe9, 0x41, 0x2e,
+ 0x97, 0x83, 0x10, 0xa2, 0xa2, 0x06, 0x85, 0x10, 0xd0, 0x34, 0x0d,
+ 0xd1, 0x68, 0x14, 0x63, 0x63, 0x63, 0xd8, 0xbb, 0x77, 0x6f, 0xd3,
+ 0x8e, 0xdf, 0xd9, 0xd9, 0x89, 0x42, 0xa1, 0x80, 0x68, 0x34, 0x8a,
+ 0x03, 0x07, 0x0e, 0x60, 0x7c, 0xbc, 0x71, 0x7d, 0x5b, 0xc7, 0x22,
+ 0xc0, 0xb6, 0xef, 0x69, 0x38, 0xf7, 0x3c, 0x02, 0xec, 0x5f, 0x75,
+ 0xc5, 0x81, 0x17, 0x9f, 0x17, 0xd8, 0xf0, 0x61, 0x13, 0xf9, 0x72,
+ 0x53, 0xbf, 0xd5, 0x4b, 0x09, 0xcf, 0x3f, 0xae, 0x95, 0x6a, 0x36,
+ 0x8d, 0xea, 0xfc, 0x3b, 0x77, 0x00, 0x97, 0xdd, 0x60, 0x60, 0x32,
+ 0x1b, 0x40, 0xa9, 0x16, 0x5b, 0x7a, 0x0e, 0x06, 0x3f, 0xfa, 0x7e,
+ 0xf6, 0xec, 0x07, 0xde, 0x49, 0xdb, 0x56, 0xac, 0xa6, 0x03, 0xc8,
+ 0x43, 0x94, 0xc7, 0x6a, 0x9f, 0xea, 0xd4, 0x31, 0x6f, 0xfb, 0xad,
+ 0xa5, 0x1b, 0x6e, 0xe9, 0x31, 0x05, 0xdc, 0x46, 0x45, 0x77, 0xea,
+ 0xb9, 0x36, 0x84, 0xe9, 0xce, 0x1e, 0x67, 0x02, 0x4e, 0x43, 0x08,
+ 0x31, 0x08, 0x14, 0x10, 0x7f, 0xe6, 0x39, 0xb1, 0xe6, 0x5f, 0x7f,
+ 0x21, 0x2e, 0xf9, 0xe9, 0xaf, 0xf8, 0xfa, 0xc3, 0x27, 0xd0, 0x11,
+ 0xdc, 0xf2, 0xc0, 0x1a, 0x69, 0xf7, 0xdf, 0xca, 0xf0, 0x5f, 0xef,
+ 0x70, 0xe8, 0xad, 0x96, 0x01, 0x5c, 0x03, 0xde, 0xf6, 0x21, 0x13,
+ 0x4f, 0x3f, 0x3f, 0x53, 0x71, 0x7d, 0xe1, 0x13, 0x0c, 0xf7, 0x7c,
+ 0xd6, 0xa1, 0x0b, 0x6e, 0x00, 0x48, 0x01, 0xff, 0xfc, 0x15, 0x8e,
+ 0xdb, 0xfe, 0x5b, 0xf0, 0x49, 0x94, 0xac, 0x85, 0x74, 0x18, 0x7f,
+ 0x7c, 0x39, 0xed, 0x7e, 0xdf, 0xdb, 0x68, 0xfb, 0xf5, 0xef, 0x64,
+ 0xcf, 0xb7, 0x74, 0x63, 0xa8, 0x0c, 0x32, 0xd3, 0x02, 0xad, 0x82,
+ 0x03, 0xc8, 0xec, 0xa3, 0x40, 0x39, 0x0d, 0x46, 0xec, 0x54, 0x61,
+ 0xc0, 0x55, 0x06, 0x49, 0x71, 0x1a, 0x57, 0xc0, 0x3e, 0x50, 0x4a,
+ 0x18, 0xd5, 0xe3, 0x0b, 0x84, 0xab, 0x96, 0x09, 0x21, 0x44, 0x41,
+ 0xd0, 0xc1, 0x46, 0x4e, 0x62, 0xde, 0x2f, 0x7e, 0x2b, 0xd6, 0x7d,
+ 0xf7, 0xc7, 0xfc, 0xd2, 0xe7, 0x77, 0x88, 0x45, 0x83, 0x23, 0x48,
+ 0x06, 0x8f, 0x42, 0x60, 0xf5, 0xd8, 0x95, 0x6f, 0x20, 0x3c, 0xf3,
+ 0xb0, 0x06, 0x9a, 0x0a, 0x8c, 0x58, 0x2d, 0x09, 0xfc, 0xe4, 0x27,
+ 0x02, 0x7f, 0xfa, 0xa9, 0xea, 0xc6, 0x68, 0x1d, 0xad, 0xc0, 0xcb,
+ 0xff, 0x5b, 0xc7, 0xa2, 0xc5, 0xa8, 0xee, 0x4e, 0x48, 0x03, 0x04,
+ 0x01, 0x6f, 0xf9, 0x2f, 0x26, 0x7e, 0xf3, 0x62, 0xe0, 0x7a, 0x7a,
+ 0x40, 0xcc, 0x3c, 0x6f, 0x15, 0x9d, 0x78, 0xd7, 0x95, 0xf4, 0x87,
+ 0xeb, 0xde, 0x45, 0x2f, 0x9d, 0xb7, 0x86, 0x0e, 0x23, 0x84, 0x5c,
+ 0x79, 0x0c, 0x01, 0x13, 0x33, 0x7b, 0xa2, 0x75, 0x1a, 0xfd, 0xc9,
+ 0x3a, 0xac, 0x9d, 0xdd, 0xfd, 0xf4, 0x1d, 0xca, 0xae, 0x11, 0xe3,
+ 0x72, 0x3a, 0x8d, 0x8a, 0xee, 0x34, 0xa4, 0x9d, 0x8e, 0x99, 0x63,
+ 0x72, 0x96, 0xe6, 0x75, 0x68, 0x88, 0x00, 0x30, 0x11, 0x3e, 0x75,
+ 0x12, 0x9d, 0xbf, 0x78, 0x96, 0xaf, 0xf9, 0xd1, 0x53, 0x62, 0xfd,
+ 0x6f, 0x5e, 0x14, 0xcb, 0x07, 0x86, 0x03, 0xb8, 0x05, 0xa6, 0x66,
+ 0xdd, 0x1d, 0xc0, 0xbf, 0x7f, 0x4f, 0xc7, 0xb2, 0xf5, 0xa8, 0x76,
+ 0x35, 0x75, 0x20, 0x3b, 0x0a, 0x5c, 0xf4, 0x3e, 0x13, 0xbb, 0x0e,
+ 0x3a, 0x43, 0xe9, 0xfa, 0x77, 0x30, 0x7c, 0xef, 0x2b, 0xac, 0x54,
+ 0x74, 0xec, 0x59, 0xa2, 0xc0, 0xc9, 0xbd, 0xc0, 0x45, 0x7f, 0x6e,
+ 0xe0, 0xe4, 0x60, 0x70, 0xad, 0x2b, 0x97, 0x25, 0x8c, 0xe2, 0xfa,
+ 0x95, 0x74, 0xf2, 0xcf, 0xae, 0xa2, 0x9d, 0xef, 0xb9, 0x8a, 0x76,
+ 0x5e, 0xb0, 0x86, 0x8e, 0x21, 0x86, 0x49, 0x14, 0xcb, 0x6e, 0xa5,
+ 0xa8, 0xc0, 0xc9, 0x6b, 0x6c, 0x4e, 0xaf, 0x21, 0xec, 0x7c, 0x07,
+ 0x47, 0x91, 0x01, 0x9a, 0x97, 0xeb, 0xe9, 0x35, 0x3e, 0xa7, 0xcc,
+ 0xc8, 0xe9, 0xd5, 0x69, 0x04, 0x1d, 0x1a, 0x18, 0xa2, 0x00, 0x0c,
+ 0x84, 0x07, 0xfb, 0xd1, 0xbe, 0x73, 0x9f, 0x98, 0xbf, 0xe5, 0x29,
+ 0xb1, 0xee, 0x77, 0xff, 0x21, 0x96, 0xed, 0x3e, 0x28, 0xe6, 0x8d,
+ 0x4e, 0x20, 0x16, 0x3c, 0x3e, 0x81, 0x79, 0xd9, 0xc2, 0x1e, 0xe0,
+ 0x8a, 0x0b, 0x09, 0xf9, 0x3c, 0xaa, 0x6a, 0x2d, 0x49, 0x03, 0x4e,
+ 0x9d, 0x2a, 0xf5, 0x62, 0xeb, 0x66, 0x8c, 0x01, 0x6f, 0xbf, 0x82,
+ 0x10, 0x8e, 0x38, 0x8c, 0x8e, 0x2e, 0x80, 0x48, 0x04, 0xf8, 0xed,
+ 0x4b, 0x02, 0x27, 0x06, 0xe6, 0xee, 0x35, 0x66, 0x0c, 0x7c, 0xc5,
+ 0x62, 0x1a, 0x3a, 0x6f, 0x25, 0x4e, 0xbc, 0xf7, 0x8f, 0xd9, 0xce,
+ 0xcb, 0xcf, 0xa7, 0xc3, 0x7d, 0x0b, 0x31, 0x40, 0x29, 0xa4, 0xcb,
+ 0x5a, 0x4b, 0x40, 0xc0, 0x84, 0xf3, 0xc8, 0xe8, 0x5e, 0xcb, 0x06,
+ 0xdc, 0x07, 0x1a, 0xe6, 0xa8, 0xae, 0xf9, 0x94, 0x1e, 0x39, 0xdd,
+ 0x4b, 0xa5, 0x11, 0xdc, 0x47, 0x50, 0x77, 0x52, 0x6c, 0x4e, 0x80,
+ 0xd3, 0x1d, 0xe6, 0xa7, 0xa7, 0x29, 0xb8, 0x85, 0x40, 0xd0, 0x40,
+ 0xc8, 0x22, 0x76, 0xbc, 0x1f, 0x6d, 0xcf, 0xbc, 0x28, 0x96, 0xff,
+ 0xee, 0x3f, 0xc4, 0xd2, 0xa7, 0x9e, 0x13, 0xcb, 0x0f, 0x1e, 0x17,
+ 0x1d, 0x99, 0x2c, 0xc2, 0x41, 0x11, 0x0e, 0x2c, 0xb0, 0xe6, 0x1a,
+ 0x11, 0xc4, 0xfc, 0x2e, 0x8c, 0xbf, 0x61, 0x1d, 0x1d, 0xfb, 0xa3,
+ 0xcb, 0x68, 0xdf, 0x5b, 0x2f, 0xa5, 0x7d, 0x6b, 0xfb, 0xa8, 0x3f,
+ 0x92, 0x42, 0x1a, 0x04, 0xa3, 0x8c, 0x22, 0x01, 0x5e, 0x71, 0x0b,
+ 0xad, 0xae, 0xa2, 0x15, 0x54, 0x5e, 0xf3, 0x26, 0x66, 0x0e, 0x55,
+ 0x67, 0xb8, 0x80, 0xcc, 0xeb, 0x0b, 0x02, 0xd8, 0x81, 0x26, 0x03,
+ 0x35, 0xaf, 0x81, 0x52, 0x18, 0xaa, 0xfb, 0x04, 0x77, 0x82, 0x9b,
+ 0x66, 0x03, 0x9a, 0xe6, 0xb2, 0xbe, 0x34, 0x4f, 0x60, 0xd0, 0x41,
+ 0x08, 0x43, 0x80, 0xa0, 0x19, 0x63, 0x48, 0x1e, 0x3d, 0x85, 0xb6,
+ 0x5d, 0x07, 0x44, 0xf7, 0x2f, 0x9f, 0x13, 0xcb, 0x5f, 0xfa, 0x83,
+ 0x58, 0xb8, 0x7d, 0x97, 0x98, 0x3f, 0x34, 0x8a, 0xe0, 0xeb, 0xbb,
+ 0xc0, 0x02, 0x6b, 0x40, 0x1c, 0x6c, 0x5d, 0x1f, 0xf5, 0x9f, 0xbb,
+ 0x0a, 0x27, 0xdf, 0x76, 0x19, 0xed, 0xbd, 0x68, 0x1d, 0x1d, 0x5f,
+ 0x3a, 0x9f, 0x86, 0x5b, 0x3b, 0x31, 0x8e, 0x10, 0x0a, 0x15, 0x67,
+ 0x91, 0x57, 0x60, 0x63, 0x8f, 0x73, 0x59, 0x87, 0x9c, 0xf3, 0x9a,
+ 0x4c, 0x38, 0x8f, 0x8e, 0xee, 0x15, 0xfc, 0xb7, 0x36, 0xaa, 0x95,
+ 0x02, 0x9a, 0x9f, 0xeb, 0xe9, 0x56, 0x51, 0xe0, 0xa4, 0xd6, 0x9c,
+ 0x5c, 0x52, 0xcd, 0x03, 0x60, 0x4e, 0x79, 0xaa, 0xf7, 0xc7, 0xca,
+ 0x80, 0xd3, 0x21, 0xc0, 0xa0, 0xa1, 0x80, 0x50, 0xff, 0x49, 0xb4,
+ 0xed, 0x3e, 0x24, 0xba, 0x77, 0x1f, 0x12, 0x5d, 0x3b, 0xf6, 0xa0,
+ 0xe7, 0xb7, 0x2f, 0x89, 0x25, 0x87, 0x4e, 0x88, 0xf6, 0x20, 0x0e,
+ 0x17, 0x58, 0x60, 0xee, 0x96, 0x88, 0xa1, 0xb0, 0xa0, 0x9b, 0xc6,
+ 0x2f, 0x5a, 0x8b, 0xa3, 0x97, 0x9c, 0x4b, 0xc7, 0xd6, 0x2d, 0xa3,
+ 0xc1, 0xe5, 0x8b, 0x30, 0xb0, 0x7a, 0x29, 0x0d, 0xb0, 0x04, 0xb2,
+ 0x20, 0x98, 0x16, 0x05, 0xc6, 0x21, 0xaa, 0xbe, 0x0e, 0x72, 0x02,
+ 0x9a, 0xe9, 0x02, 0x2b, 0x37, 0x70, 0x39, 0xd5, 0x60, 0xba, 0xc1,
+ 0x4c, 0xb8, 0x00, 0x0d, 0x32, 0x40, 0xb3, 0xc2, 0x0c, 0x2e, 0x50,
+ 0xb3, 0xb6, 0x53, 0x23, 0x1b, 0x7c, 0xdc, 0x00, 0xe7, 0x04, 0x2b,
+ 0xdd, 0x25, 0x8f, 0x93, 0x02, 0x9c, 0xd9, 0x2e, 0x8e, 0xc0, 0x2a,
+ 0xa3, 0x85, 0x6a, 0x20, 0x10, 0x18, 0xd2, 0x88, 0x0e, 0x8d, 0x21,
+ 0xf9, 0xda, 0x7e, 0xd1, 0xbd, 0x7d, 0x97, 0x58, 0xb0, 0xe7, 0x30,
+ 0x3a, 0xf7, 0x1d, 0x15, 0x1d, 0xbb, 0x0e, 0x60, 0xde, 0xfe, 0xa3,
+ 0xa2, 0xd3, 0x30, 0x82, 0x9e, 0x75, 0x03, 0x9b, 0x5b, 0xd6, 0xd3,
+ 0x89, 0xf1, 0xb5, 0xcb, 0x69, 0x70, 0xe9, 0x39, 0x18, 0xe9, 0x5b,
+ 0x4c, 0x83, 0x6b, 0x97, 0xd1, 0xa9, 0x4b, 0xd6, 0xe3, 0xd8, 0xfc,
+ 0x79, 0x34, 0x1e, 0x6e, 0xc1, 0x24, 0x34, 0x98, 0x30, 0xcb, 0x8e,
+ 0x63, 0x11, 0x54, 0x9e, 0xe3, 0x36, 0xc8, 0x58, 0xa1, 0xe3, 0xa4,
+ 0xa8, 0x64, 0x61, 0xe7, 0x04, 0x30, 0x2b, 0xc4, 0x4c, 0x9b, 0x1a,
+ 0xf3, 0x85, 0x99, 0x17, 0xd0, 0xbc, 0x54, 0x1a, 0x3c, 0xa0, 0xe6,
+ 0x56, 0x71, 0xc0, 0x24, 0x21, 0xa7, 0x79, 0xc0, 0x4b, 0x43, 0x75,
+ 0x03, 0x5f, 0xa7, 0x63, 0x4c, 0x0f, 0xda, 0xa2, 0x81, 0xca, 0x90,
+ 0x03, 0x08, 0x0c, 0x06, 0xf4, 0xfc, 0x04, 0x62, 0x07, 0x8f, 0x89,
+ 0x8e, 0x63, 0xa7, 0xd0, 0xb6, 0x7d, 0x97, 0xe8, 0x79, 0x79, 0x97,
+ 0x38, 0xe7, 0xf0, 0x71, 0xb4, 0x9d, 0x18, 0x40, 0x6a, 0x60, 0x44,
+ 0x24, 0x86, 0xc7, 0x10, 0x7c, 0xb9, 0x17, 0xd8, 0xeb, 0x5a, 0x71,
+ 0xcd, 0x6b, 0xc7, 0x64, 0x77, 0x07, 0xa5, 0x17, 0xf5, 0x62, 0x6c,
+ 0xe5, 0x62, 0x1a, 0xbc, 0xec, 0x7c, 0x3a, 0xb2, 0x64, 0x01, 0x46,
+ 0x97, 0x2e, 0xa0, 0xa1, 0x8e, 0x79, 0x98, 0x40, 0x08, 0x45, 0x30,
+ 0x98, 0xe0, 0x10, 0x28, 0x80, 0xca, 0xe8, 0x10, 0x1e, 0x50, 0xb1,
+ 0xa7, 0x99, 0x2e, 0x90, 0xf3, 0x83, 0x95, 0x9b, 0x3b, 0xe9, 0x14,
+ 0x23, 0x93, 0xf9, 0xe4, 0xa9, 0xea, 0x63, 0x75, 0x19, 0xa0, 0xc9,
+ 0xb8, 0xa0, 0x32, 0xae, 0xa8, 0x17, 0xe0, 0x9c, 0x94, 0x97, 0xe6,
+ 0x01, 0x33, 0xcd, 0x65, 0xff, 0x4e, 0xc7, 0xa2, 0x19, 0xe9, 0x0c,
+ 0x34, 0x43, 0x0b, 0x0a, 0x68, 0x28, 0x22, 0x54, 0xcc, 0x20, 0x32,
+ 0x9a, 0x46, 0x7c, 0xff, 0x51, 0xd1, 0xf6, 0xda, 0x01, 0xd1, 0x73,
+ 0xa4, 0x1f, 0xad, 0x7b, 0x0e, 0xa2, 0x73, 0xc7, 0x1e, 0xd1, 0x3b,
+ 0x30, 0x22, 0x12, 0x23, 0xe3, 0x88, 0x4d, 0x66, 0x11, 0x9e, 0xcb,
+ 0x03, 0x26, 0x07, 0x76, 0x66, 0x58, 0x38, 0x04, 0xb3, 0xad, 0x05,
+ 0xd9, 0x8e, 0x56, 0xca, 0x2c, 0x3f, 0x07, 0x43, 0xe7, 0xad, 0xa2,
+ 0x53, 0x8b, 0x7a, 0x30, 0xd6, 0xb7, 0x90, 0x86, 0xd6, 0xad, 0xa0,
+ 0xfe, 0xce, 0x36, 0x4c, 0x26, 0x12, 0xc8, 0x21, 0x8c, 0x22, 0x74,
+ 0x18, 0xe0, 0xe5, 0x3a, 0xc7, 0x29, 0x7d, 0x24, 0x66, 0x40, 0xc3,
+ 0x0d, 0x26, 0x5e, 0x30, 0x73, 0x5b, 0x36, 0x5c, 0xb6, 0x35, 0x5d,
+ 0xd2, 0x38, 0xbc, 0xdb, 0x95, 0xf9, 0x7d, 0xee, 0x54, 0xf5, 0xdd,
+ 0xb9, 0x17, 0xd0, 0x64, 0xa0, 0x26, 0x1b, 0x5f, 0x73, 0xab, 0x1d,
+ 0x65, 0x92, 0x80, 0x92, 0xcd, 0xef, 0xb4, 0x6c, 0x3f, 0x7e, 0xf5,
+ 0xe0, 0xa5, 0x54, 0x76, 0x53, 0xa7, 0xab, 0x34, 0x04, 0x08, 0x0c,
+ 0x1c, 0x0c, 0x59, 0x44, 0x26, 0xd2, 0x88, 0x8d, 0xa7, 0x11, 0x1d,
+ 0x1c, 0x11, 0xc9, 0x53, 0xa3, 0x48, 0xec, 0x3d, 0x2c, 0xda, 0x77,
+ 0xec, 0xc1, 0xfc, 0xfe, 0x21, 0x91, 0xea, 0x1f, 0x42, 0x72, 0x78,
+ 0x0c, 0xf1, 0xd1, 0x09, 0x11, 0x1d, 0x9b, 0x40, 0x74, 0x32, 0xa8,
+ 0x79, 0x0d, 0xac, 0x0e, 0x0b, 0xe9, 0x30, 0x5b, 0x52, 0xc8, 0xb5,
+ 0xa7, 0x90, 0x6b, 0x6b, 0xa1, 0x6c, 0x77, 0x3b, 0x26, 0xbb, 0x3b,
+ 0x29, 0xbd, 0x7c, 0x21, 0x06, 0xcf, 0x5f, 0x49, 0xa7, 0xba, 0x3b,
+ 0x91, 0xee, 0x6a, 0xa7, 0x74, 0x47, 0x2b, 0x32, 0x2d, 0x09, 0xe4,
+ 0xf4, 0x04, 0xb2, 0x08, 0xc1, 0x80, 0x28, 0x63, 0xaa, 0x08, 0x4b,
+ 0x0f, 0x85, 0x55, 0xbd, 0x53, 0xcc, 0xec, 0xee, 0x0b, 0x15, 0x55,
+ 0xc6, 0x7d, 0xa0, 0xe6, 0x94, 0xdf, 0xf4, 0xc9, 0xcb, 0x15, 0x00,
+ 0xe6, 0x07, 0x31, 0xaf, 0x1e, 0x6b, 0x21, 0x13, 0x43, 0x73, 0x83,
+ 0x9a, 0x9f, 0x2b, 0xca, 0x7c, 0xe2, 0x6c, 0xcc, 0xa2, 0x98, 0xec,
+ 0xdf, 0x88, 0x92, 0x0f, 0xa0, 0xc8, 0x03, 0x56, 0x32, 0x13, 0xc1,
+ 0x79, 0x24, 0x66, 0xe6, 0x70, 0x7e, 0x33, 0x61, 0x37, 0xed, 0xc4,
+ 0x4e, 0x9f, 0x01, 0xc0, 0x60, 0x42, 0x83, 0x01, 0xcd, 0xcc, 0x23,
+ 0x9c, 0xce, 0x20, 0x92, 0xce, 0x20, 0xb2, 0xff, 0xa8, 0x68, 0x3b,
+ 0x72, 0x12, 0x1d, 0x03, 0xc3, 0x22, 0xd1, 0x3f, 0x82, 0xc4, 0xe1,
+ 0xe3, 0x68, 0xdd, 0x7f, 0x54, 0x74, 0x0e, 0x8f, 0x23, 0x3e, 0x31,
+ 0x29, 0x22, 0x13, 0x93, 0x88, 0xe4, 0xf2, 0xd0, 0x8b, 0x41, 0x0c,
+ 0x6f, 0x4e, 0x19, 0x63, 0x10, 0x91, 0x30, 0x8c, 0x44, 0x0c, 0xf9,
+ 0x96, 0x04, 0x0a, 0x2d, 0x09, 0xca, 0xcf, 0xef, 0xc6, 0xe8, 0xea,
+ 0xa5, 0x34, 0xdc, 0x53, 0x86, 0x54, 0x6f, 0x27, 0x26, 0x56, 0x2e,
+ 0xc6, 0x50, 0x47, 0x3b, 0x65, 0x92, 0x31, 0xe4, 0xa3, 0x31, 0xe4,
+ 0x11, 0x82, 0x01, 0x0d, 0x26, 0x58, 0x39, 0x24, 0x6f, 0x5a, 0x80,
+ 0x55, 0x2a, 0xfa, 0x4e, 0xe0, 0x72, 0xeb, 0xea, 0xcb, 0x9a, 0x66,
+ 0xba, 0xac, 0x93, 0x99, 0x64, 0x20, 0xe8, 0x04, 0x4e, 0xe1, 0x11,
+ 0xe8, 0xf7, 0x82, 0x99, 0x9b, 0x2a, 0x83, 0x4a, 0x0c, 0x4d, 0x05,
+ 0x6c, 0x4e, 0x90, 0x73, 0x82, 0x9b, 0x5b, 0xcc, 0x8d, 0x5c, 0xe0,
+ 0xc3, 0x7c, 0xe2, 0x73, 0xcc, 0x67, 0x3f, 0x4c, 0x11, 0x60, 0x4e,
+ 0xf3, 0x4e, 0xbf, 0xd3, 0xf3, 0xd3, 0x7f, 0x28, 0xbb, 0xb3, 0x62,
+ 0xc6, 0x1a, 0x13, 0x0c, 0x05, 0x84, 0x8a, 0x39, 0x84, 0x33, 0xe5,
+ 0x69, 0x3c, 0x2d, 0x22, 0xe3, 0x69, 0xc4, 0x46, 0xd3, 0x88, 0x0e,
+ 0x8e, 0x20, 0xbe, 0xe7, 0xb0, 0x68, 0xeb, 0x1f, 0x44, 0xdb, 0xc8,
+ 0x04, 0x62, 0xe3, 0x69, 0x11, 0x19, 0x4d, 0x23, 0x3a, 0x32, 0x8a,
+ 0x58, 0xff, 0xb0, 0x48, 0x4c, 0x66, 0x11, 0x2d, 0x14, 0xa1, 0x71,
+ 0x1e, 0xb8, 0xba, 0x67, 0xa2, 0x9a, 0x8a, 0x46, 0x50, 0xec, 0x68,
+ 0xc5, 0x64, 0x6f, 0x27, 0x65, 0x92, 0x09, 0xe4, 0x3a, 0x52, 0xc8,
+ 0xa7, 0x92, 0x94, 0xed, 0x6a, 0xc7, 0xe4, 0xd2, 0x73, 0x30, 0xbc,
+ 0xa8, 0x97, 0x26, 0x5a, 0x93, 0xc8, 0xb7, 0x24, 0x91, 0x6d, 0x4f,
+ 0x51, 0x36, 0x1e, 0x45, 0x21, 0x1e, 0x43, 0x31, 0x16, 0x45, 0x1e,
+ 0x11, 0x14, 0xcb, 0x63, 0x50, 0x8a, 0x8a, 0xc2, 0x32, 0x40, 0x15,
+ 0x50, 0xf1, 0x72, 0x30, 0x5c, 0xb8, 0x16, 0x78, 0x2f, 0x80, 0xc9,
+ 0x40, 0xce, 0x4d, 0xa1, 0x09, 0x9f, 0x65, 0x3f, 0xa5, 0xc5, 0xe1,
+ 0x5d, 0x43, 0x29, 0x5c, 0x80, 0x56, 0x33, 0xc8, 0x6a, 0x01, 0x9a,
+ 0x8c, 0x1b, 0x6a, 0x77, 0x41, 0x9d, 0x54, 0x9b, 0xdb, 0x68, 0xc8,
+ 0xf6, 0x5f, 0xcd, 0x53, 0x39, 0x79, 0x2f, 0x93, 0x4f, 0x1e, 0x92,
+ 0x04, 0x98, 0x1f, 0xd4, 0xbc, 0x46, 0x76, 0x9e, 0x9e, 0xb7, 0x02,
+ 0x6f, 0x7a, 0x2d, 0xcd, 0xd8, 0xa3, 0x00, 0x81, 0x43, 0x03, 0x2f,
+ 0xb9, 0xba, 0x66, 0x16, 0xa1, 0x91, 0x09, 0xc4, 0x26, 0x33, 0x88,
+ 0x8c, 0x4d, 0x8a, 0x48, 0x36, 0x87, 0xf0, 0x78, 0x49, 0xdd, 0x85,
+ 0xc7, 0x26, 0x10, 0x99, 0xc8, 0x88, 0xc8, 0x64, 0x16, 0x91, 0xb1,
+ 0x09, 0x84, 0x73, 0x05, 0x44, 0x4e, 0x0e, 0x88, 0xd8, 0x89, 0x21,
+ 0x24, 0x26, 0x26, 0x91, 0xc8, 0x64, 0xa1, 0xe7, 0x8b, 0xd0, 0x0d,
+ 0x03, 0x7a, 0x26, 0x27, 0xb4, 0x7c, 0x11, 0x9a, 0x61, 0x40, 0xcf,
+ 0x17, 0xa0, 0xcd, 0x75, 0x65, 0x48, 0x04, 0x1e, 0x8b, 0xc0, 0xd4,
+ 0x75, 0x98, 0x61, 0x1d, 0x66, 0x2c, 0x4a, 0x46, 0x38, 0x04, 0x33,
+ 0x1c, 0x82, 0x11, 0x8b, 0xc0, 0x48, 0xc4, 0x91, 0xeb, 0x6c, 0x45,
+ 0x7a, 0x61, 0x0f, 0x65, 0x92, 0x09, 0xe4, 0x53, 0x31, 0xe4, 0x5b,
+ 0x52, 0x28, 0xc4, 0x23, 0x94, 0x6f, 0x4b, 0x21, 0x1f, 0x8b, 0x21,
+ 0x9f, 0x8a, 0xa1, 0x90, 0x88, 0xa3, 0x90, 0x8c, 0x21, 0x9f, 0x4a,
+ 0x50, 0x3e, 0x95, 0x40, 0x36, 0x91, 0x42, 0xbe, 0x7c, 0xf7, 0xcc,
+ 0x72, 0xb0, 0x82, 0x5b, 0x8a, 0xab, 0x70, 0x68, 0x0e, 0x2a, 0x2c,
+ 0xea, 0x4a, 0x78, 0xa8, 0x14, 0xee, 0x31, 0xef, 0xb4, 0xce, 0x0d,
+ 0x6a, 0x7e, 0xeb, 0x4c, 0x87, 0x7d, 0xfb, 0xa9, 0x3d, 0xbf, 0xbc,
+ 0x6e, 0xc7, 0x84, 0xa2, 0x1a, 0x93, 0x82, 0x59, 0xad, 0x40, 0x73,
+ 0x52, 0x6b, 0x7e, 0xb1, 0x35, 0xaf, 0x8a, 0x04, 0x15, 0x90, 0xf8,
+ 0x29, 0x27, 0x59, 0x70, 0x11, 0x54, 0x54, 0x98, 0xf7, 0x70, 0xf4,
+ 0x5e, 0x69, 0xb0, 0x1c, 0xd7, 0xef, 0x1a, 0x4c, 0xc3, 0x0f, 0x15,
+ 0x00, 0xda, 0x8f, 0x3c, 0x55, 0x25, 0x31, 0x95, 0x0f, 0x95, 0x5f,
+ 0xb3, 0xec, 0x02, 0x9b, 0xd0, 0x78, 0x09, 0x5c, 0xba, 0x69, 0x82,
+ 0xe5, 0x8b, 0xe5, 0x79, 0x0e, 0x36, 0x9e, 0x16, 0xe1, 0xe1, 0x31,
+ 0x44, 0xd2, 0x19, 0x44, 0xf3, 0x05, 0x84, 0x27, 0xb3, 0x08, 0x65,
+ 0x72, 0x08, 0x15, 0x0d, 0xa1, 0x15, 0xcb, 0xc0, 0xcb, 0xe4, 0xa0,
+ 0x17, 0x8a, 0xd3, 0xdb, 0x9b, 0x1c, 0x5a, 0x26, 0x07, 0xcd, 0x30,
+ 0xc1, 0x8a, 0x45, 0x30, 0xd3, 0x84, 0x66, 0x72, 0x41, 0x9c, 0x43,
+ 0xe3, 0x02, 0xc4, 0x39, 0x28, 0x93, 0xab, 0x40, 0x92, 0x0a, 0x45,
+ 0x30, 0x93, 0x83, 0x91, 0xf5, 0xa1, 0x23, 0xc0, 0x30, 0xca, 0x2a,
+ 0x93, 0xa6, 0xd5, 0x0d, 0xd9, 0x1e, 0x4c, 0x51, 0x0a, 0x78, 0x73,
+ 0x8d, 0x81, 0x0b, 0x01, 0x8a, 0x84, 0x61, 0x86, 0x43, 0xa5, 0x07,
+ 0x5f, 0xd7, 0xc0, 0x89, 0x20, 0x74, 0x8d, 0x4c, 0x4d, 0x83, 0x28,
+ 0xab, 0x23, 0x33, 0xa4, 0x83, 0xeb, 0x1a, 0x4c, 0x5d, 0x83, 0x19,
+ 0xd2, 0x61, 0xc4, 0xa2, 0x30, 0xe3, 0x51, 0x18, 0xa5, 0x65, 0x32,
+ 0xca, 0x6e, 0x9e, 0x11, 0x8b, 0xa2, 0x10, 0x8b, 0x20, 0xd7, 0x96,
+ 0x42, 0x7e, 0x5e, 0x1b, 0xe5, 0x74, 0x1d, 0xa6, 0xa6, 0x81, 0x47,
+ 0x42, 0x30, 0x43, 0x3a, 0x4c, 0x5d, 0x87, 0xa1, 0x87, 0x60, 0x42,
+ 0x2f, 0x5f, 0xc9, 0x50, 0xe5, 0xb3, 0x76, 0x61, 0x29, 0x56, 0xc2,
+ 0x02, 0x23, 0xaa, 0x68, 0x27, 0x5e, 0x56, 0x55, 0x70, 0x04, 0x94,
+ 0xb5, 0xf0, 0xc2, 0x47, 0x91, 0x78, 0xb9, 0x5e, 0x6e, 0xa0, 0x93,
+ 0x81, 0x9c, 0x4c, 0x7e, 0xd3, 0x07, 0x42, 0xdc, 0x63, 0x5b, 0x2e,
+ 0x09, 0x60, 0xeb, 0x35, 0x00, 0xe4, 0x47, 0x74, 0x92, 0x82, 0x59,
+ 0x3d, 0x40, 0xf3, 0x73, 0x43, 0xfd, 0x62, 0x6d, 0x7e, 0x60, 0x93,
+ 0x55, 0x3f, 0xf5, 0xa4, 0xc9, 0xaa, 0x2e, 0xb7, 0xed, 0xa0, 0x00,
+ 0xb7, 0x5a, 0x26, 0x48, 0xa4, 0xc1, 0x06, 0x43, 0xd8, 0x70, 0x87,
+ 0xaa, 0x34, 0x0d, 0x02, 0x04, 0x61, 0x5b, 0x4f, 0x96, 0xbb, 0x46,
+ 0x0e, 0x8f, 0x10, 0xb3, 0x3c, 0x72, 0xa5, 0x63, 0x09, 0xcb, 0x76,
+ 0xbc, 0x72, 0x0e, 0x02, 0xc2, 0xf1, 0x99, 0x10, 0x96, 0x6d, 0xac,
+ 0xc7, 0x15, 0x2e, 0x4f, 0xd4, 0xd4, 0xde, 0xad, 0xe7, 0x69, 0x3d,
+ 0x03, 0xeb, 0x59, 0x54, 0xbf, 0xbd, 0x85, 0xc3, 0xbc, 0xa8, 0xa8,
+ 0xe0, 0xea, 0xe2, 0x64, 0x45, 0xd1, 0xcc, 0x2d, 0xdd, 0x7a, 0x6c,
+ 0x86, 0xcf, 0xb2, 0x9b, 0xf2, 0xe0, 0x1e, 0xcb, 0x32, 0x70, 0xf3,
+ 0x52, 0x37, 0xdc, 0x07, 0x86, 0xb2, 0x40, 0x14, 0x35, 0x82, 0x4a,
+ 0x48, 0xfe, 0x3f, 0x6e, 0x00, 0x13, 0xb5, 0x42, 0xcc, 0x6a, 0xf5,
+ 0x76, 0xe4, 0x2e, 0x1c, 0x1e, 0x5c, 0xaf, 0xbc, 0x34, 0xe3, 0x01,
+ 0xaf, 0x2e, 0x98, 0x5c, 0x01, 0x76, 0x5e, 0x40, 0xf2, 0x03, 0x24,
+ 0x53, 0x38, 0x06, 0x49, 0x6e, 0x03, 0x49, 0x98, 0xc1, 0x01, 0x8a,
+ 0xa8, 0x01, 0x68, 0xd5, 0xf3, 0xa2, 0x82, 0x03, 0xaf, 0xd1, 0xee,
+ 0xdd, 0xd2, 0xdd, 0x42, 0x08, 0xfe, 0x2f, 0x2f, 0x92, 0x56, 0xf1,
+ 0x2a, 0xcf, 0x93, 0x3d, 0x45, 0xf8, 0x6c, 0xe3, 0xf6, 0x66, 0xf7,
+ 0x6a, 0xbb, 0xe4, 0x35, 0xe0, 0x86, 0x2c, 0xd0, 0x20, 0x51, 0x60,
+ 0x1b, 0x35, 0xf9, 0xb9, 0x6b, 0x2a, 0xca, 0xce, 0x6f, 0x9d, 0x90,
+ 0x3c, 0x0e, 0x57, 0x84, 0x3a, 0xe0, 0xd3, 0xeb, 0x6c, 0x2d, 0x20,
+ 0x6b, 0x14, 0xd0, 0x9c, 0x0e, 0x4e, 0x0e, 0x0f, 0x10, 0x39, 0xcc,
+ 0xab, 0x28, 0x37, 0x2a, 0x4b, 0x62, 0x27, 0x80, 0xa0, 0x06, 0x40,
+ 0xd9, 0x21, 0xa2, 0xba, 0x3d, 0x24, 0xd7, 0xc9, 0xb9, 0x99, 0xb5,
+ 0xc0, 0xcb, 0xbf, 0x52, 0xc6, 0xed, 0x1a, 0x7b, 0x81, 0x8b, 0x3c,
+ 0x94, 0xb6, 0x3b, 0xa8, 0x9a, 0xd7, 0x36, 0x4f, 0xd4, 0x90, 0x26,
+ 0x24, 0xa1, 0x06, 0x05, 0xc0, 0xf9, 0x15, 0x4a, 0x59, 0xd5, 0xd6,
+ 0x0c, 0xc8, 0x09, 0x49, 0x08, 0xd5, 0x02, 0x3f, 0x95, 0xc9, 0xcf,
+ 0x95, 0x94, 0x89, 0x8d, 0xd5, 0x04, 0xb1, 0x66, 0x01, 0x0d, 0x0e,
+ 0xd0, 0xf2, 0x7b, 0x08, 0xad, 0xaa, 0x8e, 0xd9, 0xa0, 0xe8, 0x54,
+ 0x50, 0x99, 0xe5, 0xa2, 0xa9, 0xaa, 0x20, 0xbf, 0xfc, 0x4c, 0x01,
+ 0x40, 0xf5, 0xb8, 0x8d, 0xb2, 0x31, 0xc6, 0x7a, 0x20, 0x26, 0xdb,
+ 0x7e, 0x50, 0x16, 0x70, 0xb2, 0xaa, 0x0d, 0x67, 0x08, 0xd8, 0xbc,
+ 0xd4, 0x9a, 0x0c, 0xe8, 0xbc, 0x54, 0x18, 0x5c, 0x0a, 0xb0, 0x5f,
+ 0x41, 0x56, 0x85, 0x9b, 0x1b, 0x20, 0x4e, 0xd7, 0x04, 0x0f, 0x35,
+ 0x26, 0xe3, 0x3e, 0x0a, 0x09, 0x60, 0xd5, 0xdd, 0x73, 0xa6, 0x3e,
+ 0x4b, 0x0f, 0x20, 0x49, 0x9c, 0x34, 0x97, 0x28, 0x84, 0x5c, 0x52,
+ 0xd1, 0x01, 0xf5, 0xa9, 0x22, 0x26, 0xb1, 0x7f, 0x26, 0x09, 0x2c,
+ 0x28, 0xc2, 0x0c, 0xa8, 0x4f, 0x89, 0xd5, 0x03, 0x31, 0x3f, 0x35,
+ 0x46, 0x0a, 0x95, 0x44, 0xcd, 0x02, 0x99, 0x4c, 0xad, 0x97, 0xac,
+ 0xfb, 0xa9, 0x0a, 0x39, 0x15, 0xe0, 0xd5, 0xa2, 0xda, 0x20, 0x09,
+ 0x34, 0x48, 0xba, 0x7a, 0xb0, 0xb9, 0xa9, 0xa8, 0x11, 0xac, 0x7e,
+ 0x0a, 0x0c, 0xf0, 0x6e, 0xf8, 0xda, 0x14, 0x35, 0x36, 0x9b, 0x40,
+ 0x93, 0x05, 0x9c, 0x70, 0x51, 0x76, 0x76, 0xf5, 0xe6, 0x57, 0xa8,
+ 0x65, 0xd6, 0xcb, 0x42, 0x05, 0x0a, 0x10, 0x83, 0xc7, 0x7a, 0x2f,
+ 0x60, 0xfa, 0x41, 0xcc, 0x69, 0xbd, 0xdf, 0x75, 0x68, 0x96, 0x1a,
+ 0x23, 0xc7, 0x00, 0x7f, 0x73, 0xa0, 0x26, 0x7c, 0x62, 0xb1, 0x4e,
+ 0xeb, 0x55, 0x6a, 0xc5, 0x64, 0x5c, 0x1f, 0x59, 0xf7, 0xb3, 0x56,
+ 0xe8, 0x01, 0xf2, 0xf1, 0x38, 0x59, 0x00, 0xd5, 0x53, 0x71, 0xa1,
+ 0x72, 0x8e, 0xb5, 0x5c, 0xbb, 0xa6, 0x43, 0xec, 0x74, 0x00, 0xcd,
+ 0xaf, 0x32, 0x01, 0x0a, 0x80, 0x53, 0xa9, 0x49, 0xad, 0x25, 0x4d,
+ 0x56, 0x61, 0xa9, 0xc6, 0xb8, 0x64, 0xcf, 0xa1, 0x96, 0x3c, 0x50,
+ 0x58, 0x27, 0x0b, 0xb5, 0x5a, 0xdc, 0x4c, 0x6a, 0xf0, 0xb3, 0x51,
+ 0xab, 0x6a, 0x93, 0x55, 0x70, 0x2a, 0x40, 0x83, 0x42, 0x01, 0xf7,
+ 0xfd, 0x88, 0x5a, 0x41, 0xdd, 0xa9, 0xe6, 0x57, 0x55, 0x92, 0x2a,
+ 0xe7, 0xec, 0x05, 0x2d, 0x71, 0x3a, 0x00, 0x76, 0xa6, 0x00, 0xcd,
+ 0xef, 0x1f, 0x26, 0x8f, 0x87, 0x4a, 0xb6, 0x90, 0xd6, 0xd2, 0x84,
+ 0x64, 0xb6, 0x40, 0xe9, 0x74, 0x7e, 0x8d, 0x70, 0x23, 0x6b, 0x55,
+ 0x65, 0x2a, 0xae, 0xe4, 0x99, 0x08, 0x34, 0x51, 0x07, 0xe0, 0xbc,
+ 0x0a, 0x68, 0x3d, 0xea, 0x4e, 0xa5, 0x22, 0xa2, 0x56, 0xb7, 0xb6,
+ 0x5e, 0xc8, 0xca, 0xfe, 0x3f, 0x2a, 0x0a, 0x6c, 0xd6, 0x21, 0x76,
+ 0xa6, 0x01, 0xad, 0x51, 0x90, 0x73, 0x72, 0x47, 0x48, 0xa1, 0xa0,
+ 0xab, 0xb8, 0x6e, 0x8d, 0xac, 0x61, 0xac, 0x57, 0x71, 0xa9, 0xb4,
+ 0x05, 0x54, 0x75, 0x31, 0x67, 0x13, 0x64, 0x8d, 0x80, 0x9b, 0x0a,
+ 0xd8, 0x54, 0x0b, 0xae, 0x6a, 0x4d, 0xaa, 0xac, 0xda, 0x51, 0x01,
+ 0x4d, 0x23, 0x9a, 0xa3, 0xf8, 0x01, 0x5b, 0x15, 0x5e, 0xa7, 0x15,
+ 0x60, 0xaf, 0x17, 0xa0, 0xa9, 0xb8, 0xa9, 0x4e, 0x17, 0x9f, 0x5c,
+ 0x80, 0xa7, 0x12, 0x2b, 0x52, 0x85, 0x4c, 0xad, 0x79, 0x20, 0x19,
+ 0x17, 0x53, 0xd9, 0x0f, 0x14, 0xf3, 0x9d, 0x2e, 0x35, 0xd6, 0x48,
+ 0xc0, 0xc9, 0x28, 0x37, 0x55, 0xa0, 0xa9, 0xce, 0xd7, 0x0a, 0x42,
+ 0x15, 0x08, 0xaa, 0xba, 0xcc, 0xb2, 0xff, 0xdb, 0x19, 0xad, 0xbc,
+ 0xce, 0x46, 0xa0, 0xd5, 0x73, 0x61, 0x9d, 0xc0, 0xa6, 0x52, 0xc8,
+ 0xeb, 0x89, 0x45, 0xd5, 0x52, 0xc3, 0x28, 0x0b, 0x3e, 0x48, 0xba,
+ 0x90, 0xe4, 0xa2, 0x74, 0xfd, 0x3e, 0x61, 0xf3, 0x7b, 0x21, 0x34,
+ 0x0b, 0x72, 0xc2, 0x63, 0xff, 0x4e, 0x71, 0x56, 0x21, 0xb1, 0xad,
+ 0xf0, 0x51, 0xf9, 0xb5, 0xc6, 0xe1, 0xea, 0x55, 0x74, 0xaa, 0xdb,
+ 0xa9, 0xee, 0xaf, 0x16, 0x25, 0xfb, 0xba, 0x35, 0x1d, 0x67, 0xa7,
+ 0x09, 0xc5, 0x7c, 0xe4, 0xa2, 0x02, 0x65, 0xe1, 0xa7, 0x0a, 0x34,
+ 0x81, 0xe9, 0x1a, 0xd1, 0x7a, 0xd5, 0x94, 0x5a, 0xab, 0xfe, 0xfa,
+ 0xd2, 0x55, 0xd4, 0x9b, 0x6a, 0x01, 0x91, 0xdd, 0x46, 0xf8, 0xe4,
+ 0x57, 0x09, 0x4e, 0xab, 0xaa, 0x3a, 0x55, 0xd7, 0xcc, 0x2f, 0x2e,
+ 0xd7, 0x08, 0xb7, 0xb8, 0x51, 0x69, 0x67, 0x85, 0x9d, 0xad, 0x40,
+ 0x6b, 0x84, 0xb2, 0x13, 0x0d, 0x72, 0xd1, 0xdc, 0xd2, 0xb8, 0x02,
+ 0x50, 0x54, 0xa0, 0xe5, 0xd5, 0xb4, 0xc2, 0x0d, 0x88, 0x02, 0xcd,
+ 0x6b, 0x63, 0x46, 0x0d, 0xbc, 0x27, 0x2a, 0xdb, 0x0b, 0x45, 0xe8,
+ 0xd9, 0x41, 0x59, 0x0b, 0xec, 0x6a, 0x05, 0x22, 0x35, 0x70, 0xbb,
+ 0xd7, 0xa5, 0xab, 0x18, 0x00, 0xed, 0xf4, 0xba, 0xb0, 0x6e, 0x0f,
+ 0x94, 0x4a, 0x1c, 0xaa, 0x19, 0x79, 0x9b, 0x11, 0xd0, 0xa7, 0xd7,
+ 0xf9, 0x7d, 0x13, 0x0d, 0x5c, 0x57, 0x6b, 0x43, 0x5f, 0x55, 0xe5,
+ 0xa8, 0x0a, 0x65, 0x3f, 0xd5, 0x3a, 0x67, 0x2c, 0x00, 0x5a, 0x7d,
+ 0x85, 0x47, 0xc0, 0xff, 0x2b, 0x08, 0x99, 0x36, 0x77, 0x2a, 0x0f,
+ 0x63, 0x33, 0x82, 0xf7, 0xaa, 0xd0, 0xa2, 0x33, 0xec, 0x3e, 0x9c,
+ 0x0e, 0xe0, 0xd5, 0x0a, 0x29, 0xd5, 0xff, 0x81, 0x2b, 0xec, 0x47,
+ 0xcc, 0xf5, 0x42, 0x1a, 0x00, 0xed, 0xf4, 0x14, 0x30, 0x92, 0xdc,
+ 0x0f, 0x29, 0x1e, 0x4f, 0x05, 0x34, 0xcd, 0x00, 0xdd, 0x99, 0x7e,
+ 0x0f, 0x1a, 0x99, 0xcf, 0xad, 0x92, 0x21, 0x70, 0xfd, 0x02, 0xa0,
+ 0x05, 0x10, 0x54, 0xc8, 0x47, 0x0d, 0x2a, 0x30, 0x14, 0x5c, 0xf7,
+ 0xba, 0xf7, 0x11, 0x00, 0xea, 0x0c, 0xb3, 0xff, 0x3f, 0x00, 0x33,
+ 0x7e, 0xb5, 0x01, 0x3c, 0x57, 0x93, 0xe4, 0x00, 0x00, 0x00, 0x00,
+ 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
+};
+
+unsigned int nxlogo_png_size = sizeof(nxlogo_png);
+