summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addons/BSD/nxd_bsd.c220
-rw-r--r--addons/BSD/nxd_bsd.h6
-rw-r--r--addons/CMakeLists.txt4
-rw-r--r--addons/azure_iot/samples/sample_azure_iot_embedded_sdk.c6
-rw-r--r--addons/azure_iot/samples/sample_azure_iot_embedded_sdk_pnp.c6
-rw-r--r--addons/dhcp/nxd_dhcp_client.c12
-rw-r--r--addons/dhcp/nxd_dhcp_server.c25
-rw-r--r--addons/dhcp/nxd_dhcpv6_server.c84
-rw-r--r--addons/dns/nxd_dns.c9
-rw-r--r--addons/ftp/nxd_ftp_client.c14
-rw-r--r--addons/ftp/nxd_ftp_server.c3904
-rw-r--r--addons/mdns/nxd_mdns.h6
-rw-r--r--addons/mqtt/nxd_mqtt_client.c48
-rw-r--r--addons/mqtt/nxd_mqtt_client.h6
-rw-r--r--addons/nat/nx_nat.c25
-rw-r--r--addons/ppp/nx_ppp.c24
-rw-r--r--addons/ppp/nx_ppp.h6
-rw-r--r--addons/rtp/nx_rtp_sender.c3981
-rw-r--r--addons/rtp/nx_rtp_sender.h495
-rw-r--r--addons/rtsp/nx_rtsp_server.c4854
-rw-r--r--addons/rtsp/nx_rtsp_server.h535
-rw-r--r--addons/smtp/nxd_smtp_client.c6
-rw-r--r--addons/snmp/nxd_snmp.c1463
-rw-r--r--addons/snmp/nxd_snmp.h11
-rw-r--r--addons/sntp/nxd_sntp_client.c17
-rw-r--r--common/inc/nx_api.h10
-rw-r--r--common/inc/nx_icmpv6.h22
-rw-r--r--common/inc/nx_user_sample.h6
-rw-r--r--common/src/nx_icmpv6_packet_process.c18
-rw-r--r--common/src/nx_icmpv6_process_na.c32
-rw-r--r--common/src/nx_icmpv6_process_ns.c25
-rw-r--r--common/src/nx_icmpv6_process_packet_too_big.c13
-rw-r--r--common/src/nx_icmpv6_process_ra.c25
-rw-r--r--common/src/nx_icmpv6_process_redirect.c11
-rw-r--r--common/src/nx_igmp_packet_process.c121
-rw-r--r--common/src/nx_ip_create.c6
-rw-r--r--common/src/nx_ip_header_add.c6
-rw-r--r--common/src/nx_ipv4_packet_receive.c21
-rw-r--r--common/src/nx_ipv6_fragment_process.c6
-rw-r--r--common/src/nx_tcp_free_port_find.c11
-rw-r--r--common/src/nx_tcp_packet_process.c25
-rw-r--r--common/src/nx_tcp_socket_state_data_check.c10
-rw-r--r--common/src/nx_udp_free_port_find.c11
-rw-r--r--crypto_libraries/src/nx_crypto_3des.c12
-rw-r--r--crypto_libraries/src/nx_crypto_aes.c42
-rw-r--r--crypto_libraries/src/nx_crypto_des.c12
-rw-r--r--crypto_libraries/src/nx_crypto_drbg.c12
-rw-r--r--crypto_libraries/src/nx_crypto_ecdh.c12
-rw-r--r--crypto_libraries/src/nx_crypto_ecdsa.c12
-rw-r--r--crypto_libraries/src/nx_crypto_ecjpake.c12
-rw-r--r--crypto_libraries/src/nx_crypto_hkdf.c12
-rw-r--r--crypto_libraries/src/nx_crypto_hmac.c12
-rw-r--r--crypto_libraries/src/nx_crypto_hmac_md5.c12
-rw-r--r--crypto_libraries/src/nx_crypto_hmac_sha1.c12
-rw-r--r--crypto_libraries/src/nx_crypto_hmac_sha2.c12
-rw-r--r--crypto_libraries/src/nx_crypto_hmac_sha5.c12
-rw-r--r--crypto_libraries/src/nx_crypto_md5.c6
-rw-r--r--crypto_libraries/src/nx_crypto_pkcs1_v1.5.c12
-rw-r--r--crypto_libraries/src/nx_crypto_rsa.c12
-rw-r--r--crypto_libraries/src/nx_crypto_sha1.c6
-rw-r--r--crypto_libraries/src/nx_crypto_sha2.c12
-rw-r--r--crypto_libraries/src/nx_crypto_sha5.c12
-rw-r--r--crypto_libraries/src/nx_crypto_tls_prf_1.c12
-rw-r--r--crypto_libraries/src/nx_crypto_tls_prf_sha256.c12
-rw-r--r--crypto_libraries/src/nx_crypto_tls_prf_sha384.c12
-rw-r--r--crypto_libraries/src/nx_crypto_tls_prf_sha512.c12
-rw-r--r--nx_secure/inc/nx_secure_tls.h7
-rw-r--r--nx_secure/ports/nx_secure_port.h2
-rw-r--r--nx_secure/src/nx_secure_dtls_send_record.c7
-rw-r--r--nx_secure/src/nx_secure_dtls_server_handshake.c8
-rw-r--r--nx_secure/src/nx_secure_dtls_session_end.c27
-rw-r--r--nx_secure/src/nx_secure_dtls_session_receive.c12
-rw-r--r--nx_secure/src/nx_secure_tls_send_certificate.c6
-rw-r--r--nx_secure/src/nxe_secure_tls_session_send.c6
-rw-r--r--ports/arc_em/metaware/inc/nx_port.h2
-rw-r--r--ports/arc_hs/metaware/inc/nx_port.h2
-rw-r--r--ports/cortex_a15/gnu/inc/nx_port.h2
-rw-r--r--ports/cortex_a5/ac5/inc/nx_port.h2
-rw-r--r--ports/cortex_a5/gnu/inc/nx_port.h2
-rw-r--r--ports/cortex_a5/iar/inc/nx_port.h2
-rw-r--r--ports/cortex_a5x/ac6/inc/nx_port.h2
-rw-r--r--ports/cortex_a7/ac5/inc/nx_port.h2
-rw-r--r--ports/cortex_a7/gnu/inc/nx_port.h2
-rw-r--r--ports/cortex_a7/iar/inc/nx_port.h2
-rw-r--r--ports/cortex_a8/ac5/inc/nx_port.h2
-rw-r--r--ports/cortex_a8/gnu/inc/nx_port.h2
-rw-r--r--ports/cortex_a8/iar/inc/nx_port.h2
-rw-r--r--ports/cortex_a9/ac5/inc/nx_port.h2
-rw-r--r--ports/cortex_a9/gnu/inc/nx_port.h2
-rw-r--r--ports/cortex_a9/iar/inc/nx_port.h2
-rw-r--r--ports/cortex_a9/rvds/inc/nx_port.h2
-rw-r--r--ports/cortex_m0/ac5/inc/nx_port.h2
-rw-r--r--ports/cortex_m0/gnu/inc/nx_port.h2
-rw-r--r--ports/cortex_m0/iar/inc/nx_port.h2
-rw-r--r--ports/cortex_m23/ac5/inc/nx_port.h2
-rw-r--r--ports/cortex_m23/gnu/inc/nx_port.h2
-rw-r--r--ports/cortex_m23/iar/inc/nx_port.h2
-rw-r--r--ports/cortex_m3/ac5/inc/nx_port.h2
-rw-r--r--ports/cortex_m3/gnu/inc/nx_port.h2
-rw-r--r--ports/cortex_m3/iar/inc/nx_port.h2
-rw-r--r--ports/cortex_m3/keil/inc/nx_port.h2
-rw-r--r--ports/cortex_m33/ac5/inc/nx_port.h2
-rw-r--r--ports/cortex_m33/ac6/inc/nx_port.h2
-rw-r--r--ports/cortex_m33/gnu/inc/nx_port.h2
-rw-r--r--ports/cortex_m33/iar/inc/nx_port.h2
-rw-r--r--ports/cortex_m4/ac5/inc/nx_port.h2
-rw-r--r--ports/cortex_m4/gnu/inc/nx_port.h2
-rw-r--r--ports/cortex_m4/iar/inc/nx_port.h2
-rw-r--r--ports/cortex_m4/keil/inc/nx_port.h2
-rw-r--r--ports/cortex_m55/ac5/inc/nx_port.h2
-rw-r--r--ports/cortex_m55/ac6/inc/nx_port.h2
-rw-r--r--ports/cortex_m55/gnu/inc/nx_port.h2
-rw-r--r--ports/cortex_m55/iar/inc/nx_port.h2
-rw-r--r--ports/cortex_m7/ac5/inc/nx_port.h2
-rw-r--r--ports/cortex_m7/ac6/inc/nx_port.h2
-rw-r--r--ports/cortex_m7/gnu/inc/nx_port.h2
-rw-r--r--ports/cortex_m7/iar/inc/nx_port.h2
-rw-r--r--ports/cortex_m85/ac5/inc/nx_port.h2
-rw-r--r--ports/cortex_m85/ac6/inc/nx_port.h2
-rw-r--r--ports/cortex_m85/gnu/inc/nx_port.h2
-rw-r--r--ports/cortex_m85/iar/inc/nx_port.h2
-rw-r--r--ports/cortex_r4/ac5/inc/nx_port.h2
-rw-r--r--ports/cortex_r4/ac6/inc/nx_port.h2
-rw-r--r--ports/cortex_r4/gnu/inc/nx_port.h2
-rw-r--r--ports/cortex_r4/iar/inc/nx_port.h2
-rw-r--r--ports/cortex_r5/ac5/inc/nx_port.h2
-rw-r--r--ports/cortex_r5/gnu/inc/nx_port.h2
-rw-r--r--ports/cortex_r5/iar/inc/nx_port.h2
-rw-r--r--ports/linux/gnu/inc/nx_port.h2
-rw-r--r--ports/mips/gnu/inc/nx_port.h2
-rw-r--r--ports/rxv2/ccrx/inc/nx_port.h2
-rw-r--r--ports/rxv2/gnu/inc/nx_port.h2
-rw-r--r--ports/rxv2/iar/inc/nx_port.h2
-rw-r--r--ports/win32/vs_2019/inc/nx_port.h2
-rw-r--r--samples/demo_rtsp_over_rtp.c956
-rw-r--r--samples/demo_rtsp_over_rtp.h95
-rw-r--r--samples/main.c (renamed from addons/azure_iot/samples/main.c)4
-rw-r--r--utility/iperf/nx_iperf.c16
138 files changed, 13954 insertions, 3752 deletions
diff --git a/addons/BSD/nxd_bsd.c b/addons/BSD/nxd_bsd.c
index 168b5689..22adff5e 100644
--- a/addons/BSD/nxd_bsd.c
+++ b/addons/BSD/nxd_bsd.c
@@ -205,7 +205,7 @@ static struct NX_BSD_SERVICE_LIST *_nx_bsd_serv_list_ptr;
/* FUNCTION RELEASE */
/* */
/* bsd_initialize PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -255,9 +255,9 @@ static struct NX_BSD_SERVICE_LIST *_nx_bsd_serv_list_ptr;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_initialize(NX_IP *default_ip, NX_PACKET_POOL *default_pool, CHAR *bsd_thread_stack_area,
@@ -667,7 +667,7 @@ VOID nx_bsd_thread_entry(ULONG info)
/* FUNCTION RELEASE */
/* */
/* socket PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -712,9 +712,9 @@ VOID nx_bsd_thread_entry(ULONG info)
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_socket(INT protocolFamily, INT type, INT protocol)
@@ -1207,7 +1207,7 @@ UINT index;
/* FUNCTION RELEASE */
/* */
/* connect PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -1265,9 +1265,9 @@ UINT index;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_connect(INT sockID, struct nx_bsd_sockaddr *remoteAddress, INT addressLength)
@@ -1766,7 +1766,7 @@ ULONG actual_status;
/* FUNCTION RELEASE */
/* */
/* bind PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -1810,9 +1810,9 @@ ULONG actual_status;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_bind(INT sockID, const struct nx_bsd_sockaddr *localAddress, INT addressLength)
@@ -2367,7 +2367,7 @@ INT address_conflict;
/* FUNCTION RELEASE */
/* */
/* listen PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -2412,9 +2412,9 @@ INT address_conflict;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_listen(INT sockID, INT backlog)
@@ -2617,7 +2617,7 @@ INT ret;
/* FUNCTION RELEASE */
/* */
/* accept PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -2669,9 +2669,9 @@ INT ret;
/* 09-30-2020 Yuxin Zhou Modified comment(s), and */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_accept(INT sockID, struct nx_bsd_sockaddr *ClientAddress, INT *addressLength)
@@ -3092,7 +3092,7 @@ struct nx_bsd_sockaddr_in6
/* FUNCTION RELEASE */
/* */
/* nx_bsd_send_internal PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -3148,9 +3148,9 @@ struct nx_bsd_sockaddr_in6
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Tiejun Zhou Modified comment(s), */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), */
/* supported random IP id, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
static INT nx_bsd_send_internal(INT sockID, const CHAR *msg, INT msgLength, INT flags,
@@ -3543,7 +3543,7 @@ ULONG data_sent = (ULONG)msgLength;
/* FUNCTION RELEASE */
/* */
/* send PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -3601,9 +3601,9 @@ ULONG data_sent = (ULONG)msgLength;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_send(INT sockID, const CHAR *msg, INT msgLength, INT flags)
@@ -3698,7 +3698,7 @@ NX_BSD_SOCKET *bsd_socket_ptr;
/* FUNCTION RELEASE */
/* */
/* sendto PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -3752,9 +3752,9 @@ NX_BSD_SOCKET *bsd_socket_ptr;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_sendto(INT sockID, CHAR *msg, INT msgLength, INT flags, struct nx_bsd_sockaddr *destAddr, INT destAddrLen)
@@ -3944,7 +3944,7 @@ USHORT peer_port = 0;
/* FUNCTION RELEASE */
/* */
/* recv PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -4006,9 +4006,9 @@ USHORT peer_port = 0;
/* 09-30-2020 Yuxin Zhou Modified comment(s), and */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_recv(INT sockID, VOID *rcvBuffer, INT bufferLength, INT flags)
@@ -4503,7 +4503,7 @@ ULONG start_time = nx_bsd_system_clock;
/* FUNCTION RELEASE */
/* */
/* recvfrom PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -4554,9 +4554,9 @@ ULONG start_time = nx_bsd_system_clock;
/* 09-30-2020 Yuxin Zhou Modified comment(s), and */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_recvfrom(INT sockID, CHAR *rcvBuffer, INT bufferLength, INT flags, struct nx_bsd_sockaddr *fromAddr, INT *fromAddrLen)
@@ -4723,7 +4723,7 @@ struct nx_bsd_sockaddr_in6
/* FUNCTION RELEASE */
/* */
/* soc_close PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -4780,9 +4780,9 @@ struct nx_bsd_sockaddr_in6
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_soc_close(INT sockID)
@@ -5202,7 +5202,7 @@ UINT index;
/* FUNCTION RELEASE */
/* */
/* fcntl PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -5241,9 +5241,9 @@ UINT index;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_fcntl(INT sockID, UINT flag_type, UINT f_options)
@@ -5315,7 +5315,7 @@ NX_BSD_SOCKET *bsd_socket_ptr;
/* FUNCTION RELEASE */
/* */
/* ioctl PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -5360,9 +5360,9 @@ NX_BSD_SOCKET *bsd_socket_ptr;
/* 03-08-2023 Wenhui Xie Modified comment(s), corrected*/
/* the result of FIONREAD, */
/* resulting in version 6.2.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_ioctl(INT sockID, INT command, INT *result)
@@ -5510,7 +5510,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* inet_ntoa PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -5547,9 +5547,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 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
CHAR *nx_bsd_inet_ntoa(struct nx_bsd_in_addr address_to_convert)
@@ -5680,7 +5680,7 @@ UINT size;
/* FUNCTION RELEASE */
/* */
/* inet_aton PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -5718,9 +5718,9 @@ UINT size;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_inet_aton(const CHAR *address_buffer_ptr, struct nx_bsd_in_addr *addr)
@@ -5964,7 +5964,7 @@ UINT dot_flag;
/* FUNCTION RELEASE */
/* */
/* inet_addr PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -5999,9 +5999,9 @@ UINT dot_flag;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
nx_bsd_in_addr_t nx_bsd_inet_addr(const CHAR *buffer)
@@ -6026,7 +6026,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* getsockopt PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -6066,9 +6066,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 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_getsockopt(INT sockID, INT option_level, INT option_name, VOID *option_value, INT *option_length)
@@ -6364,7 +6364,7 @@ ULONG ticks;
/* FUNCTION RELEASE */
/* */
/* setsockopt PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -6403,9 +6403,9 @@ ULONG ticks;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_setsockopt(INT sockID, INT option_level, INT option_name, const VOID *option_value, INT option_length)
@@ -6964,7 +6964,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* getsockname PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -7005,9 +7005,9 @@ UINT status;
/* 09-30-2020 Yuxin Zhou Modified comment(s), and */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_getsockname(INT sockID, struct nx_bsd_sockaddr *localAddress, INT *addressLength)
@@ -7201,7 +7201,7 @@ NX_BSD_SOCKET *bsd_socket_ptr;
/* FUNCTION RELEASE */
/* */
/* getpeername PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -7238,9 +7238,9 @@ NX_BSD_SOCKET *bsd_socket_ptr;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_getpeername(INT sockID, struct nx_bsd_sockaddr *remoteAddress, INT *addressLength)
@@ -7493,7 +7493,7 @@ struct nx_bsd_sockaddr_in6 *soc6_struct_ptr = NX_NULL;
/* FUNCTION RELEASE */
/* */
/* select PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -7573,9 +7573,9 @@ struct nx_bsd_sockaddr_in6 *soc6_struct_ptr = NX_NULL;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_select(INT nfds, nx_bsd_fd_set *readfds, nx_bsd_fd_set *writefds, nx_bsd_fd_set *exceptfds, struct nx_bsd_timeval *timeout)
@@ -8426,7 +8426,7 @@ NX_UDP_SOCKET *udp_socket_ptr;
/* FUNCTION RELEASE */
/* */
/* FD_SET PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -8459,9 +8459,9 @@ NX_UDP_SOCKET *udp_socket_ptr;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
VOID NX_BSD_FD_SET(INT fd, nx_bsd_fd_set *fdset)
@@ -8506,7 +8506,7 @@ UINT index;
/* FUNCTION RELEASE */
/* */
/* FD_CLR PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -8539,9 +8539,9 @@ UINT index;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
VOID NX_BSD_FD_CLR(INT fd, nx_bsd_fd_set *fdset)
@@ -8666,7 +8666,7 @@ UINT index;
/* FUNCTION RELEASE */
/* */
/* FD_ZERO PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -8698,9 +8698,9 @@ UINT index;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
VOID NX_BSD_FD_ZERO(nx_bsd_fd_set *fdset)
@@ -8941,7 +8941,7 @@ VOID nx_bsd_raw_receive_notify(NX_IP *ip_ptr, UINT bsd_socket_index)
/* FUNCTION RELEASE */
/* */
/* nx_bsd_raw_packet_receive PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -8979,9 +8979,9 @@ VOID nx_bsd_raw_receive_notify(NX_IP *ip_ptr, UINT bsd_socket_index)
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT nx_bsd_raw_packet_receive(NX_BSD_SOCKET *bsd_socket_ptr, NX_PACKET **packet_ptr)
@@ -9752,7 +9752,7 @@ static UINT nx_bsd_isxdigit(UCHAR c)
/* FUNCTION RELEASE */
/* */
/* set_errno PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -9786,9 +9786,9 @@ static UINT nx_bsd_isxdigit(UCHAR c)
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
VOID nx_bsd_set_errno(INT tx_errno)
@@ -9873,7 +9873,7 @@ TX_THREAD *current_thread_ptr;
/* FUNCTION RELEASE */
/* */
/* nx_bsd_select_wakeup PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -9916,9 +9916,9 @@ TX_THREAD *current_thread_ptr;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
static VOID nx_bsd_select_wakeup(UINT sock_id, UINT fd_sets)
@@ -10063,7 +10063,7 @@ NX_BSD_SOCKET_SUSPEND *suspend_info;
/* FUNCTION RELEASE */
/* */
/* nx_bsd_set_error_code PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -10097,9 +10097,9 @@ NX_BSD_SOCKET_SUSPEND *suspend_info;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
static VOID nx_bsd_set_error_code(NX_BSD_SOCKET *bsd_socket_ptr, UINT status_code)
@@ -10553,7 +10553,7 @@ NX_INTERFACE *interface_ptr;
/* FUNCTION RELEASE */
/* */
/* nx_bsd_tcp_create_listen_socket PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -10591,9 +10591,9 @@ NX_INTERFACE *interface_ptr;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
static INT nx_bsd_tcp_create_listen_socket(INT master_sockid, INT backlog)
@@ -12506,7 +12506,7 @@ NX_IPV6_HEADER_OPTION *option;
/* FUNCTION RELEASE */
/* */
/* nx_bsd_pppoe_internal_sendto PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -12548,9 +12548,9 @@ NX_IPV6_HEADER_OPTION *option;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
static INT nx_bsd_pppoe_internal_sendto(NX_BSD_SOCKET *bsd_socket_ptr, CHAR *msg, INT msgLength, INT flags, struct nx_bsd_sockaddr* destAddr, INT destAddrLen)
@@ -13123,7 +13123,7 @@ NX_BSD_SOCKET *bsd_ptr;
/* FUNCTION RELEASE */
/* */
/* inet_pton PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -13162,9 +13162,9 @@ NX_BSD_SOCKET *bsd_ptr;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_inet_pton(INT af, const CHAR *src, VOID *dst)
@@ -13393,7 +13393,7 @@ struct nx_bsd_in_addr ipv4_addr;
/* FUNCTION RELEASE */
/* */
/* inet_ntop PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -13432,9 +13432,9 @@ struct nx_bsd_in_addr ipv4_addr;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
const CHAR *nx_bsd_inet_ntop(INT af, const VOID *src, CHAR *dst, nx_bsd_socklen_t size)
@@ -13731,7 +13731,7 @@ UINT index = 0;
/* FUNCTION RELEASE */
/* */
/* getaddrinfo PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -13795,9 +13795,9 @@ UINT index = 0;
/* 07-29-2022 Yuxin Zhou Modified comment(s), and */
/* fixed compiler warnings, */
/* resulting in version 6.1.12 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_getaddrinfo(const CHAR *node, const CHAR *service, const struct nx_bsd_addrinfo *hints, struct nx_bsd_addrinfo **res)
@@ -14349,7 +14349,7 @@ static struct nx_bsd_addrinfo default_hints = {0, AF_UNSPEC, 0, 0, 0, NX_NULL, N
/* FUNCTION RELEASE */
/* */
/* freeaddrinfo PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -14381,9 +14381,9 @@ static struct nx_bsd_addrinfo default_hints = {0, AF_UNSPEC, 0, 0, 0, NX_NULL, N
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
VOID nx_bsd_freeaddrinfo(struct nx_bsd_addrinfo *res)
@@ -14495,7 +14495,7 @@ static INT bsd_string_to_number(const CHAR *string, UINT *number)
/* FUNCTION RELEASE */
/* */
/* getnameinfo PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -14538,9 +14538,9 @@ static INT bsd_string_to_number(const CHAR *string, UINT *number)
/* 09-30-2020 Yuxin Zhou Modified comment(s), and */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* used new API/structs naming,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_getnameinfo(const struct nx_bsd_sockaddr *sa, nx_bsd_socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
@@ -14888,7 +14888,7 @@ static VOID _nx_bsd_fast_periodic_timer_entry(ULONG id)
/* FUNCTION RELEASE */
/* */
/* poll PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Chaoqiong Xiao, Microsoft Corporation */
@@ -14943,7 +14943,7 @@ static VOID _nx_bsd_fast_periodic_timer_entry(ULONG id)
/* */
/* DATE NAME DESCRIPTION */
/* */
-/* xx-xx-xxxx Chaoqiong Xiao Initial Version 6.x */
+/* 10-31-2023 Chaoqiong Xiao Initial Version 6.3.0 */
/* */
/**************************************************************************/
INT nx_bsd_poll(struct nx_bsd_pollfd *fds, ULONG nfds, INT timeout)
diff --git a/addons/BSD/nxd_bsd.h b/addons/BSD/nxd_bsd.h
index 6d1e2629..9f24b1f0 100644
--- a/addons/BSD/nxd_bsd.h
+++ b/addons/BSD/nxd_bsd.h
@@ -25,7 +25,7 @@
/* BSD DEFINITIONS RELEASE */
/* */
/* nxd_bsd.h PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -50,10 +50,10 @@
/* defined IP protocols for */
/* ICMP, IGMP and ICMPv6, */
/* resulting in version 6.1.9 */
-/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), and */
+/* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
/* added option to enable */
/* native APIs with prefix, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
diff --git a/addons/CMakeLists.txt b/addons/CMakeLists.txt
index 37aae089..718aa978 100644
--- a/addons/CMakeLists.txt
+++ b/addons/CMakeLists.txt
@@ -36,6 +36,8 @@ set(SOURCES
${CMAKE_CURRENT_LIST_DIR}/web/nx_web_http_client.c
${CMAKE_CURRENT_LIST_DIR}/web/nx_web_http_server.c
${CMAKE_CURRENT_LIST_DIR}/websocket/nx_websocket_client.c
+ ${CMAKE_CURRENT_LIST_DIR}/rtp/nx_rtp_sender.c
+ ${CMAKE_CURRENT_LIST_DIR}/rtsp/nx_rtsp_server.c
# {{END_TARGET_SOURCES}}
)
@@ -105,4 +107,6 @@ target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_LIST_DIR}/tftp
${CMAKE_CURRENT_LIST_DIR}/web
${CMAKE_CURRENT_LIST_DIR}/websocket
+ ${CMAKE_CURRENT_LIST_DIR}/rtp
+ ${CMAKE_CURRENT_LIST_DIR}/rtsp
)
diff --git a/addons/azure_iot/samples/sample_azure_iot_embedded_sdk.c b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk.c
index 22f040ea..bb12fb70 100644
--- a/addons/azure_iot/samples/sample_azure_iot_embedded_sdk.c
+++ b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk.c
@@ -99,7 +99,7 @@ static TX_THREAD sample_device_twin_thread;
static ULONG sample_device_twin_thread_stack[SAMPLE_STACK_SIZE / sizeof(ULONG)];
#endif /* DISABLE_DEVICE_TWIN_SAMPLE */
-void sample_entry(NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, NX_DNS *dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time));
+void sample_entry(NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, VOID *dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time));
#ifdef ENABLE_DPS_SAMPLE
static UINT sample_dps_entry(UCHAR **iothub_hostname, UINT *iothub_hostname_length,
UCHAR **iothub_device_id, UINT *iothub_device_id_length);
@@ -283,7 +283,7 @@ static void log_callback(az_log_classification classification, UCHAR *msg, UINT
}
}
-void sample_entry(NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, NX_DNS *dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time))
+void sample_entry(NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, VOID *dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time))
{
UINT status = 0;
UINT loop = NX_TRUE;
@@ -291,7 +291,7 @@ UINT loop = NX_TRUE;
nx_azure_iot_log_init(log_callback);
/* Create Azure IoT handler. */
- if ((status = nx_azure_iot_create(&nx_azure_iot, (UCHAR *)"Azure IoT", ip_ptr, pool_ptr, dns_ptr,
+ if ((status = nx_azure_iot_create(&nx_azure_iot, (UCHAR *)"Azure IoT", ip_ptr, pool_ptr, (NX_DNS *)dns_ptr,
nx_azure_iot_thread_stack, sizeof(nx_azure_iot_thread_stack),
NX_AZURE_IOT_THREAD_PRIORITY, unix_time_callback)))
{
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 d7e82d0d..8d8a5ca9 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
@@ -67,7 +67,7 @@ static SAMPLE_CLIENT client;
#define prov_client client.prov_client
#endif /* ENABLE_DPS_SAMPLE */
-void sample_entry(NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, NX_DNS *dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time));
+void sample_entry(NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, VOID *dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time));
#ifdef ENABLE_DPS_SAMPLE
static UINT sample_dps_entry(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
@@ -984,7 +984,7 @@ static void log_callback(az_log_classification classification, UCHAR *msg, UINT
}
}
-void sample_entry(NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, NX_DNS *dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time))
+void sample_entry(NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, VOID *dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time))
{
UINT status = 0;
UINT loop = NX_TRUE;
@@ -993,7 +993,7 @@ ULONG app_events;
nx_azure_iot_log_init(log_callback);
/* Create Azure IoT handler. */
- if ((status = nx_azure_iot_create(&nx_azure_iot, (UCHAR *)"Azure IoT", ip_ptr, pool_ptr, dns_ptr,
+ if ((status = nx_azure_iot_create(&nx_azure_iot, (UCHAR *)"Azure IoT", ip_ptr, pool_ptr, (NX_DNS *)dns_ptr,
nx_azure_iot_thread_stack, sizeof(nx_azure_iot_thread_stack),
NX_AZURE_IOT_THREAD_PRIORITY, unix_time_callback)))
{
diff --git a/addons/dhcp/nxd_dhcp_client.c b/addons/dhcp/nxd_dhcp_client.c
index 441bb1c0..677b8a1e 100644
--- a/addons/dhcp/nxd_dhcp_client.c
+++ b/addons/dhcp/nxd_dhcp_client.c
@@ -3552,7 +3552,7 @@ NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL;
/* FUNCTION RELEASE */
/* */
/* _nxe_dhcp_state_change_notify PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -3586,9 +3586,9 @@ 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 */
-/* xx-xx-xxxx Haiqing Zhao Modified comment(s), and */
+/* 10-31-2023 Haiqing Zhao Modified comment(s), and */
/* corrected caller checking, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nxe_dhcp_state_change_notify(NX_DHCP *dhcp_ptr, VOID (*dhcp_state_change_notify)(NX_DHCP *dhcp_ptr, UCHAR new_state))
@@ -6995,7 +6995,7 @@ UINT name_length;
/* FUNCTION RELEASE */
/* */
/* _nx_dhcp_client_send_with_zero_source_address PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -7042,9 +7042,9 @@ UINT name_length;
/* udp socket send and ip */
/* header add, */
/* resulting in version 6.1.12 */
-/* xx-xx-xxxx Tiejun Zhou Modified comment(s), */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), */
/* supported random IP id, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
static UINT _nx_dhcp_client_send_with_zero_source_address(NX_DHCP *dhcp_ptr, UINT iface_index, NX_PACKET *packet_ptr)
diff --git a/addons/dhcp/nxd_dhcp_server.c b/addons/dhcp/nxd_dhcp_server.c
index 90143562..8e90b0cd 100644
--- a/addons/dhcp/nxd_dhcp_server.c
+++ b/addons/dhcp/nxd_dhcp_server.c
@@ -2669,7 +2669,7 @@ CHAR *buffer;
/* FUNCTION RELEASE */
/* */
/* _nx_dhcp_server_packet_process PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -2714,6 +2714,10 @@ CHAR *buffer;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 10-31-2023 Bo Chen Modified comment(s), corrected*/
+/* the logic of verifying the */
+/* incoming packet length, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
static UINT _nx_dhcp_server_packet_process(NX_DHCP_SERVER *dhcp_ptr, NX_PACKET *packet_ptr)
@@ -2778,6 +2782,10 @@ ULONG offset;
return(status);
}
+ /* Update the prepend pointer to make sure that the IP header and UDP header also are copied into new packet. */
+ packet_ptr -> nx_packet_prepend_ptr -= 28;
+ packet_ptr -> nx_packet_length += 28;
+
/* Verify the incoming packet does not exceed our DHCP Server packet payload. */
if ((ULONG)(new_packet_ptr -> nx_packet_data_end - new_packet_ptr -> nx_packet_prepend_ptr) < (packet_ptr -> nx_packet_length))
{
@@ -2790,10 +2798,6 @@ ULONG offset;
return(NX_DHCP_INADEQUATE_PACKET_POOL_PAYLOAD);
}
-
- /* Update the prepend pointer to make sure that the IP header and UDP header also are copied into new packet. */
- packet_ptr -> nx_packet_prepend_ptr -= 28;
- packet_ptr -> nx_packet_length += 28;
/* Initialize the offset to the beginning of the packet buffer. */
offset = 0;
@@ -4812,7 +4816,7 @@ UINT lease_time;
/* FUNCTION RELEASE */
/* */
/* _nx_dhcp_server_extract_information PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -4865,6 +4869,9 @@ UINT lease_time;
/* and write overflow, */
/* fixed compiler warnings, */
/* resulting in version 6.1 */
+/* 10-31-2023 Haiqing Zhao Modified comment(s), and */
+/* improved internal logic, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
static UINT _nx_dhcp_server_extract_information(NX_DHCP_SERVER *dhcp_ptr, NX_DHCP_CLIENT **dhcp_client_ptr,
@@ -4873,7 +4880,7 @@ static UINT _nx_dhcp_server_extract_information(NX_DHCP_SERVER *dhcp_ptr, NX_DH
UINT status;
ULONG value;
-UINT size = 0;
+ULONG size = 0;
ULONG xid;
UCHAR *work_ptr;
ULONG client_mac_msw;
@@ -5063,7 +5070,7 @@ NX_DHCP_CLIENT *temp_client_rec_ptr;
work_ptr++;
/* Get the option length. */
- _nx_dhcp_server_get_data(work_ptr, 1, (ULONG *)&size);
+ _nx_dhcp_server_get_data(work_ptr, 1, &size);
/* Move up the buffer pointer to the next option. */
work_ptr++;
@@ -5083,7 +5090,7 @@ NX_DHCP_CLIENT *temp_client_rec_ptr;
{
/* Process as any other option. */
- _nx_dhcp_process_option_data(temp_client_rec_ptr, (CHAR *)work_ptr, (UCHAR)value, NX_TRUE, size);
+ _nx_dhcp_process_option_data(temp_client_rec_ptr, (CHAR *)work_ptr, (UCHAR)value, NX_TRUE, (UINT)size);
}
}
diff --git a/addons/dhcp/nxd_dhcpv6_server.c b/addons/dhcp/nxd_dhcpv6_server.c
index b84c8072..e31b3e68 100644
--- a/addons/dhcp/nxd_dhcpv6_server.c
+++ b/addons/dhcp/nxd_dhcpv6_server.c
@@ -3810,7 +3810,7 @@ NXD_ADDRESS client_address;
/* FUNCTION RELEASE */
/* */
/* _nx_dhcpv6_server_extract_packet_information PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -3862,6 +3862,10 @@ NXD_ADDRESS client_address;
/* packet length verification, */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
+/* 10-31-2023 Haiqing Zhao Modified comment(s), and */
+/* updated client record on */
+/* each message, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_dhcpv6_server_extract_packet_information(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NX_DHCPV6_CLIENT **dhcpv6_client_ptr, NX_PACKET *packet_ptr,
@@ -4189,37 +4193,25 @@ UINT matching;
*dhcpv6_client_ptr = &dhcpv6_server_ptr -> nx_dhcpv6_clients[record_index];
/* Was a match was found? */
- if (!matching)
- {
-
- /* No, this is a new record. Create a new client record. */
- status = _nx_dhcpv6_update_client_record(dhcpv6_server_ptr, &temp_client_rec, *dhcpv6_client_ptr);
- }
- else
+ if (matching)
{
- /* A match was found. Check if this is a different message request than the previous client request. */
- if ((temp_client_rec.nx_dhcpv6_message_type != (*dhcpv6_client_ptr) -> nx_dhcpv6_message_type) &&
- (received_message_type != NX_DHCPV6_MESSAGE_TYPE_INFORM_REQUEST))
+ /* This is a different message from the Client. Before updating the record check the client global address
+ to be the same as what the server assigned or is offering to assign. */
+ if (!CHECK_IPV6_ADDRESSES_SAME(&temp_client_rec.nx_dhcpv6_ia.nx_global_address.nxd_ip_address.v6[0],
+ &(*dhcpv6_client_ptr )-> nx_dhcpv6_ia.nx_global_address.nxd_ip_address.v6[0]))
{
- /* This is a different message from the Client. Before updating the record check the client global address
- to be the same as what the server assigned or is offering to assign. */
- if (!CHECK_IPV6_ADDRESSES_SAME(&temp_client_rec.nx_dhcpv6_ia.nx_global_address.nxd_ip_address.v6[0],
- &(*dhcpv6_client_ptr )-> nx_dhcpv6_ia.nx_global_address.nxd_ip_address.v6[0]))
- {
-
- /* This is a different address. Disregard this message. */
- (*dhcpv6_client_ptr) -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT;
+ /* This is a different address. Disregard this message. */
+ (*dhcpv6_client_ptr) -> nx_dhcpv6_response_back_from_server = NX_DHCPV6_MESSAGE_TYPE_DHCPSILENT;
- return NX_SUCCESS;
- }
-
- /* This is a valid request. Update the client record with the new data. */
- status = _nx_dhcpv6_update_client_record(dhcpv6_server_ptr, &temp_client_rec, *dhcpv6_client_ptr);
+ return NX_SUCCESS;
}
}
+ /* Update the client record. */
+ status = _nx_dhcpv6_update_client_record(dhcpv6_server_ptr, &temp_client_rec, *dhcpv6_client_ptr);
+
/* Yes we're done with no processing errors detected. */
return NX_SUCCESS;
}
@@ -6476,7 +6468,7 @@ ULONG data;
/* FUNCTION RELEASE */
/* */
/* _nx_dhcpv6_server_process_ia PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -6517,12 +6509,17 @@ ULONG data;
/* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
/* packet length verification, */
/* resulting in version 6.1 */
+/* 10-31-2023 Haiqing Zhao Modified comment(s), and */
+/* improved to ignore valid */
+/* lifetime and preferred life */
+/* time in client message, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_dhcpv6_server_process_ia(NX_DHCPV6_CLIENT *dhcpv6_client_ptr, ULONG option_code, UINT option_length, UCHAR *option_data, UINT process_ia)
{
-UINT index = 0, k;
+UINT k;
ULONG data;
@@ -6535,7 +6532,7 @@ ULONG data;
}
/* Check option length for Ipv6 address (16 bytes), preferred-lifetime (4 bytes) and valid-lifetime (4 bytes). */
- if (option_length < 24)
+ if (option_length != 24)
{
return(NX_DHCPV6_INVALID_IA_DATA);
}
@@ -6545,42 +6542,19 @@ ULONG data;
{
/* Copy each IPv6 address word into the IA address. */
- _nx_dhcpv6_server_utility_get_data(option_data + index, sizeof(ULONG), &data);
+ _nx_dhcpv6_server_utility_get_data(option_data + (k * 4), sizeof(ULONG), &data);
if (process_ia)
{
dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_global_address.nxd_ip_address.v6[k] = data;
}
-
- /* Move to the next IPv6 address word. */
- index += 4;
}
- /* Copy the preferred lifetime data from the client buffer to IA.*/
- _nx_dhcpv6_server_utility_get_data(option_data + index, sizeof(ULONG), &data);
- if (process_ia)
- {
- dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime = data;
- }
- index += 4;
-
- /* Copy the valid lifetime data from the client buffer to IA.*/
- _nx_dhcpv6_server_utility_get_data(option_data + index, sizeof(ULONG), &data);
- if (process_ia)
- {
- dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime = data;
- }
- index += 4;
-
- /* Check if we went past the reported size of IA address data. */
- if (index != option_length)
- {
+ /* Skip 4 bytes preferred lifetime data and 4 bytes valid lifetime data from the client buffer to IA.
+ This is because in RFC 8415, page 105, it requires that the server MUST ignore any received
+ preferred-lifetime and valid-lifetime values in a message sent by a client to a server. */
- /* Return an error status. Cannot accept this reply. */
- return NX_DHCPV6_INVALID_IA_DATA;
- }
-
- return NX_SUCCESS;
+ return(NX_SUCCESS);
}
diff --git a/addons/dns/nxd_dns.c b/addons/dns/nxd_dns.c
index dc4cded7..e9a26b5a 100644
--- a/addons/dns/nxd_dns.c
+++ b/addons/dns/nxd_dns.c
@@ -4704,7 +4704,7 @@ NX_PACKET *packet_ptr;
/* FUNCTION RELEASE */
/* */
/* _nx_dns_response_receive PORTABLE C */
-/* 6.1.4 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -4738,6 +4738,10 @@ NX_PACKET *packet_ptr;
/* DATE NAME DESCRIPTION */
/* */
/* 02-02-2021 Yuxin Zhou Initial Version 6.1.4 */
+/* 10-31-2023 Bo Chen Modified comment(s), and */
+/* reset the status to avoid */
+/* processing null packet, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
static UINT _nx_dns_response_receive(NX_DNS *dns_ptr, NX_PACKET **packet_ptr, ULONG wait_option)
@@ -4779,6 +4783,9 @@ ULONG time_remaining;
/* They do not. Discard the packet! */
nx_packet_release((*packet_ptr));
+ /* Set the status. */
+ status = NX_DNS_BAD_ID_ERROR;
+
/* Continue to receive next packet. */
if (time_remaining == 0)
{
diff --git a/addons/ftp/nxd_ftp_client.c b/addons/ftp/nxd_ftp_client.c
index 84118c5a..7dd2d742 100644
--- a/addons/ftp/nxd_ftp_client.c
+++ b/addons/ftp/nxd_ftp_client.c
@@ -340,7 +340,7 @@ UINT _nxd_ftp_client_connect(NX_FTP_CLIENT *ftp_client_ptr, NXD_ADDRESS *server
/* FUNCTION RELEASE */
/* */
/* _nx_ftp_client_connect_internal PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -382,6 +382,9 @@ UINT _nxd_ftp_client_connect(NX_FTP_CLIENT *ftp_client_ptr, NXD_ADDRESS *server
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), */
+/* corrected length of buffer, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_ftp_client_connect_internal(NX_FTP_CLIENT *ftp_client_ptr, NXD_ADDRESS *server_ip, CHAR *username,
@@ -629,6 +632,7 @@ UINT status;
/* We have a packet, setup pointer to the buffer area. */
buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
+ length = packet_ptr -> nx_packet_length;
/* Check for 220 message. */
if ((packet_ptr -> nx_packet_length >= 3) && (buffer_ptr[0] == '2') && (buffer_ptr[1] == '2'))
@@ -4447,7 +4451,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* _nx_ftp_client_file_write PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -4484,6 +4488,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 */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), */
+/* fixed packet double release,*/
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_ftp_client_file_write(NX_FTP_CLIENT *ftp_client_ptr, NX_PACKET *packet_ptr, ULONG wait_option)
@@ -4516,9 +4523,6 @@ ULONG file_size = 0;
if (status)
{
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
/* Return error. */
return(status);
}
diff --git a/addons/ftp/nxd_ftp_server.c b/addons/ftp/nxd_ftp_server.c
index 5b43e940..9a1d304e 100644
--- a/addons/ftp/nxd_ftp_server.c
+++ b/addons/ftp/nxd_ftp_server.c
@@ -976,7 +976,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* _nx_ftp_server_stop PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -1011,6 +1011,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 */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), */
+/* removed deletion of control */
+/* socket, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_ftp_server_stop(NX_FTP_SERVER *ftp_server_ptr)
@@ -1071,9 +1075,6 @@ NX_FTP_CLIENT_REQUEST *client_request_ptr;
/* Unaccept the control socket. */
nx_tcp_server_socket_unaccept(&(client_request_ptr -> nx_ftp_client_request_control_socket));
-
- /* Delete both the control and data sockets. */
- nx_tcp_socket_delete(&(client_request_ptr -> nx_ftp_client_request_control_socket));
}
/* Unlisten on the FTP control port. */
@@ -1507,7 +1508,7 @@ ULONG events;
/* FUNCTION RELEASE */
/* */
/* _nx_ftp_server_command_process PORTABLE C */
-/* 6.1.9 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -1594,6 +1595,13 @@ ULONG events;
/* reset the packet prepend */
/* pointer for alignment, */
/* resulting in version 6.1.9 */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), */
+/* fixed duplicate packet */
+/* release issue, avoided */
+/* duplicate creation for data */
+/* socket, fixed data length */
+/* underflow, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
VOID _nx_ftp_server_command_process(NX_FTP_SERVER *ftp_server_ptr)
@@ -1662,2668 +1670,2714 @@ ULONG block_size;
/* Reset the client request activity timeout. */
client_req_ptr -> nx_ftp_client_request_activity_timeout = NX_FTP_ACTIVITY_TIMEOUT;
- /* Attempt to read a packet from this socket. */
- status = nx_tcp_socket_receive(&(client_req_ptr -> nx_ftp_client_request_control_socket), &packet_ptr, NX_NO_WAIT);
-
- /* Check for not data present. */
- if (status != NX_SUCCESS)
+ for (;;)
{
- /* Just continue the loop and look at the next socket. */
- continue;
- }
+ /* Attempt to read a packet from this socket. */
+ status = nx_tcp_socket_receive(&(client_req_ptr -> nx_ftp_client_request_control_socket), &packet_ptr, NX_NO_WAIT);
+
+ /* Check for not data present. */
+ if (status != NX_SUCCESS)
+ {
+
+ /* Break the loop and look at the next socket. */
+ break;
+ }
#ifndef NX_DISABLE_PACKET_CHAIN
- if (packet_ptr -> nx_packet_next)
- {
+ if (packet_ptr -> nx_packet_next)
+ {
- /* Release the packet. */
- nx_packet_release(packet_ptr);
+ /* Release the packet. */
+ nx_packet_release(packet_ptr);
- /* And continue looking at other client requests. */
- continue;
- }
+ /* And continue looking at other client requests. */
+ continue;
+ }
#endif /* NX_DISABLE_PACKET_CHAIN */
- /* Now, parse the command in the packet. Note that the parse command adjusts the packet pointer
- such that it is positioned at the next token in the buffer. */
- ftp_command = _nx_ftp_server_parse_command(packet_ptr);
-
- /* Check to make sure the client request is authenticated. */
- if ((client_req_ptr -> nx_ftp_client_request_authenticated == NX_FALSE) &&
- (ftp_command != NX_FTP_USER) && (ftp_command != NX_FTP_PASS))
- {
+ /* Now, parse the command in the packet. Note that the parse command adjusts the packet pointer
+ such that it is positioned at the next token in the buffer. */
+ ftp_command = _nx_ftp_server_parse_command(packet_ptr);
- /* Unauthorized request. */
+ /* Check to make sure the client request is authenticated. */
+ if ((client_req_ptr -> nx_ftp_client_request_authenticated == NX_FALSE) &&
+ (ftp_command != NX_FTP_USER) && (ftp_command != NX_FTP_PASS))
+ {
- /* Increment the access error count. */
- ftp_server_ptr -> nx_ftp_server_authentication_errors++;
+ /* Unauthorized request. */
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_UNAUTHORIZED, "Not logged in");
+ /* Increment the access error count. */
+ ftp_server_ptr -> nx_ftp_server_authentication_errors++;
- /* And continue looking at other client requests. */
- continue;
- }
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_UNAUTHORIZED, "Not logged in");
- /* Check to make sure the client has write access if requesting a write. */
- else if ((client_req_ptr -> nx_ftp_client_request_read_only == NX_TRUE) &&
- ((ftp_command == NX_FTP_STOR) || (ftp_command == NX_FTP_RNFR) || (ftp_command == NX_FTP_RNTO) ||
- (ftp_command == NX_FTP_DELE) || (ftp_command == NX_FTP_RMD ) || (ftp_command == NX_FTP_MKD )))
- {
+ /* And continue looking at other client requests. */
+ continue;
+ }
- /* Unauthorized request. */
+ /* Check to make sure the client has write access if requesting a write. */
+ else if ((client_req_ptr -> nx_ftp_client_request_read_only == NX_TRUE) &&
+ ((ftp_command == NX_FTP_STOR) || (ftp_command == NX_FTP_RNFR) || (ftp_command == NX_FTP_RNTO) ||
+ (ftp_command == NX_FTP_DELE) || (ftp_command == NX_FTP_RMD ) || (ftp_command == NX_FTP_MKD )))
+ {
- /* Increment the access error count. */
- ftp_server_ptr -> nx_ftp_server_authentication_errors++;
+ /* Unauthorized request. */
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_NO_ACCT, "Need account for storing files");
+ /* Increment the access error count. */
+ ftp_server_ptr -> nx_ftp_server_authentication_errors++;
- /* And continue looking at other client requests. */
- continue;
- }
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_NO_ACCT, "Need account for storing files");
- /* Switch on the command received. */
- switch(ftp_command)
- {
+ /* And continue looking at other client requests. */
+ continue;
+ }
- case NX_FTP_USER:
- {
-
- /* Setup pointer to packet buffer area. */
- buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
+ /* Switch on the command received. */
+ switch(ftp_command)
+ {
- /* First, save the username in the request structure. */
- for (j = 0; j < (NX_FTP_USERNAME_SIZE - 1) && (j < packet_ptr -> nx_packet_length); j++)
+ case NX_FTP_USER:
{
+
+ /* Setup pointer to packet buffer area. */
+ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- /* Copy a character. */
- client_req_ptr -> nx_ftp_client_request_username[j] = (CHAR) buffer_ptr[j];
+ /* First, save the username in the request structure. */
+ for (j = 0; j < (NX_FTP_USERNAME_SIZE - 1) && (j < packet_ptr -> nx_packet_length); j++)
+ {
- /* Determine if a CR/LF is present. */
- if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
- break;
- }
+ /* Copy a character. */
+ client_req_ptr -> nx_ftp_client_request_username[j] = (CHAR) buffer_ptr[j];
- /* Ensure the username is NULL terminated. */
- client_req_ptr -> nx_ftp_client_request_username[j] = NX_NULL;
+ /* Determine if a CR/LF is present. */
+ if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
+ break;
+ }
- /* Now send an intermediate response to the username. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_USER_OK, "Enter password");
- break;
- }
+ /* Ensure the username is NULL terminated. */
+ client_req_ptr -> nx_ftp_client_request_username[j] = NX_NULL;
- case NX_FTP_PASS:
- {
-
- /* Setup pointer to packet buffer area. */
- buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
+ /* Now send an intermediate response to the username. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_USER_OK, "Enter password");
+ break;
+ }
- /* First, save the password in the request structure. */
- for (j = 0; j < (NX_FTP_PASSWORD_SIZE - 1) && (j < packet_ptr -> nx_packet_length); j++)
+ case NX_FTP_PASS:
{
+
+ /* Setup pointer to packet buffer area. */
+ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- /* Copy a character. */
- client_req_ptr -> nx_ftp_client_request_password[j] = (CHAR) buffer_ptr[j];
-
- /* Determine if a CR/LF is present. */
- if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
- break;
- }
+ /* First, save the password in the request structure. */
+ for (j = 0; j < (NX_FTP_PASSWORD_SIZE - 1) && (j < packet_ptr -> nx_packet_length); j++)
+ {
- /* Ensure the password is NULL terminated. */
- client_req_ptr -> nx_ftp_client_request_password[j] = NX_NULL;
+ /* Copy a character. */
+ client_req_ptr -> nx_ftp_client_request_password[j] = (CHAR) buffer_ptr[j];
- /* Initially assume client will have read-write access. */
- client_req_ptr -> nx_ftp_client_request_read_only = NX_FALSE;
+ /* Determine if a CR/LF is present. */
+ if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
+ break;
+ }
- /* Initialize the login status as unsuccessful. */
- status = NX_FTP_INVALID_LOGIN;
+ /* Ensure the password is NULL terminated. */
+ client_req_ptr -> nx_ftp_client_request_password[j] = NX_NULL;
- /* Does this FTP server have an login handler? */
- if (ftp_server_ptr -> nx_ftp_login)
- {
+ /* Initially assume client will have read-write access. */
+ client_req_ptr -> nx_ftp_client_request_read_only = NX_FALSE;
- /* Now call the user's login callback routine to see if the username,password is valid. */
- status = (ftp_server_ptr -> nx_ftp_login)(ftp_server_ptr, &(client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip),
- client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_port,
- client_req_ptr -> nx_ftp_client_request_username,
- client_req_ptr -> nx_ftp_client_request_password,
- &client_req_ptr -> nx_ftp_client_request_read_only);
- }
-#ifndef NX_DISABLE_IPV4
- else
- {
+ /* Initialize the login status as unsuccessful. */
+ status = NX_FTP_INVALID_LOGIN;
- /* No duo handler. Check if this is an IPv4 connection. */
- if (client_req_ptr -> nx_ftp_client_request_ip_type == NX_IP_VERSION_V4)
+ /* Does this FTP server have an login handler? */
+ if (ftp_server_ptr -> nx_ftp_login)
{
- /* This is an IPv4 connection. */
+ /* Now call the user's login callback routine to see if the username,password is valid. */
+ status = (ftp_server_ptr -> nx_ftp_login)(ftp_server_ptr, &(client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip),
+ client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_port,
+ client_req_ptr -> nx_ftp_client_request_username,
+ client_req_ptr -> nx_ftp_client_request_password,
+ &client_req_ptr -> nx_ftp_client_request_read_only);
+ }
+#ifndef NX_DISABLE_IPV4
+ else
+ {
- /* Does this server have an IPv4 login function? */
- if (ftp_server_ptr -> nx_ftp_login_ipv4)
+ /* No duo handler. Check if this is an IPv4 connection. */
+ if (client_req_ptr -> nx_ftp_client_request_ip_type == NX_IP_VERSION_V4)
{
-
- /* Yes; Now call the user's login callback routine to see if the username,password is valid. */
- status = (ftp_server_ptr -> nx_ftp_login_ipv4)
- (ftp_server_ptr,
- (client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip.nxd_ip_address.v4),
- client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_port,
- client_req_ptr -> nx_ftp_client_request_username,
- client_req_ptr -> nx_ftp_client_request_password,
- &client_req_ptr -> nx_ftp_client_request_read_only);
+
+ /* This is an IPv4 connection. */
+
+ /* Does this server have an IPv4 login function? */
+ if (ftp_server_ptr -> nx_ftp_login_ipv4)
+ {
+
+ /* Yes; Now call the user's login callback routine to see if the username,password is valid. */
+ status = (ftp_server_ptr -> nx_ftp_login_ipv4)
+ (ftp_server_ptr,
+ (client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip.nxd_ip_address.v4),
+ client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_port,
+ client_req_ptr -> nx_ftp_client_request_username,
+ client_req_ptr -> nx_ftp_client_request_password,
+ &client_req_ptr -> nx_ftp_client_request_read_only);
+ }
}
}
- }
#endif /* NX_DISABLE_IPV4 */
- /* Set the login as TRUE. */
- client_req_ptr -> nx_ftp_client_request_login = NX_TRUE;
-
- if (status == NX_SUCCESS)
- {
+ /* Set the login as TRUE. */
+ client_req_ptr -> nx_ftp_client_request_login = NX_TRUE;
- /* Successful connection. */
+ if (status == NX_SUCCESS)
+ {
- /* Mark as authenticated. */
- client_req_ptr -> nx_ftp_client_request_authenticated = NX_TRUE;
+ /* Successful connection. */
- /* Default transfer type is ASCII image. */
- client_req_ptr -> nx_ftp_client_request_transfer_type = 'A';
+ /* Mark as authenticated. */
+ client_req_ptr -> nx_ftp_client_request_authenticated = NX_TRUE;
- /* Now build a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_LOGIN, "Logged in");
- }
- else
- {
+ /* Default transfer type is ASCII image. */
+ client_req_ptr -> nx_ftp_client_request_transfer_type = 'A';
- /* Unsuccessful login. */
+ /* Now build a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_LOGIN, "Logged in");
+ }
+ else
+ {
- /* Increment the number of login errors. */
- ftp_server_ptr -> nx_ftp_server_login_errors++;
+ /* Unsuccessful login. */
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_UNAUTHORIZED, "Login Fail");
- }
+ /* Increment the number of login errors. */
+ ftp_server_ptr -> nx_ftp_server_login_errors++;
- break;
- }
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_UNAUTHORIZED, "Login Fail");
+ }
- case NX_FTP_QUIT:
- {
-
- /* Increment the number of disconnection requests. */
- ftp_server_ptr -> nx_ftp_server_disconnection_requests++;
+ break;
+ }
- /* Check if this client login. */
- if (client_req_ptr -> nx_ftp_client_request_login)
+ case NX_FTP_QUIT:
{
+
+ /* Increment the number of disconnection requests. */
+ ftp_server_ptr -> nx_ftp_server_disconnection_requests++;
+
+ /* Check if this client login. */
+ if (client_req_ptr -> nx_ftp_client_request_login)
+ {
- /* Call the logout function. */
+ /* Call the logout function. */
#ifndef NX_DISABLE_IPV4
- /* Does this server have an IPv4 login function? */
- if (ftp_server_ptr -> nx_ftp_logout_ipv4)
- {
+ /* Does this server have an IPv4 login function? */
+ if (ftp_server_ptr -> nx_ftp_logout_ipv4)
+ {
- /* Call the logout which takes IPv4 address input. */
- (ftp_server_ptr -> nx_ftp_logout_ipv4)(ftp_server_ptr,
- client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip.nxd_ip_address.v4,
- client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_port,
- client_req_ptr -> nx_ftp_client_request_username,
- client_req_ptr -> nx_ftp_client_request_password, NX_NULL);
- }
+ /* Call the logout which takes IPv4 address input. */
+ (ftp_server_ptr -> nx_ftp_logout_ipv4)(ftp_server_ptr,
+ client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip.nxd_ip_address.v4,
+ client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_port,
+ client_req_ptr -> nx_ftp_client_request_username,
+ client_req_ptr -> nx_ftp_client_request_password, NX_NULL);
+ }
#endif /* NX_DISABLE_IPV4 */
- if (ftp_server_ptr -> nx_ftp_logout)
- {
-
- /* Call the 'duo' logout function which takes IPv6 or IPv4 IP addresses. */
- (ftp_server_ptr -> nx_ftp_logout)(ftp_server_ptr, &(client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip),
- client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_port,
- client_req_ptr -> nx_ftp_client_request_username,
- client_req_ptr -> nx_ftp_client_request_password, NX_NULL);
- }
+ if (ftp_server_ptr -> nx_ftp_logout)
+ {
- /* Set the login as FALSE. */
- client_req_ptr -> nx_ftp_client_request_login = NX_FALSE;
- }
-
- /* Clear authentication. */
- client_req_ptr -> nx_ftp_client_request_authenticated = NX_FALSE;
+ /* Call the 'duo' logout function which takes IPv6 or IPv4 IP addresses. */
+ (ftp_server_ptr -> nx_ftp_logout)(ftp_server_ptr, &(client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip),
+ client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_port,
+ client_req_ptr -> nx_ftp_client_request_username,
+ client_req_ptr -> nx_ftp_client_request_password, NX_NULL);
+ }
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_CLOSE, "Logging Off");
+ /* Set the login as FALSE. */
+ client_req_ptr -> nx_ftp_client_request_login = NX_FALSE;
+ }
+
+ /* Clear authentication. */
+ client_req_ptr -> nx_ftp_client_request_authenticated = NX_FALSE;
- /* If create, cleanup the associated data socket. */
- if (client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_id)
- {
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_CLOSE, "Logging Off");
- /* Clean up the client socket. */
- _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr);
- }
+ /* If create, cleanup the associated data socket. */
+ if (client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_id)
+ {
- /* Now disconnect the command socket. */
- nx_tcp_socket_disconnect(&(client_req_ptr -> nx_ftp_client_request_control_socket), NX_FTP_SERVER_TIMEOUT);
+ /* Clean up the client socket. */
+ _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr);
+ }
- /* Unaccept the server socket. */
- nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_ftp_client_request_control_socket));
+ /* Now disconnect the command socket. */
+ nx_tcp_socket_disconnect(&(client_req_ptr -> nx_ftp_client_request_control_socket), NX_FTP_SERVER_TIMEOUT);
- /* Relisten on this socket. This will probably fail, but it is needed just in case all available
- clients were in use at the time of the last relisten. */
- nx_tcp_server_socket_relisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, NX_FTP_SERVER_CONTROL_PORT,
- &(client_req_ptr -> nx_ftp_client_request_control_socket));
+ /* Unaccept the server socket. */
+ nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_ftp_client_request_control_socket));
- /* Check to see if a packet is queued up. */
- if (client_req_ptr -> nx_ftp_client_request_packet)
- {
+ /* Relisten on this socket. This will probably fail, but it is needed just in case all available
+ clients were in use at the time of the last relisten. */
+ nx_tcp_server_socket_relisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, NX_FTP_SERVER_CONTROL_PORT,
+ &(client_req_ptr -> nx_ftp_client_request_control_socket));
- /* Yes, release it! */
- nx_packet_release(client_req_ptr -> nx_ftp_client_request_packet);
- }
-
- /* Disable the client request activity timeout. */
- client_req_ptr -> nx_ftp_client_request_activity_timeout = 0;
- break;
- }
-
- case NX_FTP_RETR:
- {
-
- /* Check that the transfer type is a Binary Image. */
- if (client_req_ptr -> nx_ftp_client_request_transfer_type != 'I')
- {
+ /* Check to see if a packet is queued up. */
+ if (client_req_ptr -> nx_ftp_client_request_packet)
+ {
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_TYPE, "Only Image transfer allowed");
+ /* Yes, release it! */
+ nx_packet_release(client_req_ptr -> nx_ftp_client_request_packet);
+ client_req_ptr -> nx_ftp_client_request_packet = NX_NULL;
+ }
- /* We are done processing. */
+ /* Disable the client request activity timeout. */
+ client_req_ptr -> nx_ftp_client_request_activity_timeout = 0;
break;
}
- /* Check packet length. */
- if (packet_ptr -> nx_packet_length == 0)
+ case NX_FTP_RETR:
{
+
+ /* Check that the transfer type is a Binary Image. */
+ if (client_req_ptr -> nx_ftp_client_request_transfer_type != 'I')
+ {
- /* Empty message. */
-
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "File Open Fail");
- break;
- }
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_TYPE, "Only Image transfer allowed");
- /* Change to the default directory of this connection. */
- fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
+ /* We are done processing. */
+ break;
+ }
- /* Setup pointer to packet buffer area. */
- buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
- /* Find the end of the message. */
- j = 0;
- while (j < packet_ptr -> nx_packet_length - 1)
- {
+ /* Empty message. */
- /* Determine if a CR/LF is present. */
- if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "File Open Fail");
break;
+ }
- /* Move to next character. */
- j++;
- }
-
- /* Ensure the name is NULL terminated. */
- buffer_ptr[j] = NX_NULL;
-
- /* Attempt to open the file. */
- status = fx_file_open(ftp_server_ptr -> nx_ftp_server_media_ptr,
- &(client_req_ptr -> nx_ftp_client_request_file), (CHAR *) buffer_ptr,
- FX_OPEN_FOR_READ);
+ /* Change to the default directory of this connection. */
+ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
- /* Determine if the file open was successful. */
- if (status == FX_SUCCESS)
- {
+ /* Setup pointer to packet buffer area. */
+ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- /* Check if passive transfer enabled. */
- if (client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled == NX_TRUE)
+ /* Find the end of the message. */
+ j = 0;
+ while (j < packet_ptr -> nx_packet_length - 1)
{
- /* Now wait for the data connection to connect. */
- status = nx_tcp_socket_state_wait(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_TCP_ESTABLISHED, NX_FTP_SERVER_TIMEOUT);
-
- /* Check for connect error. */
- if (status)
- {
+ /* Determine if a CR/LF is present. */
+ if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
+ break;
- /* Yes, a connect error is present. Tear everything down. */
- nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_ftp_client_request_data_socket));
- nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_port);
- nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
- fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file));
- }
+ /* Move to next character. */
+ j++;
}
- else
- {
- /* Create an FTP client data socket. */
- status = nx_tcp_socket_create(ftp_server_ptr -> nx_ftp_server_ip_ptr,
- &(client_req_ptr -> nx_ftp_client_request_data_socket), "FTP Server Data Socket",
- NX_FTP_DATA_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, NX_FTP_DATA_WINDOW_SIZE,
- NX_NULL, NX_NULL);
-
- /* If no error is present, register the receive notify function. */
- if (status == NX_SUCCESS)
- {
-
- /* Make sure each socket points to the corresponding FTP server. */
- client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_reserved_ptr = ftp_server_ptr;
+ /* Ensure the name is NULL terminated. */
+ buffer_ptr[j] = NX_NULL;
- /* Bind the socket to the FTP server data port. */
- status = nx_tcp_client_socket_bind(&(client_req_ptr -> nx_ftp_client_request_data_socket),
- NX_FTP_SERVER_DATA_PORT, NX_NO_WAIT);
+ /* Attempt to open the file. */
+ status = fx_file_open(ftp_server_ptr -> nx_ftp_server_media_ptr,
+ &(client_req_ptr -> nx_ftp_client_request_file), (CHAR *) buffer_ptr,
+ FX_OPEN_FOR_READ);
- /* Determine if the socket was bound. */
- if (status)
- {
+ /* Determine if the file open was successful. */
+ if (status == FX_SUCCESS)
+ {
- /* FTP server data port is busy, use any data port. */
- nx_tcp_client_socket_bind(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_ANY_PORT, NX_NO_WAIT);
- }
+ /* Check if passive transfer enabled. */
+ if (client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled == NX_TRUE)
+ {
- /* Now attempt to connect the data port to the client's data port. */
- status = nxd_tcp_client_socket_connect(&(client_req_ptr -> nx_ftp_client_request_data_socket),
- &(client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip),
- client_req_ptr -> nx_ftp_client_request_data_port, NX_FTP_SERVER_TIMEOUT);
+ /* Now wait for the data connection to connect. */
+ status = nx_tcp_socket_state_wait(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_TCP_ESTABLISHED, NX_FTP_SERVER_TIMEOUT);
/* Check for connect error. */
if (status)
{
- /* Yes, a connect error is present. Tear everything down. */
- nx_tcp_client_socket_unbind(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ /* Yes, a connect error is present. Tear everything down. */
+ nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_port);
nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file));
}
- else
- {
+ }
+ else if (client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_id)
+ {
- /* Setup the data port with a specific packet transmit retry logic. */
- nx_tcp_socket_transmit_configure(&(client_req_ptr -> nx_ftp_client_request_data_socket),
- NX_FTP_SERVER_TRANSMIT_QUEUE_DEPTH,
- NX_FTP_SERVER_RETRY_SECONDS*NX_IP_PERIODIC_RATE,
- NX_FTP_SERVER_RETRY_MAX,
- NX_FTP_SERVER_RETRY_SHIFT);
- }
+ /* Socket already created. Error. */
+ status = NX_NOT_CLOSED;
}
- }
- }
+ else
+ {
- /* Now check and see if the open for read has any errors. */
- if (status == NX_SUCCESS)
- {
+ /* Create an FTP client data socket. */
+ status = nx_tcp_socket_create(ftp_server_ptr -> nx_ftp_server_ip_ptr,
+ &(client_req_ptr -> nx_ftp_client_request_data_socket), "FTP Server Data Socket",
+ NX_FTP_DATA_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, NX_FTP_DATA_WINDOW_SIZE,
+ NX_NULL, NX_NULL);
+
+ /* If no error is present, register the receive notify function. */
+ if (status == NX_SUCCESS)
+ {
- /* The open for read command is successful! */
+ /* Make sure each socket points to the corresponding FTP server. */
+ client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_reserved_ptr = ftp_server_ptr;
- /* Set the open for read type in the client request structure. */
- client_req_ptr -> nx_ftp_client_request_open_type = NX_FTP_OPEN_FOR_READ;
+ /* Bind the socket to the FTP server data port. */
+ status = nx_tcp_client_socket_bind(&(client_req_ptr -> nx_ftp_client_request_data_socket),
+ NX_FTP_SERVER_DATA_PORT, NX_NO_WAIT);
- /* Set the total bytes field to files size. */
- client_req_ptr -> nx_ftp_client_request_total_bytes = (ULONG)client_req_ptr -> nx_ftp_client_request_file.fx_file_current_file_size;
+ /* Determine if the socket was bound. */
+ if (status)
+ {
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_START_XFER, "File Opened");
+ /* FTP server data port is busy, use any data port. */
+ nx_tcp_client_socket_bind(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_ANY_PORT, NX_NO_WAIT);
+ }
- /* Determine if the block mode is enabled. */
- if ((client_req_ptr -> nx_ftp_client_request_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK) &&
- (client_req_ptr -> nx_ftp_client_request_total_bytes))
- {
+ /* Now attempt to connect the data port to the client's data port. */
+ status = nxd_tcp_client_socket_connect(&(client_req_ptr -> nx_ftp_client_request_data_socket),
+ &(client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip),
+ client_req_ptr -> nx_ftp_client_request_data_port, NX_FTP_SERVER_TIMEOUT);
- /* Send start block header for file size. */
- status = _nx_ftp_server_block_header_send(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr,
- client_req_ptr -> nx_ftp_client_request_total_bytes);
+ /* Check for connect error. */
+ if (status)
+ {
+
+ /* Yes, a connect error is present. Tear everything down. */
+ nx_tcp_client_socket_unbind(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file));
+ }
+ else
+ {
+
+ /* Setup the data port with a specific packet transmit retry logic. */
+ nx_tcp_socket_transmit_configure(&(client_req_ptr -> nx_ftp_client_request_data_socket),
+ NX_FTP_SERVER_TRANSMIT_QUEUE_DEPTH,
+ NX_FTP_SERVER_RETRY_SECONDS*NX_IP_PERIODIC_RATE,
+ NX_FTP_SERVER_RETRY_MAX,
+ NX_FTP_SERVER_RETRY_SHIFT);
+ }
+ }
+ }
}
- /* Now read the file and send the contents to the client. */
- while (status == NX_SUCCESS)
+ /* Now check and see if the open for read has any errors. */
+ if (status == NX_SUCCESS)
{
- /* Allocate a new packet. */
- _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
+ /* The open for read command is successful! */
+
+ /* Set the open for read type in the client request structure. */
+ client_req_ptr -> nx_ftp_client_request_open_type = NX_FTP_OPEN_FOR_READ;
+
+ /* Set the total bytes field to files size. */
+ client_req_ptr -> nx_ftp_client_request_total_bytes = (ULONG)client_req_ptr -> nx_ftp_client_request_file.fx_file_current_file_size;
- /* Calculate the maximum read size. */
- length = ((ULONG) (packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr)) - NX_PHYSICAL_TRAILER;
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_START_XFER, "File Opened");
- /* Determine if the length is greater than the connected MSS. */
- if (length > client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss)
+ /* Determine if the block mode is enabled. */
+ if ((client_req_ptr -> nx_ftp_client_request_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK) &&
+ (client_req_ptr -> nx_ftp_client_request_total_bytes))
{
- /* Yes, reduce the length to match the MSS. */
- length = client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss;
+ /* Send start block header for file size. */
+ status = _nx_ftp_server_block_header_send(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr,
+ client_req_ptr -> nx_ftp_client_request_total_bytes);
}
- /* Read a buffer's worth of the file. */
- status = fx_file_read(&(client_req_ptr -> nx_ftp_client_request_file), packet_ptr -> nx_packet_prepend_ptr, length, &length);
-
- /* Determine if the file read was successful. */
- if (status == FX_SUCCESS)
+ /* Now read the file and send the contents to the client. */
+ while (status == NX_SUCCESS)
{
- /* Now send the packet on the data socket. */
+ /* Allocate a new packet. */
+ _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
- /* Set the packet length. */
- packet_ptr -> nx_packet_length = length;
+ /* Calculate the maximum read size. */
+ length = ((ULONG) (packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr)) - NX_PHYSICAL_TRAILER;
- /* Setup the packet append pointer. */
- packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
+ /* Determine if the length is greater than the connected MSS. */
+ if (length > client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss)
+ {
- /* Send the file data to the client. */
- status = nx_tcp_socket_send(&(client_req_ptr -> nx_ftp_client_request_data_socket),
- packet_ptr, NX_FTP_SERVER_TIMEOUT);
+ /* Yes, reduce the length to match the MSS. */
+ length = client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss;
+ }
- /* Determine if the send was unsuccessful. */
- if (status)
+ /* Read a buffer's worth of the file. */
+ status = fx_file_read(&(client_req_ptr -> nx_ftp_client_request_file), packet_ptr -> nx_packet_prepend_ptr, length, &length);
+
+ /* Determine if the file read was successful. */
+ if (status == FX_SUCCESS)
{
- /* Release the packet. */
- nx_packet_release(packet_ptr);
+
+ /* Now send the packet on the data socket. */
+
+ /* Set the packet length. */
+ packet_ptr -> nx_packet_length = length;
+
+ /* Setup the packet append pointer. */
+ packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
+
+ /* Send the file data to the client. */
+ status = nx_tcp_socket_send(&(client_req_ptr -> nx_ftp_client_request_data_socket),
+ packet_ptr, NX_FTP_SERVER_TIMEOUT);
+
+ /* Determine if the send was unsuccessful. */
+ if (status)
+ {
+ /* Release the packet. */
+ nx_packet_release(packet_ptr);
+ }
+ else
+ {
+
+ /* Update the remaining bytes in the file. */
+ client_req_ptr -> nx_ftp_client_request_total_bytes = client_req_ptr -> nx_ftp_client_request_total_bytes - length;
+
+ /* Increment the number of bytes sent. */
+ ftp_server_ptr -> nx_ftp_server_total_bytes_sent += length;
+ }
}
else
{
- /* Update the remaining bytes in the file. */
- client_req_ptr -> nx_ftp_client_request_total_bytes = client_req_ptr -> nx_ftp_client_request_total_bytes - length;
-
- /* Increment the number of bytes sent. */
- ftp_server_ptr -> nx_ftp_server_total_bytes_sent += length;
+ /* Release packet. */
+ nx_packet_release(packet_ptr);
}
}
- else
+
+ /* Determine if the block mode is enabled. */
+ if (client_req_ptr -> nx_ftp_client_request_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
{
- /* Release packet. */
- nx_packet_release(packet_ptr);
+ /* Send end block header for file size. */
+ _nx_ftp_server_block_header_send(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, 0);
}
- }
- /* Determine if the block mode is enabled. */
- if (client_req_ptr -> nx_ftp_client_request_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
- {
-
- /* Send end block header for file size. */
- _nx_ftp_server_block_header_send(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, 0);
- }
+ /* Clean up the data socket. */
+ _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr);
- /* Clean up the data socket. */
- _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr);
+ /* Clear the open type in the client request structure. */
+ client_req_ptr -> nx_ftp_client_request_open_type = 0;
- /* Clear the open type in the client request structure. */
- client_req_ptr -> nx_ftp_client_request_open_type = 0;
+ /* Allocate a new packet. */
+ _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
- /* Allocate a new packet. */
- _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
+ /* Now determine if the read was a success. */
+ if ((status == FX_END_OF_FILE) && (client_req_ptr -> nx_ftp_client_request_total_bytes == 0))
+ {
- /* Now determine if the read was a success. */
- if ((status == FX_END_OF_FILE) && (client_req_ptr -> nx_ftp_client_request_total_bytes == 0))
- {
+ /* The read command was successful! */
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_COMPLETED, "File Sent");
+ }
+ else
+ {
- /* The read command was successful! */
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_COMPLETED, "File Sent");
+ /* Read command failed. */
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Read Fail");
+ }
}
else
{
- /* Read command failed. */
+ /* Unsuccessful open for read or read command. */
+
/* Now send an error response to the client. */
_nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "Read Fail");
+ NX_FTP_CODE_BAD_FILE, "File Open Fail");
}
- }
- else
- {
- /* Unsuccessful open for read or read command. */
-
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "File Open Fail");
+ break;
}
- break;
- }
-
- case NX_FTP_STOR:
- {
-
- /* Check that the transfer type is a Binary Image. */
- if (client_req_ptr -> nx_ftp_client_request_transfer_type != 'I')
+ case NX_FTP_STOR:
{
+
+ /* Check that the transfer type is a Binary Image. */
+ if (client_req_ptr -> nx_ftp_client_request_transfer_type != 'I')
+ {
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_TYPE, "Only Image transfer allowed");
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_TYPE, "Only Image transfer allowed");
- /* And we are done processing. */
- break;
- }
+ /* And we are done processing. */
+ break;
+ }
- /* Check packet length. */
- if (packet_ptr -> nx_packet_length == 0)
- {
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
- /* Empty message. */
+ /* Empty message. */
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "File Open Failed");
- break;
- }
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "File Open Failed");
+ break;
+ }
- /* Change to the default directory of this connection. */
- fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
+ /* Change to the default directory of this connection. */
+ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
- /* Setup pointer to packet buffer area. */
- buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
+ /* Setup pointer to packet buffer area. */
+ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- /* Find the end of the message. */
- j = 0;
- while (j < packet_ptr -> nx_packet_length - 1)
- {
+ /* Find the end of the message. */
+ j = 0;
+ while (j < packet_ptr -> nx_packet_length - 1)
+ {
- /* Determine if a CR/LF is present. */
- if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
- break;
+ /* Determine if a CR/LF is present. */
+ if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
+ break;
- /* Move to next character. */
- j++;
- }
+ /* Move to next character. */
+ j++;
+ }
- /* Ensure the name is NULL terminated. */
- buffer_ptr[j] = NX_NULL;
+ /* Ensure the name is NULL terminated. */
+ buffer_ptr[j] = NX_NULL;
- /* Attempt to open the file. */
- status = fx_file_open(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_request_file), (CHAR *) buffer_ptr, FX_OPEN_FOR_WRITE);
+ /* Attempt to open the file. */
+ status = fx_file_open(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_request_file), (CHAR *) buffer_ptr, FX_OPEN_FOR_WRITE);
- /* Determine if there was an error. */
- if (status != FX_SUCCESS)
- {
+ /* Determine if there was an error. */
+ if (status != FX_SUCCESS)
+ {
- /* Create a new file. */
- status = fx_file_create(ftp_server_ptr -> nx_ftp_server_media_ptr, (CHAR *) buffer_ptr);
+ /* Create a new file. */
+ status = fx_file_create(ftp_server_ptr -> nx_ftp_server_media_ptr, (CHAR *) buffer_ptr);
- if (status == FX_SUCCESS)
- {
-
- /* Open the new file. */
- status = fx_file_open(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_request_file), (CHAR *) buffer_ptr, FX_OPEN_FOR_WRITE);
+ if (status == FX_SUCCESS)
+ {
+
+ /* Open the new file. */
+ status = fx_file_open(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_request_file), (CHAR *) buffer_ptr, FX_OPEN_FOR_WRITE);
+ }
}
- }
- /* Truncate the file to a size of 0. */
- status += fx_file_truncate(&(client_req_ptr -> nx_ftp_client_request_file), 0);
+ /* Truncate the file to a size of 0. */
+ status += fx_file_truncate(&(client_req_ptr -> nx_ftp_client_request_file), 0);
- /* Determine if the file create/open was successful. */
- if (status == FX_SUCCESS)
- {
-
- /* Check if passive transfer enabled. */
- if (client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled == NX_FALSE)
+ /* Determine if the file create/open was successful. */
+ if (status == FX_SUCCESS)
{
- /* Create an FTP client data socket. */
- status = nx_tcp_socket_create(ftp_server_ptr -> nx_ftp_server_ip_ptr, &(client_req_ptr -> nx_ftp_client_request_data_socket), "FTP Server Data Socket",
- NX_FTP_DATA_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, NX_FTP_DATA_WINDOW_SIZE, NX_NULL, _nx_ftp_server_data_disconnect);
-
- /* If no error is present, register the receive notify function. */
- if (status == NX_SUCCESS)
+ /* Check if passive transfer enabled. */
+ if (client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled == NX_FALSE)
{
+ if (client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_id)
+ {
- /* Make sure each socket points to the corresponding FTP server. */
- client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_reserved_ptr = ftp_server_ptr;
+ /* Socket already created. Error. */
+ status = NX_NOT_CLOSED;
+ }
+ else
+ {
- /* Register the receive function. */
- nx_tcp_socket_receive_notify(&(client_req_ptr -> nx_ftp_client_request_data_socket),
- _nx_ftp_server_data_present);
+ /* Create an FTP client data socket. */
+ status = nx_tcp_socket_create(ftp_server_ptr -> nx_ftp_server_ip_ptr, &(client_req_ptr -> nx_ftp_client_request_data_socket), "FTP Server Data Socket",
+ NX_FTP_DATA_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, NX_FTP_DATA_WINDOW_SIZE, NX_NULL, _nx_ftp_server_data_disconnect);
- /* Bind the socket to the FTP server data port. */
- status = nx_tcp_client_socket_bind(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_FTP_SERVER_DATA_PORT, NX_NO_WAIT);
+ /* If no error is present, register the receive notify function. */
+ if (status == NX_SUCCESS)
+ {
- /* Determine if the socket was bound. */
- if (status)
- {
+ /* Make sure each socket points to the corresponding FTP server. */
+ client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_reserved_ptr = ftp_server_ptr;
- /* FTP server data port is busy, use any data port. */
- nx_tcp_client_socket_bind(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_ANY_PORT, NX_NO_WAIT);
- }
- /* Now attempt to connect the data port to the client's data port. */
- status = nxd_tcp_client_socket_connect(&(client_req_ptr -> nx_ftp_client_request_data_socket),
- &(client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip),
- client_req_ptr -> nx_ftp_client_request_data_port, NX_FTP_SERVER_TIMEOUT);
+ /* Register the receive function. */
+ nx_tcp_socket_receive_notify(&(client_req_ptr -> nx_ftp_client_request_data_socket),
+ _nx_ftp_server_data_present);
+ /* Bind the socket to the FTP server data port. */
+ status = nx_tcp_client_socket_bind(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_FTP_SERVER_DATA_PORT, NX_NO_WAIT);
- /* Check for connect error. */
- if (status)
- {
- /* Yes, a connect error is present. Tear everything down. */
- nx_tcp_client_socket_unbind(&(client_req_ptr -> nx_ftp_client_request_data_socket));
- nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
- fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file));
+ /* Determine if the socket was bound. */
+ if (status)
+ {
+
+ /* FTP server data port is busy, use any data port. */
+ nx_tcp_client_socket_bind(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_ANY_PORT, NX_NO_WAIT);
+ }
+ /* Now attempt to connect the data port to the client's data port. */
+ status = nxd_tcp_client_socket_connect(&(client_req_ptr -> nx_ftp_client_request_data_socket),
+ &(client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip),
+ client_req_ptr -> nx_ftp_client_request_data_port, NX_FTP_SERVER_TIMEOUT);
+
+
+ /* Check for connect error. */
+ if (status)
+ {
+ /* Yes, a connect error is present. Tear everything down. */
+ nx_tcp_client_socket_unbind(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file));
#ifdef NX_FTP_FAULT_TOLERANT
- /* Flush the media. */
- fx_media_flush(ftp_server_ptr -> nx_ftp_server_media_ptr);
+ /* Flush the media. */
+ fx_media_flush(ftp_server_ptr -> nx_ftp_server_media_ptr);
#endif
- }
- else
- {
- /* Setup the data port with a specific packet transmit retry logic. */
- nx_tcp_socket_transmit_configure(&(client_req_ptr -> nx_ftp_client_request_data_socket),
- NX_FTP_SERVER_TRANSMIT_QUEUE_DEPTH,
- NX_FTP_SERVER_RETRY_SECONDS*NX_IP_PERIODIC_RATE,
- NX_FTP_SERVER_RETRY_MAX,
- NX_FTP_SERVER_RETRY_SHIFT);
+ }
+ else
+ {
+ /* Setup the data port with a specific packet transmit retry logic. */
+ nx_tcp_socket_transmit_configure(&(client_req_ptr -> nx_ftp_client_request_data_socket),
+ NX_FTP_SERVER_TRANSMIT_QUEUE_DEPTH,
+ NX_FTP_SERVER_RETRY_SECONDS*NX_IP_PERIODIC_RATE,
+ NX_FTP_SERVER_RETRY_MAX,
+ NX_FTP_SERVER_RETRY_SHIFT);
+ }
+ }
}
}
}
- }
-
- /* Now check and see if the open for write has any errors. */
- if (status == NX_SUCCESS)
- {
-
- /* The open for writing command is successful! */
-
- /* Set the open for write type in the client request structure. */
- client_req_ptr -> nx_ftp_client_request_open_type = NX_FTP_OPEN_FOR_WRITE;
-
- /* Set the total bytes field to zero. */
- client_req_ptr -> nx_ftp_client_request_total_bytes = 0;
-
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_START_XFER, "File Open for Write");
- }
- else
- {
- /* Unsuccessful open for writing command. */
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "File Open Failed");
- }
+ /* Now check and see if the open for write has any errors. */
+ if (status == NX_SUCCESS)
+ {
- break;
- }
+ /* The open for writing command is successful! */
+
+ /* Set the open for write type in the client request structure. */
+ client_req_ptr -> nx_ftp_client_request_open_type = NX_FTP_OPEN_FOR_WRITE;
- case NX_FTP_RNFR:
- {
+ /* Set the total bytes field to zero. */
+ client_req_ptr -> nx_ftp_client_request_total_bytes = 0;
- /* Check packet length. */
- if (packet_ptr -> nx_packet_length == 0)
- {
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_START_XFER, "File Open for Write");
+ }
+ else
+ {
+ /* Unsuccessful open for writing command. */
- /* Empty message. */
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "File Open Failed");
+ }
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "Rename File not found");
break;
}
-
- /* Change to the default directory of this connection. */
- fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
-
- /* Setup pointer to packet buffer area. */
- buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- /* Find the end of the message. */
- j = 0;
- while (j < packet_ptr -> nx_packet_length - 1)
+ case NX_FTP_RNFR:
{
- /* Determine if a CR/LF is present. */
- if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
- break;
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
- /* Move to next character. */
- j++;
- }
+ /* Empty message. */
- /* If specified path ends with slash or backslash, strip it. */
- if ((j > 1) && ((buffer_ptr[j - 1] == '/') || (buffer_ptr[j - 1] == '\\')))
- {
- j--;
- }
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Rename File not found");
+ break;
+ }
+
+ /* Change to the default directory of this connection. */
+ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
- /* Ensure the name is NULL terminated. */
- buffer_ptr[j] = NX_NULL;
+ /* Setup pointer to packet buffer area. */
+ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- /* Read the file attributes to see if it is actually there. */
- status = fx_file_attributes_read(ftp_server_ptr -> nx_ftp_server_media_ptr, (CHAR *) buffer_ptr, &j);
+ /* Find the end of the message. */
+ j = 0;
+ while (j < packet_ptr -> nx_packet_length - 1)
+ {
- /* If not a file, read the directory attributes. */
- if (status == FX_NOT_A_FILE)
- status = fx_directory_attributes_read(ftp_server_ptr -> nx_ftp_server_media_ptr, (CHAR *) buffer_ptr, &j);
+ /* Determine if a CR/LF is present. */
+ if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
+ break;
- /* Determine if it was successful. */
- if (status == NX_SUCCESS)
- {
+ /* Move to next character. */
+ j++;
+ }
- /* Successful start to the file rename. */
+ /* If specified path ends with slash or backslash, strip it. */
+ if ((j > 1) && ((buffer_ptr[j - 1] == '/') || (buffer_ptr[j - 1] == '\\')))
+ {
+ j--;
+ }
- /* Save the packet in the client request structure. */
- client_req_ptr -> nx_ftp_client_request_packet = packet_ptr;
+ /* Ensure the name is NULL terminated. */
+ buffer_ptr[j] = NX_NULL;
- /* Allocate a new packet. */
- _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
+ /* Read the file attributes to see if it is actually there. */
+ status = fx_file_attributes_read(ftp_server_ptr -> nx_ftp_server_media_ptr, (CHAR *) buffer_ptr, &j);
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_FILE_PEND, "Rename File From");
- }
- else
- {
+ /* If not a file, read the directory attributes. */
+ if (status == FX_NOT_A_FILE)
+ status = fx_directory_attributes_read(ftp_server_ptr -> nx_ftp_server_media_ptr, (CHAR *) buffer_ptr, &j);
- /* Unsuccessful first half of file rename. */
+ /* Determine if it was successful. */
+ if (status == NX_SUCCESS)
+ {
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "Rename File not found");
- }
- break;
- }
+ /* Successful start to the file rename. */
- case NX_FTP_RNTO:
- {
+ /* Save the packet in the client request structure. */
+ client_req_ptr -> nx_ftp_client_request_packet = packet_ptr;
- /* Check packet length. */
- if (packet_ptr -> nx_packet_length == 0)
- {
+ /* Allocate a new packet. */
+ _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
- /* Empty message. */
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_FILE_PEND, "Rename File From");
+ }
+ else
+ {
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "Rename failed");
+ /* Unsuccessful first half of file rename. */
+
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Rename File not found");
+ }
break;
}
-
- /* Change to the default directory of this connection. */
- fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
-
- /* Setup pointer to packet buffer area. */
- buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- /* Find the end of the message. */
- j = 0;
- while (j < packet_ptr -> nx_packet_length - 1)
+ case NX_FTP_RNTO:
{
- /* Determine if a CR/LF is present. */
- if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
+
+ /* Empty message. */
+
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Rename failed");
break;
+ }
+
+ /* Change to the default directory of this connection. */
+ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
- /* Move to next character. */
- j++;
- }
+ /* Setup pointer to packet buffer area. */
+ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- /* If specified path ends with slash or backslash, strip it. */
- if ((j > 1) && ((buffer_ptr[j - 1] == '/') || (buffer_ptr[j - 1] == '\\')))
- {
- j--;
- }
+ /* Find the end of the message. */
+ j = 0;
+ while (j < packet_ptr -> nx_packet_length - 1)
+ {
+
+ /* Determine if a CR/LF is present. */
+ if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
+ break;
+
+ /* Move to next character. */
+ j++;
+ }
- /* Ensure the name is NULL terminated. */
- buffer_ptr[j] = NX_NULL;
+ /* If specified path ends with slash or backslash, strip it. */
+ if ((j > 1) && ((buffer_ptr[j - 1] == '/') || (buffer_ptr[j - 1] == '\\')))
+ {
+ j--;
+ }
- /* Rename the file. */
- status = fx_file_rename(ftp_server_ptr -> nx_ftp_server_media_ptr, (CHAR *) (client_req_ptr -> nx_ftp_client_request_packet) -> nx_packet_prepend_ptr, (CHAR *) buffer_ptr);
+ /* Ensure the name is NULL terminated. */
+ buffer_ptr[j] = NX_NULL;
+
+ /* Rename the file. */
+ status = fx_file_rename(ftp_server_ptr -> nx_ftp_server_media_ptr, (CHAR *) (client_req_ptr -> nx_ftp_client_request_packet) -> nx_packet_prepend_ptr, (CHAR *) buffer_ptr);
- /* If not a file, rename the directory. */
- if (status == FX_NOT_A_FILE)
- status = fx_directory_rename(ftp_server_ptr -> nx_ftp_server_media_ptr, (CHAR *) (client_req_ptr -> nx_ftp_client_request_packet) -> nx_packet_prepend_ptr, (CHAR *) buffer_ptr);
+ /* If not a file, rename the directory. */
+ if (status == FX_NOT_A_FILE)
+ status = fx_directory_rename(ftp_server_ptr -> nx_ftp_server_media_ptr, (CHAR *) (client_req_ptr -> nx_ftp_client_request_packet) -> nx_packet_prepend_ptr, (CHAR *) buffer_ptr);
#ifdef NX_FTP_FAULT_TOLERANT
- /* Flush the media. */
- fx_media_flush(ftp_server_ptr -> nx_ftp_server_media_ptr);
+ /* Flush the media. */
+ fx_media_flush(ftp_server_ptr -> nx_ftp_server_media_ptr);
#endif
- /* Release the packet in the client request structure. */
- nx_packet_release(client_req_ptr -> nx_ftp_client_request_packet);
- client_req_ptr -> nx_ftp_client_request_packet = NX_NULL;
+ /* Release the packet in the client request structure. */
+ nx_packet_release(client_req_ptr -> nx_ftp_client_request_packet);
+ client_req_ptr -> nx_ftp_client_request_packet = NX_NULL;
- /* Determine if it was successful. */
- if (status == NX_SUCCESS)
- {
+ /* Determine if it was successful. */
+ if (status == NX_SUCCESS)
+ {
- /* Successful file rename. */
+ /* Successful file rename. */
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_COMPLETED, "File Renamed");
- }
- else
- {
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_COMPLETED, "File Renamed");
+ }
+ else
+ {
- /* Unsuccessful file rename. */
+ /* Unsuccessful file rename. */
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "Rename failed");
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Rename failed");
+ }
+ break;
}
- break;
- }
- case NX_FTP_DELE:
- {
-
- /* Check packet length. */
- if (packet_ptr -> nx_packet_length == 0)
+ case NX_FTP_DELE:
{
- /* Empty message. */
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "Delete Failed");
- break;
- }
-
- /* Change to the default directory of this connection. */
- fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
+ /* Empty message. */
- /* Setup pointer to packet buffer area. */
- buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Delete Failed");
+ break;
+ }
+
+ /* Change to the default directory of this connection. */
+ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
- /* Find the end of the message. */
- j = 0;
- while (j < packet_ptr -> nx_packet_length - 1)
- {
+ /* Setup pointer to packet buffer area. */
+ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- /* Determine if a CR/LF is present. */
- if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
- break;
+ /* Find the end of the message. */
+ j = 0;
+ while (j < packet_ptr -> nx_packet_length - 1)
+ {
- /* Move to next character. */
- j++;
- }
+ /* Determine if a CR/LF is present. */
+ if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
+ break;
- /* Ensure the name is NULL terminated. */
- buffer_ptr[j] = NX_NULL;
+ /* Move to next character. */
+ j++;
+ }
+
+ /* Ensure the name is NULL terminated. */
+ buffer_ptr[j] = NX_NULL;
- /* Remove the specified file. */
- status = fx_file_delete(ftp_server_ptr -> nx_ftp_server_media_ptr, (CHAR *) buffer_ptr);
+ /* Remove the specified file. */
+ status = fx_file_delete(ftp_server_ptr -> nx_ftp_server_media_ptr, (CHAR *) buffer_ptr);
#ifdef NX_FTP_FAULT_TOLERANT
- /* Flush the media. */
- fx_media_flush(ftp_server_ptr -> nx_ftp_server_media_ptr);
+ /* Flush the media. */
+ fx_media_flush(ftp_server_ptr -> nx_ftp_server_media_ptr);
#endif
- /* Determine if it was successful. */
- if (status == NX_SUCCESS)
- {
+ /* Determine if it was successful. */
+ if (status == NX_SUCCESS)
+ {
- /* Successful delete file. */
+ /* Successful delete file. */
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_COMPLETED, "File Deleted");
- }
- else
- {
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_COMPLETED, "File Deleted");
+ }
+ else
+ {
- /* Unsuccessful file delete. */
+ /* Unsuccessful file delete. */
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "Delete Failed");
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Delete Failed");
+ }
+ break;
}
- break;
- }
- case NX_FTP_RMD:
- {
-
- /* Check packet length. */
- if (packet_ptr -> nx_packet_length == 0)
+ case NX_FTP_RMD:
{
- /* Empty message. */
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "Delete Directory Fail");
- break;
- }
-
- /* Change to the default directory of this connection. */
- fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
+ /* Empty message. */
- /* Setup pointer to packet buffer area. */
- buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Delete Directory Fail");
+ break;
+ }
+
+ /* Change to the default directory of this connection. */
+ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
- /* Find the end of the message. */
- j = 0;
- while (j < packet_ptr -> nx_packet_length - 1)
- {
+ /* Setup pointer to packet buffer area. */
+ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- /* Determine if a CR/LF is present. */
- if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
- break;
+ /* Find the end of the message. */
+ j = 0;
+ while (j < packet_ptr -> nx_packet_length - 1)
+ {
- /* Move to next character. */
- j++;
- }
+ /* Determine if a CR/LF is present. */
+ if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
+ break;
- /* If specified path ends with slash or backslash, strip it. */
- if ((j > 1) && ((buffer_ptr[j - 1] == '/') || (buffer_ptr[j - 1] == '\\')))
- {
- j--;
- }
+ /* Move to next character. */
+ j++;
+ }
+
+ /* If specified path ends with slash or backslash, strip it. */
+ if ((j > 1) && ((buffer_ptr[j - 1] == '/') || (buffer_ptr[j - 1] == '\\')))
+ {
+ j--;
+ }
- /* Ensure the name is NULL terminated. */
- buffer_ptr[j] = NX_NULL;
+ /* Ensure the name is NULL terminated. */
+ buffer_ptr[j] = NX_NULL;
- /* Remove the specified directory. */
- status = fx_directory_delete(ftp_server_ptr -> nx_ftp_server_media_ptr, (CHAR *) buffer_ptr);
+ /* Remove the specified directory. */
+ status = fx_directory_delete(ftp_server_ptr -> nx_ftp_server_media_ptr, (CHAR *) buffer_ptr);
#ifdef NX_FTP_FAULT_TOLERANT
- /* Flush the media. */
- fx_media_flush(ftp_server_ptr -> nx_ftp_server_media_ptr);
+ /* Flush the media. */
+ fx_media_flush(ftp_server_ptr -> nx_ftp_server_media_ptr);
#endif
- /* Determine if it was successful. */
- if (status == NX_SUCCESS)
- {
+ /* Determine if it was successful. */
+ if (status == NX_SUCCESS)
+ {
- /* Successful delete directory. */
+ /* Successful delete directory. */
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_COMPLETED, "Directory Deleted");
- }
- else
- {
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_COMPLETED, "Directory Deleted");
+ }
+ else
+ {
- /* Unsuccessful directory delete. */
+ /* Unsuccessful directory delete. */
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "Delete Directory Fail");
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Delete Directory Fail");
+ }
+ break;
}
- break;
- }
- case NX_FTP_MKD:
- {
-
- /* Check packet length. */
- if (packet_ptr -> nx_packet_length == 0)
+ case NX_FTP_MKD:
{
- /* Empty message. */
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "Directory Create failed");
- break;
- }
-
- /* Change to the default directory of this connection. */
- fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
+ /* Empty message. */
- /* Setup pointer to packet buffer area. */
- buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Directory Create failed");
+ break;
+ }
+
+ /* Change to the default directory of this connection. */
+ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
- /* Find the end of the message. */
- j = 0;
- while (j < packet_ptr -> nx_packet_length - 1)
- {
+ /* Setup pointer to packet buffer area. */
+ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- /* Determine if a CR/LF is present. */
- if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
- break;
+ /* Find the end of the message. */
+ j = 0;
+ while (j < packet_ptr -> nx_packet_length - 1)
+ {
- /* Move to next character. */
- j++;
- }
+ /* Determine if a CR/LF is present. */
+ if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
+ break;
- /* If specified path ends with slash or backslash, strip it. */
- if ((j > 1) && ((buffer_ptr[j - 1] == '/') || (buffer_ptr[j - 1] == '\\')))
- {
- j--;
- }
+ /* Move to next character. */
+ j++;
+ }
+
+ /* If specified path ends with slash or backslash, strip it. */
+ if ((j > 1) && ((buffer_ptr[j - 1] == '/') || (buffer_ptr[j - 1] == '\\')))
+ {
+ j--;
+ }
- /* Ensure the name is NULL terminated. */
- buffer_ptr[j] = NX_NULL;
+ /* Ensure the name is NULL terminated. */
+ buffer_ptr[j] = NX_NULL;
- /* Create the specified directory. */
- status = fx_directory_create(ftp_server_ptr -> nx_ftp_server_media_ptr, (CHAR *) buffer_ptr);
+ /* Create the specified directory. */
+ status = fx_directory_create(ftp_server_ptr -> nx_ftp_server_media_ptr, (CHAR *) buffer_ptr);
#ifdef NX_FTP_FAULT_TOLERANT
- /* Flush the media. */
- fx_media_flush(ftp_server_ptr -> nx_ftp_server_media_ptr);
+ /* Flush the media. */
+ fx_media_flush(ftp_server_ptr -> nx_ftp_server_media_ptr);
#endif
- /* Determine if it was successful. */
- if (status == NX_SUCCESS)
- {
+ /* Determine if it was successful. */
+ if (status == NX_SUCCESS)
+ {
- FX_LOCAL_PATH temporary_path;
+ FX_LOCAL_PATH temporary_path;
- /* Successful create directory. */
+ /* Successful create directory. */
- /* Change the path to the new directory, using a temporary directory structure */
- status = fx_directory_local_path_set(ftp_server_ptr -> nx_ftp_server_media_ptr, &temporary_path, (CHAR *) buffer_ptr);
+ /* Change the path to the new directory, using a temporary directory structure */
+ status = fx_directory_local_path_set(ftp_server_ptr -> nx_ftp_server_media_ptr, &temporary_path, (CHAR *) buffer_ptr);
- /* Determine if it was successful. */
- if (status == NX_SUCCESS)
- {
+ /* Determine if it was successful. */
+ if (status == NX_SUCCESS)
+ {
- CHAR *local_dir;
+ CHAR *local_dir;
- /* Successful change directory. */
+ /* Successful change directory. */
- /* Get the actual path */
- fx_directory_local_path_get(ftp_server_ptr -> nx_ftp_server_media_ptr, &local_dir);
+ /* Get the actual path */
+ fx_directory_local_path_get(ftp_server_ptr -> nx_ftp_server_media_ptr, &local_dir);
- /* Now send a successful response to the client. */
- _nx_ftp_server_directory_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_CMD_OK, "Directory Created", local_dir);
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_directory_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_CMD_OK, "Directory Created", local_dir);
+ }
+ else
+ {
+ /* Unsuccessful directory change. */
+
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Set New Directory Fail");
+ }
+
+ /* Restore the default directory of this connection. */
+ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
}
else
{
- /* Unsuccessful directory change. */
+
+ /* Unsuccessful directory create. */
/* Now send an error response to the client. */
_nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "Set New Directory Fail");
+ NX_FTP_CODE_BAD_FILE, "Directory Create failed");
}
-
- /* Restore the default directory of this connection. */
- fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
- }
- else
- {
-
- /* Unsuccessful directory create. */
-
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "Directory Create failed");
- }
- break;
- }
-
- case NX_FTP_NLST:
- {
-
- /* Assume ASCII and relax restriction. */
- if ((client_req_ptr -> nx_ftp_client_request_transfer_type != 'A') &&
- (client_req_ptr -> nx_ftp_client_request_transfer_type != 'I'))
- {
-
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_TYPE, "Only ASCII Listing allowed");
-
- /* And we are done processing. */
break;
}
- /* Check packet length. */
- if (packet_ptr -> nx_packet_length == 0)
+ case NX_FTP_NLST:
{
+
+ /* Assume ASCII and relax restriction. */
+ if ((client_req_ptr -> nx_ftp_client_request_transfer_type != 'A') &&
+ (client_req_ptr -> nx_ftp_client_request_transfer_type != 'I'))
+ {
- /* Empty message. */
-
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "List bad Directory");
- break;
- }
-
- /* Change to the default directory of this connection. */
- fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
-
- /* Setup pointer to packet buffer area. */
- buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
-
- /* Find the end of the message. */
- j = 0;
- while (j < packet_ptr -> nx_packet_length - 1)
- {
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_TYPE, "Only ASCII Listing allowed");
- /* Determine if a CR/LF is present. */
- if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
+ /* And we are done processing. */
break;
+ }
- /* Move to next character. */
- j++;
- }
-
- /* If specified path ends with slash or backslash, strip it. */
- if ((j > 1) && ((buffer_ptr[j - 1] == '/') || (buffer_ptr[j - 1] == '\\')))
- {
- j--;
- }
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
- /* Determine if there is a directory path. */
- if (j)
- {
+ /* Empty message. */
- /* Ensure the name is NULL terminated. */
- buffer_ptr[j] = NX_NULL;
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "List bad Directory");
+ break;
+ }
- /* Set the path to the supplied directory. */
- status = fx_directory_local_path_set(ftp_server_ptr -> nx_ftp_server_media_ptr, &temp_path, (CHAR *) buffer_ptr);
- }
- else
- {
+ /* Change to the default directory of this connection. */
+ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
- /* Just set the buffer pointer to NULL since there isn't a string. */
- buffer_ptr = NX_NULL;
+ /* Setup pointer to packet buffer area. */
+ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- /* Default status to success. */
- status = FX_SUCCESS;
- }
+ /* Find the end of the message. */
+ j = 0;
+ while (j < packet_ptr -> nx_packet_length - 1)
+ {
+ /* Determine if a CR/LF is present. */
+ if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
+ break;
- /* Determine if the path setup was successful. */
- if (status == FX_SUCCESS)
- {
+ /* Move to next character. */
+ j++;
+ }
- /* Check if passive transfer enabled. */
- if (client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled == NX_TRUE)
+ /* If specified path ends with slash or backslash, strip it. */
+ if ((j > 1) && ((buffer_ptr[j - 1] == '/') || (buffer_ptr[j - 1] == '\\')))
{
+ j--;
+ }
- /* Now wait for the data connection to connect. */
- status = nx_tcp_socket_state_wait(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_TCP_ESTABLISHED, NX_FTP_SERVER_TIMEOUT);
+ /* Determine if there is a directory path. */
+ if (j)
+ {
- /* Check for connect error. */
- if (status)
- {
+ /* Ensure the name is NULL terminated. */
+ buffer_ptr[j] = NX_NULL;
- /* Yes, a connect error is present. Tear everything down. */
- nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_ftp_client_request_data_socket));
- nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_port);
- nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
- fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file));
- }
+ /* Set the path to the supplied directory. */
+ status = fx_directory_local_path_set(ftp_server_ptr -> nx_ftp_server_media_ptr, &temp_path, (CHAR *) buffer_ptr);
}
else
{
- /* Create an FTP client data socket. */
- status = nx_tcp_socket_create(ftp_server_ptr -> nx_ftp_server_ip_ptr, &(client_req_ptr -> nx_ftp_client_request_data_socket), "FTP Server Data Socket",
- NX_FTP_DATA_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, NX_FTP_DATA_WINDOW_SIZE, NX_NULL, NX_NULL);
-
- /* If no error is present, register the receive notify function. */
- if (status == NX_SUCCESS)
- {
+ /* Just set the buffer pointer to NULL since there isn't a string. */
+ buffer_ptr = NX_NULL;
- /* Make sure each socket points to the corresponding FTP server. */
- client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_reserved_ptr = ftp_server_ptr;
+ /* Default status to success. */
+ status = FX_SUCCESS;
+ }
- /* Bind the socket to the FTP server data port. */
- status = nx_tcp_client_socket_bind(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_FTP_SERVER_DATA_PORT, NX_NO_WAIT);
- /* Determine if the socket was bound. */
- if (status)
- {
+ /* Determine if the path setup was successful. */
+ if (status == FX_SUCCESS)
+ {
- /* FTP server data port is busy, use any data port. */
- nx_tcp_client_socket_bind(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_ANY_PORT, NX_NO_WAIT);
- }
- /* Now attempt to connect the data port to the client's data port. */
- status = nxd_tcp_client_socket_connect(&(client_req_ptr -> nx_ftp_client_request_data_socket),
- &(client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip),
- client_req_ptr -> nx_ftp_client_request_data_port, NX_FTP_SERVER_TIMEOUT);
+ /* Check if passive transfer enabled. */
+ if (client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled == NX_TRUE)
+ {
+ /* Now wait for the data connection to connect. */
+ status = nx_tcp_socket_state_wait(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_TCP_ESTABLISHED, NX_FTP_SERVER_TIMEOUT);
/* Check for connect error. */
if (status)
{
- /* Yes, a connect error is present. Tear everything down. */
- nx_tcp_client_socket_unbind(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ /* Yes, a connect error is present. Tear everything down. */
+ nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_port);
nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
- fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file));
+ fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file));
}
- else
- {
+ }
+ else if (client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_id)
+ {
- /* Setup the data port with a specific packet transmit retry logic. */
- nx_tcp_socket_transmit_configure(&(client_req_ptr -> nx_ftp_client_request_data_socket),
- NX_FTP_SERVER_TRANSMIT_QUEUE_DEPTH,
- NX_FTP_SERVER_RETRY_SECONDS*NX_IP_PERIODIC_RATE,
- NX_FTP_SERVER_RETRY_MAX,
- NX_FTP_SERVER_RETRY_SHIFT);
- }
+ /* Socket already created. Error. */
+ status = NX_NOT_CLOSED;
}
- }
- }
+ else
+ {
- /* Now check and see if the directory listing command has any errors. */
- if (status == NX_SUCCESS)
- {
+ /* Create an FTP client data socket. */
+ status = nx_tcp_socket_create(ftp_server_ptr -> nx_ftp_server_ip_ptr, &(client_req_ptr -> nx_ftp_client_request_data_socket), "FTP Server Data Socket",
+ NX_FTP_DATA_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, NX_FTP_DATA_WINDOW_SIZE, NX_NULL, NX_NULL);
- /* The directory listing is successful! */
+ /* If no error is present, register the receive notify function. */
+ if (status == NX_SUCCESS)
+ {
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_START_XFER, "Sending List");
+ /* Make sure each socket points to the corresponding FTP server. */
+ client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_reserved_ptr = ftp_server_ptr;
- /* Determine if the block mode is enabled. */
- if (client_req_ptr -> nx_ftp_client_request_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
- {
+ /* Bind the socket to the FTP server data port. */
+ status = nx_tcp_client_socket_bind(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_FTP_SERVER_DATA_PORT, NX_NO_WAIT);
- /* Get the directory listing size. */
- _nx_ftp_server_block_size_get(ftp_server_ptr, ftp_command, filename, &block_size);
+ /* Determine if the socket was bound. */
+ if (status)
+ {
- /* Send start block header for file size. */
- if (block_size)
- _nx_ftp_server_block_header_send(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, block_size);
- }
+ /* FTP server data port is busy, use any data port. */
+ nx_tcp_client_socket_bind(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_ANY_PORT, NX_NO_WAIT);
+ }
+ /* Now attempt to connect the data port to the client's data port. */
+ status = nxd_tcp_client_socket_connect(&(client_req_ptr -> nx_ftp_client_request_data_socket),
+ &(client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip),
+ client_req_ptr -> nx_ftp_client_request_data_port, NX_FTP_SERVER_TIMEOUT);
- /* Allocate a new packet. */
- status = _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
- /* Calculate the remaining length. */
- remaining_length = (ULONG)((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_append_ptr) - NX_PHYSICAL_TRAILER);
+ /* Check for connect error. */
+ if (status)
+ {
- /* Determine if the advertised MSS is even less. */
- if (remaining_length > client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss)
- {
+ /* Yes, a connect error is present. Tear everything down. */
+ nx_tcp_client_socket_unbind(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file));
+ }
+ else
+ {
- /* Reduce the remaining length to the MSS value. */
- remaining_length = client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss;
+ /* Setup the data port with a specific packet transmit retry logic. */
+ nx_tcp_socket_transmit_configure(&(client_req_ptr -> nx_ftp_client_request_data_socket),
+ NX_FTP_SERVER_TRANSMIT_QUEUE_DEPTH,
+ NX_FTP_SERVER_RETRY_SECONDS*NX_IP_PERIODIC_RATE,
+ NX_FTP_SERVER_RETRY_MAX,
+ NX_FTP_SERVER_RETRY_SHIFT);
+ }
+ }
+ }
}
- /* Now generate the full directory listing and send the contents to the client. */
- j = 0;
- while (status == NX_SUCCESS)
+ /* Now check and see if the directory listing command has any errors. */
+ if (status == NX_SUCCESS)
{
- /* Pickup the next directory entry. */
- if (j == 0)
- {
+ /* The directory listing is successful! */
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_START_XFER, "Sending List");
- /* First directory entry. */
- status = fx_directory_first_full_entry_find(ftp_server_ptr -> nx_ftp_server_media_ptr, filename,
- &attributes, &size, &year, &month, &day, &hour, &minute, &second);
-
- }
- else
+ /* Determine if the block mode is enabled. */
+ if (client_req_ptr -> nx_ftp_client_request_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
{
- /* Not the first entry - pickup the next! */
- status = fx_directory_next_full_entry_find(ftp_server_ptr -> nx_ftp_server_media_ptr, filename,
- &attributes, &size, &year, &month, &day, &hour, &minute, &second);
+ /* Get the directory listing size. */
+ _nx_ftp_server_block_size_get(ftp_server_ptr, ftp_command, filename, &block_size);
+ /* Send start block header for file size. */
+ if (block_size)
+ _nx_ftp_server_block_header_send(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, block_size);
}
- /* Increment the entry count. */
- j++;
+ /* Allocate a new packet. */
+ status = _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
- /* Determine if successful. */
- if (status == NX_SUCCESS)
+ /* Calculate the remaining length. */
+ remaining_length = (ULONG)((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_append_ptr) - NX_PHYSICAL_TRAILER);
+
+ /* Determine if the advertised MSS is even less. */
+ if (remaining_length > client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss)
{
- /* Setup pointer to buffer. */
- buffer_ptr = packet_ptr -> nx_packet_append_ptr;
+ /* Reduce the remaining length to the MSS value. */
+ remaining_length = client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss;
+ }
+
+ /* Now generate the full directory listing and send the contents to the client. */
+ j = 0;
+ while (status == NX_SUCCESS)
+ {
- /* Calculate the size of the name. */
- length = 0;
- do
+ /* Pickup the next directory entry. */
+ if (j == 0)
{
- if (filename[length])
- length++;
- else
- break;
- } while (length < FX_MAX_LONG_NAME_LEN);
- /* Make sure there is enough space for the file name. */
- if ((length + 2) > remaining_length)
+
+ /* First directory entry. */
+ status = fx_directory_first_full_entry_find(ftp_server_ptr -> nx_ftp_server_media_ptr, filename,
+ &attributes, &size, &year, &month, &day, &hour, &minute, &second);
+
+ }
+ else
{
- /* Send the current buffer out. */
+ /* Not the first entry - pickup the next! */
+ status = fx_directory_next_full_entry_find(ftp_server_ptr -> nx_ftp_server_media_ptr, filename,
+ &attributes, &size, &year, &month, &day, &hour, &minute, &second);
- /* Send the directory data to the client. */
- status = nx_tcp_socket_send(&(client_req_ptr -> nx_ftp_client_request_data_socket),
- packet_ptr, NX_FTP_SERVER_TIMEOUT);
+ }
- /* Determine if the send was unsuccessful. */
- if (status)
- {
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
- }
+ /* Increment the entry count. */
+ j++;
- /* Allocate a new packet. */
- status = _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
+ /* Determine if successful. */
+ if (status == NX_SUCCESS)
+ {
- /* Determine if the packet allocate was successfull. */
- if (status)
+ /* Setup pointer to buffer. */
+ buffer_ptr = packet_ptr -> nx_packet_append_ptr;
+
+ /* Calculate the size of the name. */
+ length = 0;
+ do
{
+ if (filename[length])
+ length++;
+ else
+ break;
+ } while (length < FX_MAX_LONG_NAME_LEN);
- /* Get out of the loop! */
- break;
- }
+ /* Make sure there is enough space for the file name. */
+ if ((length + 2) > remaining_length)
+ {
- /* Calculate the remaining length. */
- remaining_length = (ULONG)((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_append_ptr) - NX_PHYSICAL_TRAILER);
+ /* Send the current buffer out. */
- /* Determine if the advertised MSS is even less. */
- if (remaining_length > client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss)
- {
+ /* Send the directory data to the client. */
+ status = nx_tcp_socket_send(&(client_req_ptr -> nx_ftp_client_request_data_socket),
+ packet_ptr, NX_FTP_SERVER_TIMEOUT);
- /* Reduce the remaining length to the MSS value. */
- remaining_length = client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss;
- }
+ /* Determine if the send was unsuccessful. */
+ if (status)
+ {
+
+ /* Release the packet. */
+ nx_packet_release(packet_ptr);
+ }
- /* Setup pointer to buffer. */
- buffer_ptr = packet_ptr -> nx_packet_append_ptr;
- }
+ /* Allocate a new packet. */
+ status = _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
+
+ /* Determine if the packet allocate was successful. */
+ if (status)
+ {
+
+ /* Get out of the loop! */
+ break;
+ }
+
+ /* Calculate the remaining length. */
+ remaining_length = (ULONG)((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_append_ptr) - NX_PHYSICAL_TRAILER);
+
+ /* Determine if the advertised MSS is even less. */
+ if (remaining_length > client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss)
+ {
+
+ /* Reduce the remaining length to the MSS value. */
+ remaining_length = client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss;
+ }
+
+ /* Setup pointer to buffer. */
+ buffer_ptr = packet_ptr -> nx_packet_append_ptr;
+ }
- /* Put the file name and cr/lf in the buffer*/
- memcpy(buffer_ptr, filename, length); /* Use case of memcpy is verified. */
- buffer_ptr[length++] = '\r';
- buffer_ptr[length++] = '\n';
+ /* Put the file name and cr/lf in the buffer*/
+ memcpy(buffer_ptr, filename, length); /* Use case of memcpy is verified. */
+ buffer_ptr[length++] = '\r';
+ buffer_ptr[length++] = '\n';
- /* Set the packet length. */
- packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + length;
+ /* Set the packet length. */
+ packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + length;
- /* Setup the packet append pointer. */
- packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_append_ptr + length;
+ /* Setup the packet append pointer. */
+ packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_append_ptr + length;
- /* Adjust the remaining length. */
- remaining_length = remaining_length - length;
+ /* Adjust the remaining length. */
+ if (remaining_length > length)
+ {
+ remaining_length = remaining_length - length;
+ }
+ else
+ {
+ remaining_length = 0;
+ }
+ }
}
- }
- /* Now determine if the directory listing was a success. */
- if ((status == FX_NO_MORE_ENTRIES) && (packet_ptr) && (packet_ptr -> nx_packet_length))
- {
+ /* Now determine if the directory listing was a success. */
+ if ((status == FX_NO_MORE_ENTRIES) && (packet_ptr) && (packet_ptr -> nx_packet_length))
+ {
- no_more_ftp_entries = NX_TRUE;
+ no_more_ftp_entries = NX_TRUE;
- /* Send the directory data to the client. */
- status = nx_tcp_socket_send(&(client_req_ptr -> nx_ftp_client_request_data_socket),
- packet_ptr, NX_FTP_SERVER_TIMEOUT);
+ /* Send the directory data to the client. */
+ status = nx_tcp_socket_send(&(client_req_ptr -> nx_ftp_client_request_data_socket),
+ packet_ptr, NX_FTP_SERVER_TIMEOUT);
- /* Determine if the send was unsuccessful. */
- if (status)
+ /* Determine if the send was unsuccessful. */
+ if (status)
+ {
+
+ /* Release the packet. */
+ nx_packet_release(packet_ptr);
+ }
+ }
+ else if (packet_ptr)
{
- /* Release the packet. */
+ /* Release packet just in case! */
nx_packet_release(packet_ptr);
}
- }
- else if (packet_ptr)
- {
- /* Release packet just in case! */
- nx_packet_release(packet_ptr);
- }
+ /* Determine if the block mode is enabled. */
+ if (client_req_ptr -> nx_ftp_client_request_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
+ {
- /* Determine if the block mode is enabled. */
- if (client_req_ptr -> nx_ftp_client_request_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
- {
+ /* Send end block header for file size. */
+ _nx_ftp_server_block_header_send(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, 0);
+ }
- /* Send end block header for file size. */
- _nx_ftp_server_block_header_send(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, 0);
- }
+ /* Clean up the data socket. */
+ _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr);
- /* Clean up the data socket. */
- _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr);
+ /* Allocate a new packet. */
+ _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
- /* Allocate a new packet. */
- _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
+ /* Now determine if the directory listing was a success (e..g runs until no more entries found). */
+ if (no_more_ftp_entries)
+ {
- /* Now determine if the directory listing was a success (e..g runs until no more entries found). */
- if (no_more_ftp_entries)
- {
+ /* The directory listing was successful! */
- /* The directory listing was successful! */
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_COMPLETED, "List End");
+ }
+ else
+ {
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_COMPLETED, "List End");
+ /* Directory listing command failed. */
+
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "List fail");
+ }
}
else
{
-
- /* Directory listing command failed. */
+ /* Unsuccessful directory listing command. */
/* Now send an error response to the client. */
_nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "List fail");
+ NX_FTP_CODE_BAD_FILE, "List bad Directory");
}
- }
- else
- {
- /* Unsuccessful directory listing command. */
-
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "List bad Directory");
- }
- break;
- }
-
- case NX_FTP_LIST:
- {
-
- /* Assume ASCII and relax restriction. */
- if ((client_req_ptr -> nx_ftp_client_request_transfer_type != 'A') &&
- (client_req_ptr -> nx_ftp_client_request_transfer_type != 'I'))
- {
-
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_TYPE, "Only ASCII Listing allowed");
-
- /* And we are done processing. */
break;
}
- /* Check packet length. */
- if (packet_ptr -> nx_packet_length == 0)
- {
-
- /* Empty message. */
-
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "Bad Directory");
- break;
- }
-
- /* Change to the default directory of this connection. */
- status = fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
-
- /* Setup pointer to packet buffer area. */
- buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
-
- /* Find the end of the message. */
- j = 0;
- k = -1;
- while (j < packet_ptr -> nx_packet_length - 1)
+ case NX_FTP_LIST:
{
+
+ /* Assume ASCII and relax restriction. */
+ if ((client_req_ptr -> nx_ftp_client_request_transfer_type != 'A') &&
+ (client_req_ptr -> nx_ftp_client_request_transfer_type != 'I'))
+ {
- /* Determine if a slash or backslash is present. */
- if ((buffer_ptr[j] == '/') || (buffer_ptr[j] == '\\'))
- k = (INT)j;
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_TYPE, "Only ASCII Listing allowed");
- /* Determine if a CR/LF is present. */
- if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
+ /* And we are done processing. */
break;
+ }
- /* Move to next character. */
- j++;
- }
-
- /* If specified path ends with slash or backslash, strip it. */
- if ((j > 1) && ((buffer_ptr[j - 1] == '/') || (buffer_ptr[j - 1] == '\\')))
- {
- j--;
- }
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
- /* Default the single file specified flag to false. */
- single_file = NX_FALSE;
+ /* Empty message. */
- /* Determine if there is a directory path. */
- if (j)
- {
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Bad Directory");
+ break;
+ }
- /* Ensure the name is NULL terminated. */
- buffer_ptr[j] = NX_NULL;
+ /* Change to the default directory of this connection. */
+ status = fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
- /* Set the path to the supplied directory. */
- status = fx_directory_local_path_set(ftp_server_ptr -> nx_ftp_server_media_ptr, &temp_path, (CHAR *) buffer_ptr);
+ /* Setup pointer to packet buffer area. */
+ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- /* Determine if the path setup was unsuccessful. */
- if (status)
+ /* Find the end of the message. */
+ j = 0;
+ k = -1;
+ while (j < packet_ptr -> nx_packet_length - 1)
{
- /* Pickup the information for the single file. */
- status = fx_directory_information_get(ftp_server_ptr -> nx_ftp_server_media_ptr, (CHAR *) buffer_ptr,
- &attributes, &size, &year, &month, &day, &hour, &minute, &second);
+ /* Determine if a slash or backslash is present. */
+ if ((buffer_ptr[j] == '/') || (buffer_ptr[j] == '\\'))
+ k = (INT)j;
- /* Determine if a file is specified as the LIST parameter. */
- if ((status == FX_SUCCESS) && ((attributes & FX_DIRECTORY) == 0))
- {
+ /* Determine if a CR/LF is present. */
+ if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
+ break;
- /* Yes, a file name was supplied. Set the single file flag for the processing below. */
- single_file = NX_TRUE;
+ /* Move to next character. */
+ j++;
+ }
- /* Advance to first character of the filename. */
- k++;
+ /* If specified path ends with slash or backslash, strip it. */
+ if ((j > 1) && ((buffer_ptr[j - 1] == '/') || (buffer_ptr[j - 1] == '\\')))
+ {
+ j--;
+ }
- /* Copy the file name from the last slash into the filename buffer. */
- j = 0;
- while ((buffer_ptr[(UINT)k + j]) && (j < FX_MAX_LONG_NAME_LEN-1))
- {
+ /* Default the single file specified flag to false. */
+ single_file = NX_FALSE;
- /* Copy a character of the filename. */
- filename[j] = (CHAR)(buffer_ptr[(UINT)k + j]);
+ /* Determine if there is a directory path. */
+ if (j)
+ {
- /* Move to next character. */
- j++;
- }
+ /* Ensure the name is NULL terminated. */
+ buffer_ptr[j] = NX_NULL;
- /* Null terminate the string. */
- filename[j] = NX_NULL;
- }
- }
- }
- else
- {
+ /* Set the path to the supplied directory. */
+ status = fx_directory_local_path_set(ftp_server_ptr -> nx_ftp_server_media_ptr, &temp_path, (CHAR *) buffer_ptr);
- /* Just set the buffer pointer to NULL since there isn't a string. */
- buffer_ptr = NX_NULL;
- }
+ /* Determine if the path setup was unsuccessful. */
+ if (status)
+ {
- /* Determine if the path setup was successful. */
- if (status == FX_SUCCESS)
- {
+ /* Pickup the information for the single file. */
+ status = fx_directory_information_get(ftp_server_ptr -> nx_ftp_server_media_ptr, (CHAR *) buffer_ptr,
+ &attributes, &size, &year, &month, &day, &hour, &minute, &second);
- CHAR *local_dir;
+ /* Determine if a file is specified as the LIST parameter. */
+ if ((status == FX_SUCCESS) && ((attributes & FX_DIRECTORY) == 0))
+ {
+ /* Yes, a file name was supplied. Set the single file flag for the processing below. */
+ single_file = NX_TRUE;
- /* Get the actual path */
- fx_directory_local_path_get(ftp_server_ptr -> nx_ftp_server_media_ptr, &local_dir);
+ /* Advance to first character of the filename. */
+ k++;
- /* Check if passive transfer enabled. */
- if (client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled == NX_TRUE)
- {
+ /* Copy the file name from the last slash into the filename buffer. */
+ j = 0;
+ while ((buffer_ptr[(UINT)k + j]) && (j < FX_MAX_LONG_NAME_LEN-1))
+ {
- /* Now wait for the data connection to connect. */
- status = nx_tcp_socket_state_wait(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_TCP_ESTABLISHED, NX_FTP_SERVER_TIMEOUT);
+ /* Copy a character of the filename. */
+ filename[j] = (CHAR)(buffer_ptr[(UINT)k + j]);
- /* Check for connect error. */
- if (status)
- {
+ /* Move to next character. */
+ j++;
+ }
- /* Yes, a connect error is present. Tear everything down. */
- nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_ftp_client_request_data_socket));
- nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_port);
- nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
- fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file));
+ /* Null terminate the string. */
+ filename[j] = NX_NULL;
+ }
}
}
else
{
- /* Create an FTP client data socket. */
- status = nx_tcp_socket_create(ftp_server_ptr -> nx_ftp_server_ip_ptr, &(client_req_ptr -> nx_ftp_client_request_data_socket), "FTP Server Data Socket",
- NX_FTP_DATA_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, NX_FTP_DATA_WINDOW_SIZE, NX_NULL, NX_NULL);
-
- /* If no error is present, register the receive notify function. */
- if (status == NX_SUCCESS)
- {
+ /* Just set the buffer pointer to NULL since there isn't a string. */
+ buffer_ptr = NX_NULL;
+ }
- /* Make sure each socket points to the corresponding FTP server. */
- client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_reserved_ptr = ftp_server_ptr;
+ /* Determine if the path setup was successful. */
+ if (status == FX_SUCCESS)
+ {
- /* Bind the socket to the FTP server data port. */
- status = nx_tcp_client_socket_bind(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_FTP_SERVER_DATA_PORT, NX_NO_WAIT);
+ CHAR *local_dir;
- /* Determine if the socket was bound. */
- if (status)
- {
- /* FTP server data port is busy, use any data port. */
- nx_tcp_client_socket_bind(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_ANY_PORT, NX_NO_WAIT);
- }
+ /* Get the actual path */
+ fx_directory_local_path_get(ftp_server_ptr -> nx_ftp_server_media_ptr, &local_dir);
- /* Now attempt to connect the data port to the client's data port. */
- status = nxd_tcp_client_socket_connect(&(client_req_ptr -> nx_ftp_client_request_data_socket),
- &(client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip),
- client_req_ptr -> nx_ftp_client_request_data_port, NX_FTP_SERVER_TIMEOUT);
+ /* Check if passive transfer enabled. */
+ if (client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled == NX_TRUE)
+ {
+ /* Now wait for the data connection to connect. */
+ status = nx_tcp_socket_state_wait(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_TCP_ESTABLISHED, NX_FTP_SERVER_TIMEOUT);
/* Check for connect error. */
if (status)
{
- /* Yes, a connect error is present. Tear everything down. */
- nx_tcp_client_socket_unbind(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ /* Yes, a connect error is present. Tear everything down. */
+ nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_port);
nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file));
}
- else
- {
+ }
+ else if (client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_id)
+ {
- /* Setup the data port with a specific packet transmit retry logic. */
- nx_tcp_socket_transmit_configure(&(client_req_ptr -> nx_ftp_client_request_data_socket),
- NX_FTP_SERVER_TRANSMIT_QUEUE_DEPTH,
- NX_FTP_SERVER_RETRY_SECONDS*NX_IP_PERIODIC_RATE,
- NX_FTP_SERVER_RETRY_MAX,
- NX_FTP_SERVER_RETRY_SHIFT);
- }
+ /* Socket already created. Error. */
+ status = NX_NOT_CLOSED;
}
- }
- }
+ else
+ {
- /* Now check and see if the directory listing command has any errors. */
- if (status == NX_SUCCESS)
- {
+ /* Create an FTP client data socket. */
+ status = nx_tcp_socket_create(ftp_server_ptr -> nx_ftp_server_ip_ptr, &(client_req_ptr -> nx_ftp_client_request_data_socket), "FTP Server Data Socket",
+ NX_FTP_DATA_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, NX_FTP_DATA_WINDOW_SIZE, NX_NULL, NX_NULL);
- /* The directory listing is successful! */
+ /* If no error is present, register the receive notify function. */
+ if (status == NX_SUCCESS)
+ {
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_START_XFER, "Sending List");
+ /* Make sure each socket points to the corresponding FTP server. */
+ client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_reserved_ptr = ftp_server_ptr;
- /* Determine if the block mode is enabled. */
- if (client_req_ptr -> nx_ftp_client_request_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
- {
+ /* Bind the socket to the FTP server data port. */
+ status = nx_tcp_client_socket_bind(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_FTP_SERVER_DATA_PORT, NX_NO_WAIT);
- /* Get the directory listing size. */
- _nx_ftp_server_block_size_get(ftp_server_ptr, ftp_command, filename, &block_size);
+ /* Determine if the socket was bound. */
+ if (status)
+ {
- /* Send start block header for file size. */
- if (block_size)
- _nx_ftp_server_block_header_send(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, block_size);
- }
+ /* FTP server data port is busy, use any data port. */
+ nx_tcp_client_socket_bind(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_ANY_PORT, NX_NO_WAIT);
+ }
- /* Allocate a new packet. */
- status = _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
+ /* Now attempt to connect the data port to the client's data port. */
+ status = nxd_tcp_client_socket_connect(&(client_req_ptr -> nx_ftp_client_request_data_socket),
+ &(client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip),
+ client_req_ptr -> nx_ftp_client_request_data_port, NX_FTP_SERVER_TIMEOUT);
- /* Calculate the remaining length. */
- remaining_length = (ULONG)((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_append_ptr) - NX_PHYSICAL_TRAILER);
- /* Determine if the advertised MSS is even less. */
- if (remaining_length > client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss)
- {
+ /* Check for connect error. */
+ if (status)
+ {
+
+ /* Yes, a connect error is present. Tear everything down. */
+ nx_tcp_client_socket_unbind(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file));
+ }
+ else
+ {
- /* Reduce the remaining length to the MSS value. */
- remaining_length = client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss;
+ /* Setup the data port with a specific packet transmit retry logic. */
+ nx_tcp_socket_transmit_configure(&(client_req_ptr -> nx_ftp_client_request_data_socket),
+ NX_FTP_SERVER_TRANSMIT_QUEUE_DEPTH,
+ NX_FTP_SERVER_RETRY_SECONDS*NX_IP_PERIODIC_RATE,
+ NX_FTP_SERVER_RETRY_MAX,
+ NX_FTP_SERVER_RETRY_SHIFT);
+ }
+ }
+ }
}
- /* Now generate the full directory listing and send the contents to the client. */
- j = 0;
- while (status == NX_SUCCESS)
+ /* Now check and see if the directory listing command has any errors. */
+ if (status == NX_SUCCESS)
{
- /* Determine if a single file was specified. */
- if (single_file == NX_FALSE)
+ /* The directory listing is successful! */
+
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_START_XFER, "Sending List");
+
+ /* Determine if the block mode is enabled. */
+ if (client_req_ptr -> nx_ftp_client_request_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
{
- /* Typical case - not a single file. */
+ /* Get the directory listing size. */
+ _nx_ftp_server_block_size_get(ftp_server_ptr, ftp_command, filename, &block_size);
- /* Pickup the next directory entry. */
- if (j == 0)
+ /* Send start block header for file size. */
+ if (block_size)
+ _nx_ftp_server_block_header_send(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, block_size);
+ }
+
+ /* Allocate a new packet. */
+ status = _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
+
+ /* Calculate the remaining length. */
+ remaining_length = (ULONG)((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_append_ptr) - NX_PHYSICAL_TRAILER);
+
+ /* Determine if the advertised MSS is even less. */
+ if (remaining_length > client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss)
+ {
+
+ /* Reduce the remaining length to the MSS value. */
+ remaining_length = client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss;
+ }
+
+ /* Now generate the full directory listing and send the contents to the client. */
+ j = 0;
+ while (status == NX_SUCCESS)
+ {
+
+ /* Determine if a single file was specified. */
+ if (single_file == NX_FALSE)
{
- /* First directory entry. */
- status = fx_directory_first_full_entry_find(ftp_server_ptr -> nx_ftp_server_media_ptr, filename,
- &attributes, &size, &year, &month, &day, &hour, &minute, &second);
+ /* Typical case - not a single file. */
+ /* Pickup the next directory entry. */
+ if (j == 0)
+ {
+
+ /* First directory entry. */
+ status = fx_directory_first_full_entry_find(ftp_server_ptr -> nx_ftp_server_media_ptr, filename,
+ &attributes, &size, &year, &month, &day, &hour, &minute, &second);
+
+ }
+ else
+ {
+
+ /* Not the first entry - pickup the next! */
+ status = fx_directory_next_full_entry_find(ftp_server_ptr -> nx_ftp_server_media_ptr, filename,
+ &attributes, &size, &year, &month, &day, &hour, &minute, &second);
+
+ }
}
else
{
- /* Not the first entry - pickup the next! */
- status = fx_directory_next_full_entry_find(ftp_server_ptr -> nx_ftp_server_media_ptr, filename,
- &attributes, &size, &year, &month, &day, &hour, &minute, &second);
+ /* The parameter to the LIST command is a single file. Simply return the information
+ already gathered above for this one file instead of traversing the entire list. */
+
+ /* Is this the first pass through the loop? */
+ if (j)
+ {
+ /* End the loop, since the single file has already been sent. */
+ status = FX_NO_MORE_ENTRIES;
+ }
}
- }
- else
- {
- /* The parameter to the LIST command is a single file. Simply return the information
- already gathered above for this one file instead of traversing the entire list. */
+ /* Increment the entry count. */
+ j++;
- /* Is this the first pass through the loop? */
- if (j)
+ /* Determine if successful. */
+ if (status == NX_SUCCESS)
{
- /* End the loop, since the single file has already been sent. */
- status = FX_NO_MORE_ENTRIES;
- }
- }
+ /* Check if the month is valid before convert it. */
+ if ((month < 1) || (month > 12))
+ continue;
- /* Increment the entry count. */
- j++;
+ /* Setup pointer to buffer. */
+ buffer_ptr = packet_ptr -> nx_packet_append_ptr;
- /* Determine if successful. */
- if (status == NX_SUCCESS)
- {
+ /* Calculate the size of the name. */
+ length = 0;
+ do
+ {
+ if (filename[length])
+ length++;
+ else
+ break;
+ } while (length < FX_MAX_LONG_NAME_LEN);
- /* Check if the month is valid before convert it. */
- if ((month < 1) || (month > 12))
- continue;
+ /* Make sure there is enough space for the data plus the file info.
+ File Info is 10 chars for permissions, 15 chars for owner and group,
+ 11 chars for size (for file size up to 4gB), 14 for date, 2 chars for cr lf. */
+ if ((length + 52) > remaining_length)
+ {
- /* Setup pointer to buffer. */
- buffer_ptr = packet_ptr -> nx_packet_append_ptr;
+ /* Send the current buffer out. */
- /* Calculate the size of the name. */
- length = 0;
- do
- {
- if (filename[length])
- length++;
- else
- break;
- } while (length < FX_MAX_LONG_NAME_LEN);
+ /* Send the directory data to the client. */
+ status = nx_tcp_socket_send(&(client_req_ptr -> nx_ftp_client_request_data_socket), packet_ptr, NX_FTP_SERVER_TIMEOUT);
- /* Make sure there is enough space for the data plus the file info.
- File Info is 10 chars for permissions, 15 chars for owner and group,
- 11 chars for size (for file size up to 4gB), 14 for date, 2 chars for cr lf. */
- if ((length + 52) > remaining_length)
- {
+ /* Determine if the send was unsuccessful. */
+ if (status)
+ {
+
+ /* Release the packet. */
+ nx_packet_release(packet_ptr);
+ }
- /* Send the current buffer out. */
+ /* Allocate a new packet. */
+ status = _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
- /* Send the directory data to the client. */
- status = nx_tcp_socket_send(&(client_req_ptr -> nx_ftp_client_request_data_socket), packet_ptr, NX_FTP_SERVER_TIMEOUT);
+ /* Determine if the packet allocate was successfull. */
+ if (status)
+ {
- /* Determine if the send was unsuccessful. */
- if (status)
- {
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
- }
+ /* Get out of the loop! */
+ break;
+ }
- /* Allocate a new packet. */
- status = _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
+ /* Calculate the remaining length. */
+ remaining_length = (ULONG)((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_append_ptr) - NX_PHYSICAL_TRAILER);
- /* Determine if the packet allocate was successfull. */
- if (status)
- {
+ /* Determine if the advertised MSS is even less. */
+ if (remaining_length > client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss)
+ {
- /* Get out of the loop! */
- break;
- }
+ /* Reduce the remaining length to the MSS value. */
+ remaining_length = client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss;
+ }
- /* Calculate the remaining length. */
- remaining_length = (ULONG)((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_append_ptr) - NX_PHYSICAL_TRAILER);
+ /* Setup pointer to buffer. */
+ buffer_ptr = packet_ptr -> nx_packet_append_ptr;
+ }
- /* Determine if the advertised MSS is even less. */
- if (remaining_length > client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss)
+ /* Put the file information followed by the file name */
+ buffer_ptr[0] = ((attributes & FX_DIRECTORY) ? 'd' : '-');
+ if (attributes & FX_READ_ONLY)
{
-
- /* Reduce the remaining length to the MSS value. */
- remaining_length = client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss;
+ memcpy(&buffer_ptr[1], "r--r--r--", 9); /* Use case of memcpy is verified. */
}
+ else
+ {
+ 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, ' ');
+ 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, '0');
+ buffer_ptr[43] = ' ';
+ _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, '0');
+ buffer_ptr[49] = ' ';
+ memcpy(&buffer_ptr[50], filename, length); /* Use case of memcpy is verified. */
+ length += 50;
+ buffer_ptr[length++] = '\r';
+ buffer_ptr[length++] = '\n';
+
- /* Setup pointer to buffer. */
- buffer_ptr = packet_ptr -> nx_packet_append_ptr;
+ /* Set the packet length. */
+ packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + length;
+
+ /* Setup the packet append pointer. */
+ packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_append_ptr + length;
+
+ /* Adjust the remaining length. */
+ if (remaining_length > length)
+ {
+ remaining_length = remaining_length - length;
+ }
+ else
+ {
+ remaining_length = 0;
+ }
}
+ }
+
+ /* Now determine if the directory listing was a success. */
+ if ((status == FX_NO_MORE_ENTRIES) && (packet_ptr) && (packet_ptr -> nx_packet_length))
+ {
- /* Put the file information followed by the file name */
- buffer_ptr[0] = ((attributes & FX_DIRECTORY) ? 'd' : '-');
- if (attributes & FX_READ_ONLY)
+ /* Send the directory data to the client. */
+ status = nx_tcp_socket_send(&(client_req_ptr -> nx_ftp_client_request_data_socket),
+ packet_ptr, NX_FTP_SERVER_TIMEOUT);
+
+ /* Determine if the send was unsuccessful. */
+ if (status)
{
- memcpy(&buffer_ptr[1], "r--r--r--", 9); /* Use case of memcpy is verified. */
+
+ /* Release the packet. */
+ nx_packet_release(packet_ptr);
}
else
{
- memcpy(&buffer_ptr[1], "rw-rw-rw-", 9); /* Use case of memcpy is verified. */
+
+ /* Reset the status for the response processing below. */
+ status = FX_NO_MORE_ENTRIES;
}
- 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, ' ');
- 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, '0');
- buffer_ptr[43] = ' ';
- _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, '0');
- buffer_ptr[49] = ' ';
- memcpy(&buffer_ptr[50], filename, length); /* Use case of memcpy is verified. */
- length += 50;
- buffer_ptr[length++] = '\r';
- buffer_ptr[length++] = '\n';
-
+ }
+ else if (packet_ptr)
+ {
- /* Set the packet length. */
- packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + length;
+ /* Release packet just in case! */
+ nx_packet_release(packet_ptr);
+ }
- /* Setup the packet append pointer. */
- packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_append_ptr + length;
+ /* Determine if the block mode is enabled. */
+ if (client_req_ptr -> nx_ftp_client_request_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
+ {
- /* Adjust the remaining length. */
- remaining_length = remaining_length - length;
+ /* Send end block header for file size. */
+ _nx_ftp_server_block_header_send(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, 0);
}
- }
- /* Now determine if the directory listing was a success. */
- if ((status == FX_NO_MORE_ENTRIES) && (packet_ptr) && (packet_ptr -> nx_packet_length))
- {
+ /* Clean up the data socket. */
+ _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr);
- /* Send the directory data to the client. */
- status = nx_tcp_socket_send(&(client_req_ptr -> nx_ftp_client_request_data_socket),
- packet_ptr, NX_FTP_SERVER_TIMEOUT);
+ /* Allocate a new packet. */
+ _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
- /* Determine if the send was unsuccessful. */
- if (status)
+ /* Now determine if the directory listing was a success. */
+ if (status == FX_NO_MORE_ENTRIES)
{
- /* Release the packet. */
- nx_packet_release(packet_ptr);
+ /* The directory listing was successful! */
+
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_COMPLETED, "List End");
}
else
{
- /* Reset the status for the response processing below. */
- status = FX_NO_MORE_ENTRIES;
- }
- }
- else if (packet_ptr)
- {
+ /* Directory listing command failed. */
- /* Release packet just in case! */
- nx_packet_release(packet_ptr);
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "List fail");
+ }
}
-
- /* Determine if the block mode is enabled. */
- if (client_req_ptr -> nx_ftp_client_request_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
+ else
{
+ /* Unsuccessful directory listing command. */
- /* Send end block header for file size. */
- _nx_ftp_server_block_header_send(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, 0);
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Bad Directory");
}
+ break;
+ }
- /* Clean up the data socket. */
- _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr);
-
- /* Allocate a new packet. */
- _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
+#ifndef NX_DISABLE_IPV4
+ case NX_FTP_PORT:
+ {
+
- /* Now determine if the directory listing was a success. */
- if (status == FX_NO_MORE_ENTRIES)
+ /* Check that only IPv4 packets can use the PORT command. */
+ if (client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
{
+ /* Illegal PORT command. */
- /* The directory listing was successful! */
-
- /* Now send a successful response to the client. */
+ /* Now send an error response to the client. */
_nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_COMPLETED, "List End");
+ NX_FTP_CODE_NOT_IMPLEMENTED, "PORT illegal in IPv6");
+
+ /* Bail out! */
+ break;
}
- else
- {
+ /* Setup pointer to packet buffer area. */
+ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- /* Directory listing command failed. */
+ /* First, pickup the IP address. */
+ commas = 0;
+ ip_address = 0;
+ j = 0;
+ temp = 0;
+ status = NX_SUCCESS;
+ while (j < packet_ptr -> nx_packet_length)
+ {
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "List fail");
- }
- }
- else
- {
- /* Unsuccessful directory listing command. */
+ /* Is a numeric character present? */
+ if ((buffer_ptr[j] >= '0') && (buffer_ptr[j] <= '9'))
+ {
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "Bad Directory");
- }
- break;
- }
+ /* Yes, numeric character is present. Update the IP address. */
+ temp = (temp*10) + (ULONG) (buffer_ptr[j] - '0');
+ }
-#ifndef NX_DISABLE_IPV4
- case NX_FTP_PORT:
- {
-
+ /* Determine if a CR/LF is present. */
+ if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
+ {
+ status = NX_FTP_INVALID_COMMAND;
+ break;
+ }
- /* Check that only IPv4 packets can use the PORT command. */
- if (client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
- {
- /* Illegal PORT command. */
+ /* Determine if a comma is present. */
+ if (buffer_ptr[j] == ',')
+ {
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_NOT_IMPLEMENTED, "PORT illegal in IPv6");
+ /* Increment the comma count. */
+ commas++;
- /* Bail out! */
- break;
- }
- /* Setup pointer to packet buffer area. */
- buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
+ /* Setup next byte of IP address. */
+ ip_address = (ip_address << 8) & 0xFFFFFFFF;
+ ip_address = ip_address | (temp & 0xFF);
+ temp = 0;
- /* First, pickup the IP address. */
- commas = 0;
- ip_address = 0;
- j = 0;
- temp = 0;
- status = NX_SUCCESS;
- while (j < packet_ptr -> nx_packet_length)
- {
+ /* Have we finished with the IP address? */
+ if (commas == 4)
+ {
- /* Is a numeric character present? */
- if ((buffer_ptr[j] >= '0') && (buffer_ptr[j] <= '9'))
- {
+ /* Finished with IP address. */
+ j++;
+ break;
+ }
- /* Yes, numeric character is present. Update the IP address. */
- temp = (temp*10) + (ULONG) (buffer_ptr[j] - '0');
- }
+ }
- /* Determine if a CR/LF is present. */
- if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
- {
- status = NX_FTP_INVALID_COMMAND;
- break;
+ /* Move to next character. */
+ j++;
}
- /* Determine if a comma is present. */
- if (buffer_ptr[j] == ',')
+ /* Now pickup the port number. */
+ port = 0;
+ temp = 0;
+ while (j < packet_ptr -> nx_packet_length)
{
- /* Increment the comma count. */
- commas++;
+ /* Is a numeric character present? */
+ if ((buffer_ptr[j] >= '0') && (buffer_ptr[j] <= '9'))
+ {
- /* Setup next byte of IP address. */
- ip_address = (ip_address << 8) & 0xFFFFFFFF;
- ip_address = ip_address | (temp & 0xFF);
- temp = 0;
+ /* Yes, numeric character is present. Update the IP port. */
+ temp = (temp*10) + (UINT) (buffer_ptr[j] - '0');
+ }
- /* Have we finished with the IP address? */
- if (commas == 4)
+ /* Determine if a CR/LF is present. */
+ if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
{
-
- /* Finished with IP address. */
- j++;
+ /* Good condition on the port number! */
break;
}
- }
+ /* Determine if a comma is present. */
+ if (buffer_ptr[j] == ',')
+ {
- /* Move to next character. */
- j++;
- }
+ /* Increment the comma count. */
+ commas++;
- /* Now pickup the port number. */
- port = 0;
- temp = 0;
- while (j < packet_ptr -> nx_packet_length)
- {
+ /* Move port number up. */
+ port = (port << 8) & 0xFFFFFFFF;
+ port = port | (temp & 0xFF);
+ temp = 0;
- /* Is a numeric character present? */
- if ((buffer_ptr[j] >= '0') && (buffer_ptr[j] <= '9'))
- {
+ /* Have we finished with the IP address? */
+ if (commas >= 6)
+ {
- /* Yes, numeric character is present. Update the IP port. */
- temp = (temp*10) + (UINT) (buffer_ptr[j] - '0');
+ /* Error, get out of the loop. */
+ status = NX_FTP_INVALID_ADDRESS;
+ break;
+ }
+ }
+
+ /* Move to next character. */
+ j++;
}
- /* Determine if a CR/LF is present. */
- if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
+ /* Move port number up. */
+ port = (port << 8) & 0xFFFFFFFF;
+ port = port | (temp & 0xFF);
+ temp = 0;
+
+ /* Determine if an error occurred. */
+ if ((buffer_ptr[j] != 13) || (commas != 5) || (ip_address == 0) || (port == 0) ||
+ (ip_address != connect_ip4_address))
{
- /* Good condition on the port number! */
- break;
+
+ /* Set the error status. */
+ status = NX_FTP_INVALID_COMMAND;
}
- /* Determine if a comma is present. */
- if (buffer_ptr[j] == ',')
+ /* Save the data port. */
+ client_req_ptr -> nx_ftp_client_request_data_port = port;
+
+ /* Determine if the port command was successful. */
+ if (status == NX_SUCCESS)
{
- /* Increment the comma count. */
- commas++;
+ /* Yes, the port command is successful! */
- /* Move port number up. */
- port = (port << 8) & 0xFFFFFFFF;
- port = port | (temp & 0xFF);
- temp = 0;
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_CMD_OK, "Port set");
+ }
+ else
+ {
- /* Have we finished with the IP address? */
- if (commas >= 6)
- {
+ /* Unsuccessful port command. */
- /* Error, get out of the loop. */
- status = NX_FTP_INVALID_ADDRESS;
- break;
- }
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_CMD_FAIL, "Port Fail");
}
- /* Move to next character. */
- j++;
+ break;
}
- /* Move port number up. */
- port = (port << 8) & 0xFFFFFFFF;
- port = port | (temp & 0xFF);
- temp = 0;
+ case NX_FTP_PASV:
+ {
- /* Determine if an error occurred. */
- if ((buffer_ptr[j] != 13) || (commas != 5) || (ip_address == 0) || (port == 0) ||
- (ip_address != connect_ip4_address))
- {
+ /* If create, cleanup the data socket. */
+ if (client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_id)
+ {
- /* Set the error status. */
- status = NX_FTP_INVALID_COMMAND;
- }
+ /* Clean up the data socket. */
+ _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr);
+ }
- /* Save the data port. */
- client_req_ptr -> nx_ftp_client_request_data_port = port;
+ /* Try to find the data port. */
+ status = nx_tcp_free_port_find(ftp_server_ptr -> nx_ftp_server_ip_ptr,
+ ftp_server_ptr -> nx_ftp_server_data_port++, &port);
- /* Determine if the port command was successful. */
- if (status == NX_SUCCESS)
- {
+ /* Determine if the PASV command was successful. */
+ if (status != NX_SUCCESS)
+ {
- /* Yes, the port command is successful! */
+ /* Unsuccessful port find. */
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_CMD_OK, "Port set");
- }
- else
- {
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_CMD_FAIL, "PASV Fail");
- /* Unsuccessful port command. */
+ /* And we are done processing. */
+ break;
+ }
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_CMD_FAIL, "Port Fail");
- }
+ /* Create an FTP client data socket. */
+ status = nx_tcp_socket_create(ftp_server_ptr -> nx_ftp_server_ip_ptr, &(client_req_ptr -> nx_ftp_client_request_data_socket), "FTP Server Data Socket",
+ NX_FTP_DATA_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, NX_FTP_DATA_WINDOW_SIZE, NX_NULL, _nx_ftp_server_data_disconnect);
- break;
- }
+ /* Determine if the listen is successful. */
+ if (status != NX_SUCCESS)
+ {
- case NX_FTP_PASV:
- {
+ /* Unsuccessful data socket create. */
- /* If create, cleanup the data socket. */
- if (client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_id)
- {
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_CMD_FAIL, "PASV Fail");
- /* Clean up the data socket. */
- _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr);
- }
+ /* And we are done processing. */
+ break;
+ }
- /* Try to find the data port. */
- status = nx_tcp_free_port_find(ftp_server_ptr -> nx_ftp_server_ip_ptr,
- ftp_server_ptr -> nx_ftp_server_data_port++, &port);
+ /* Register the receive function. */
+ nx_tcp_socket_receive_notify(&(client_req_ptr -> nx_ftp_client_request_data_socket), _nx_ftp_server_data_present);
- /* Determine if the PASV command was successful. */
- if (status != NX_SUCCESS)
- {
+ /* Setup the data port with a specific packet transmit retry logic. */
+ nx_tcp_socket_transmit_configure(&(client_req_ptr -> nx_ftp_client_request_data_socket),
+ NX_FTP_SERVER_TRANSMIT_QUEUE_DEPTH,
+ NX_FTP_SERVER_RETRY_SECONDS*NX_IP_PERIODIC_RATE,
+ NX_FTP_SERVER_RETRY_MAX,
+ NX_FTP_SERVER_RETRY_SHIFT);
- /* Unsuccessful port find. */
+ /* Make sure each socket points to the corresponding FTP server. */
+ client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_reserved_ptr = ftp_server_ptr;
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_CMD_FAIL, "PASV Fail");
+ /* Start listening on the data port. */
+ status = nx_tcp_server_socket_listen(ftp_server_ptr -> nx_ftp_server_ip_ptr, port, &(client_req_ptr -> nx_ftp_client_request_data_socket), 5, 0);
- /* And we are done processing. */
- break;
- }
+ /* Determine if the listen is successful. */
+ if (status != NX_SUCCESS)
+ {
- /* Create an FTP client data socket. */
- status = nx_tcp_socket_create(ftp_server_ptr -> nx_ftp_server_ip_ptr, &(client_req_ptr -> nx_ftp_client_request_data_socket), "FTP Server Data Socket",
- NX_FTP_DATA_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, NX_FTP_DATA_WINDOW_SIZE, NX_NULL, _nx_ftp_server_data_disconnect);
+ /* Unsuccessful data socket listen. */
- /* Determine if the listen is successful. */
- if (status != NX_SUCCESS)
- {
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_CMD_FAIL, "PASV Fail");
- /* Unsuccessful data socket create. */
+ /* Delete data socket. */
+ nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_CMD_FAIL, "PASV Fail");
+ /* And we are done processing. */
+ break;
+ }
- /* And we are done processing. */
- break;
- }
+ /* Wait for the data connection to connect. */
+ nx_tcp_server_socket_accept(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_NO_WAIT);
- /* Register the receive function. */
- nx_tcp_socket_receive_notify(&(client_req_ptr -> nx_ftp_client_request_data_socket), _nx_ftp_server_data_present);
+ /* Pickup the IPv4 address of this IP instance. */
+ ip_address = client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_interface -> nx_interface_ip_address;
- /* Setup the data port with a specific packet transmit retry logic. */
- nx_tcp_socket_transmit_configure(&(client_req_ptr -> nx_ftp_client_request_data_socket),
- NX_FTP_SERVER_TRANSMIT_QUEUE_DEPTH,
- NX_FTP_SERVER_RETRY_SECONDS*NX_IP_PERIODIC_RATE,
- NX_FTP_SERVER_RETRY_MAX,
- NX_FTP_SERVER_RETRY_SHIFT);
+ /* Reset the packet prepend pointer for alignment. */
+ packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_data_start + NX_TCP_PACKET;
- /* Make sure each socket points to the corresponding FTP server. */
- client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_reserved_ptr = ftp_server_ptr;
+ /* Setup pointer to packet buffer area. */
+ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- /* Start listening on the data port. */
- status = nx_tcp_server_socket_listen(ftp_server_ptr -> nx_ftp_server_ip_ptr, port, &(client_req_ptr -> nx_ftp_client_request_data_socket), 5, 0);
+ /* Now build PASV response. "227 Entering Passive Mode (h1,h2,h3,h4,p1,p2)." */
+
+ /* Verify packet payload. The max size of this message is 54. */
+ if ((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 54)
+ {
- /* Determine if the listen is successful. */
- if (status != NX_SUCCESS)
- {
+ /* Delete data socket. */
+ nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, port);
+ nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
- /* Unsuccessful data socket listen. */
+ /* Release the packet. */
+ nx_packet_release(packet_ptr);
+ break;
+ }
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_CMD_FAIL, "PASV Fail");
+ /* Build the string. "227 Entering Passive Mode " */
+ memcpy(buffer_ptr, "227 Entering Passive Mode ", 26); /* Use case of memcpy is verified. */
- /* Delete data socket. */
- nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ /* Build the IP address and port. */
+ j = 26;
+ buffer_ptr[j++] = '(';
+ j += _nx_utility_uint_to_string((ip_address >> 24), 10, (CHAR *)(buffer_ptr + j), 54 - j);
+ buffer_ptr[j++] = ',';
+ j += _nx_utility_uint_to_string(((ip_address >> 16) & 0xFF), 10, (CHAR *)(buffer_ptr + j), 54 - j);
+ buffer_ptr[j++] = ',';
+ j += _nx_utility_uint_to_string(((ip_address >> 8) & 0xFF), 10, (CHAR *)(buffer_ptr + j), 54 - j);
+ buffer_ptr[j++] = ',';
+ j += _nx_utility_uint_to_string((ip_address & 0xFF), 10, (CHAR *)(buffer_ptr + j), 54 - j);
+ buffer_ptr[j++] = ',';
+ j += _nx_utility_uint_to_string((port >> 8), 10, (CHAR *)(buffer_ptr + j), 54 - j);
+ buffer_ptr[j++] = ',';
+ j += _nx_utility_uint_to_string((port & 0XFF), 10, (CHAR *)(buffer_ptr + j), 54 - j);
+ buffer_ptr[j++] = ')';
+ buffer_ptr[j++] = '.';
- /* And we are done processing. */
- break;
- }
+ /* Set the CR/LF. */
+ buffer_ptr[j++] = 13;
+ buffer_ptr[j++] = 10;
+
+ /* Set the packet length. */
+ packet_ptr -> nx_packet_length = j;
- /* Wait for the data connection to connect. */
- nx_tcp_server_socket_accept(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_NO_WAIT);
+ /* Setup the packet append pointer. */
+ packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
- /* Pickup the IPv4 address of this IP instance. */
- ip_address = client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_interface -> nx_interface_ip_address;
+ /* Send the PASV response message. */
+ status = nx_tcp_socket_send(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, NX_FTP_SERVER_TIMEOUT);
- /* Reset the packet prepend pointer for alignment. */
- packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_data_start + NX_TCP_PACKET;
+ /* Determine if the send was unsuccessful. */
+ if (status != NX_SUCCESS)
+ {
- /* Setup pointer to packet buffer area. */
- buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
+ /* Delete data socket. */
+ nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, port);
+ nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
- /* Now build PASV response. "227 Entering Passive Mode (h1,h2,h3,h4,p1,p2)." */
-
- /* Verify packet payload. The max size of this message is 54. */
- if ((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 54)
- {
+ /* Release the packet. */
+ nx_packet_release(packet_ptr);
+ }
- /* Delete data socket. */
- nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, port);
- nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ /* Yes, passive transfer enabled. */
+ client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled = NX_TRUE;
- /* Release the packet. */
- nx_packet_release(packet_ptr);
break;
}
+#endif /* NX_DISABLE_IPV4 */
- /* Build the string. "227 Entering Passive Mode " */
- memcpy(buffer_ptr, "227 Entering Passive Mode ", 26); /* Use case of memcpy is verified. */
+#ifdef FEATURE_NX_IPV6
+ case NX_FTP_EPRT:
+ {
+
- /* Build the IP address and port. */
- j = 26;
- buffer_ptr[j++] = '(';
- j += _nx_utility_uint_to_string((ip_address >> 24), 10, (CHAR *)(buffer_ptr + j), 54 - j);
- buffer_ptr[j++] = ',';
- j += _nx_utility_uint_to_string(((ip_address >> 16) & 0xFF), 10, (CHAR *)(buffer_ptr + j), 54 - j);
- buffer_ptr[j++] = ',';
- j += _nx_utility_uint_to_string(((ip_address >> 8) & 0xFF), 10, (CHAR *)(buffer_ptr + j), 54 - j);
- buffer_ptr[j++] = ',';
- j += _nx_utility_uint_to_string((ip_address & 0xFF), 10, (CHAR *)(buffer_ptr + j), 54 - j);
- buffer_ptr[j++] = ',';
- j += _nx_utility_uint_to_string((port >> 8), 10, (CHAR *)(buffer_ptr + j), 54 - j);
- buffer_ptr[j++] = ',';
- j += _nx_utility_uint_to_string((port & 0XFF), 10, (CHAR *)(buffer_ptr + j), 54 - j);
- buffer_ptr[j++] = ')';
- buffer_ptr[j++] = '.';
+ /* Check that only IPv6 packets can use the EPRT command. */
+ if (client_req_ptr -> nx_ftp_client_request_ip_type == NX_IP_VERSION_V4)
+ {
+ /* Illegal EPRT command. */
- /* Set the CR/LF. */
- buffer_ptr[j++] = 13;
- buffer_ptr[j++] = 10;
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_NOT_IMPLEMENTED, "EPRT illegal in IPv4");
- /* Set the packet length. */
- packet_ptr -> nx_packet_length = j;
+ /* Bail out! */
+ break;
+ }
- /* Setup the packet append pointer. */
- packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
+ /* Setup pointer to packet buffer area. */
+ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- /* Send the PASV response message. */
- status = nx_tcp_socket_send(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, NX_FTP_SERVER_TIMEOUT);
+ /* First, pickup the IPv6 address. */
+ status = _nx_ftp_utility_parse_IPv6_address((CHAR *)buffer_ptr, packet_ptr -> nx_packet_length, &ipduo_address);
- /* Determine if the send was unsuccessful. */
- if (status != NX_SUCCESS)
- {
+ if (status != NX_SUCCESS)
+ {
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_CMD_FAIL, "Bad IPv6 address");
- /* Delete data socket. */
- nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, port);
- nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ return;
+ }
- /* Release the packet. */
- nx_packet_release(packet_ptr);
- }
+ /* Now pickup the port number. */
+ status = _nx_ftp_utility_parse_port_number((CHAR *)buffer_ptr, packet_ptr -> nx_packet_length, &port);
- /* Yes, passive transfer enabled. */
- client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled = NX_TRUE;
+ /* Save the data port. */
+ client_req_ptr -> nx_ftp_client_request_data_port = port;
- break;
- }
-#endif /* NX_DISABLE_IPV4 */
+ /* Determine if the EPRT command was successful. */
+ if (status == NX_SUCCESS)
+ {
-#ifdef FEATURE_NX_IPV6
- case NX_FTP_EPRT:
- {
-
+ /* Yes, the EPRT command is successful! */
- /* Check that only IPv6 packets can use the EPRT command. */
- if (client_req_ptr -> nx_ftp_client_request_ip_type == NX_IP_VERSION_V4)
- {
- /* Illegal EPRT command. */
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_CMD_OK, "EPRT command set");
+ }
+ else
+ {
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_NOT_IMPLEMENTED, "EPRT illegal in IPv4");
+ /* Unsuccessful EPRT command. */
+
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_CMD_FAIL, "EPRT command failed");
+ }
- /* Bail out! */
break;
+
}
+
+ case NX_FTP_EPSV:
+ {
- /* Setup pointer to packet buffer area. */
- buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
+ /* If create, cleanup the data socket. */
+ if (client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_id)
+ {
- /* First, pickup the IPv6 address. */
- status = _nx_ftp_utility_parse_IPv6_address((CHAR *)buffer_ptr, packet_ptr -> nx_packet_length, &ipduo_address);
+ /* Clean up the client socket. */
+ _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr);
+ }
- if (status != NX_SUCCESS)
- {
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_CMD_FAIL, "Bad IPv6 address");
+ /* Try to find the data port. */
+ status = nx_tcp_free_port_find(ftp_server_ptr -> nx_ftp_server_ip_ptr,
+ ftp_server_ptr -> nx_ftp_server_data_port++, &port);
- return;
- }
+ /* Determine if the EPSV command was successful. */
+ if (status != NX_SUCCESS)
+ {
- /* Now pickup the port number. */
- status = _nx_ftp_utility_parse_port_number((CHAR *)buffer_ptr, packet_ptr -> nx_packet_length, &port);
+ /* Unsuccessful port find. */
- /* Save the data port. */
- client_req_ptr -> nx_ftp_client_request_data_port = port;
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_CMD_FAIL, "EPSV Fail");
- /* Determine if the EPRT command was successful. */
- if (status == NX_SUCCESS)
- {
+ /* And we are done processing. */
+ break;
+ }
- /* Yes, the EPRT command is successful! */
+ /* Create an FTP client data socket. */
+ status = nx_tcp_socket_create(ftp_server_ptr -> nx_ftp_server_ip_ptr, &(client_req_ptr -> nx_ftp_client_request_data_socket), "FTP Server Data Socket",
+ NX_FTP_DATA_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, NX_FTP_DATA_WINDOW_SIZE, NX_NULL, _nx_ftp_server_data_disconnect);
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_CMD_OK, "EPRT command set");
- }
- else
- {
+ /* Determine if the listen is successful. */
+ if (status != NX_SUCCESS)
+ {
- /* Unsuccessful EPRT command. */
+ /* Unsuccessful data socket create. */
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_CMD_FAIL, "EPRT command failed");
- }
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_CMD_FAIL, "EPSV Fail");
- break;
+ /* And we are done processing. */
+ break;
+ }
- }
-
- case NX_FTP_EPSV:
- {
+ /* Make sure each socket points to the corresponding FTP server. */
+ client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_reserved_ptr = ftp_server_ptr;
- /* If create, cleanup the data socket. */
- if (client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_id)
- {
+ /* Start listening on the data port. */
+ status = nx_tcp_server_socket_listen(ftp_server_ptr -> nx_ftp_server_ip_ptr, port, &(client_req_ptr -> nx_ftp_client_request_data_socket), 5, 0);
- /* Clean up the client socket. */
- _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr);
- }
+ /* Determine if the listen is successful. */
+ if (status != NX_SUCCESS)
+ {
- /* Try to find the data port. */
- status = nx_tcp_free_port_find(ftp_server_ptr -> nx_ftp_server_ip_ptr,
- ftp_server_ptr -> nx_ftp_server_data_port++, &port);
+ /* Unsuccessful data socket listen. */
- /* Determine if the EPSV command was successful. */
- if (status != NX_SUCCESS)
- {
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_CMD_FAIL, "EPSV Fail");
- /* Unsuccessful port find. */
+ /* Delete data socket. */
+ nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_CMD_FAIL, "EPSV Fail");
+ /* And we are done processing. */
+ break;
+ }
- /* And we are done processing. */
- break;
- }
+ /* Wait for the data connection to connect. */
+ nx_tcp_server_socket_accept(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_NO_WAIT);
- /* Create an FTP client data socket. */
- status = nx_tcp_socket_create(ftp_server_ptr -> nx_ftp_server_ip_ptr, &(client_req_ptr -> nx_ftp_client_request_data_socket), "FTP Server Data Socket",
- NX_FTP_DATA_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, NX_FTP_DATA_WINDOW_SIZE, NX_NULL, _nx_ftp_server_data_disconnect);
+ /* Reset the packet prepend pointer for alignment. */
+ packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_data_start + NX_TCP_PACKET;
- /* Determine if the listen is successful. */
- if (status != NX_SUCCESS)
- {
+ /* Setup pointer to packet buffer area. */
+ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- /* Unsuccessful data socket create. */
+ /* Now build EPSV response. "229 Entering Extended Passive Mode (|||6446|)." */
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_CMD_FAIL, "EPSV Fail");
+ /* Get port size. */
+ port_size = _nx_ftp_server_utility_fill_port_number(temp_buffer, port);
+
+ /* Verify packet payload. */
+ if ((ULONG)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < (43 + port_size))
+ {
- /* And we are done processing. */
- break;
- }
+ /* Delete data socket. */
+ nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, port);
+ nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
- /* Make sure each socket points to the corresponding FTP server. */
- client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_reserved_ptr = ftp_server_ptr;
+ /* Release the packet. */
+ nx_packet_release(packet_ptr);
+ break;
+ }
- /* Start listening on the data port. */
- status = nx_tcp_server_socket_listen(ftp_server_ptr -> nx_ftp_server_ip_ptr, port, &(client_req_ptr -> nx_ftp_client_request_data_socket), 5, 0);
+ /* Build the string. "229 Entering Extended Passive Mode " */
+ memcpy(buffer_ptr, "229 Entering Extended Passive Mode ", 35); /* Use case of memcpy is verified. */
- /* Determine if the listen is successful. */
- if (status != NX_SUCCESS)
- {
+ /* Build the IPv6 address and port. */
+ buffer_ptr[35] = '(';
+ buffer_ptr[36] = '|';
+ buffer_ptr[37] = '|';
+ buffer_ptr[38] = '|';
- /* Unsuccessful data socket listen. */
+ memcpy(&buffer_ptr[39], temp_buffer, port_size); /* Use case of memcpy is verified. */
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_CMD_FAIL, "EPSV Fail");
+ buffer_ptr[39 + port_size] = '|';
+ buffer_ptr[40 + port_size] = ')';
- /* Delete data socket. */
- nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ /* Set the CR/LF. */
+ buffer_ptr[41 + port_size] = 13;
+ buffer_ptr[42 + port_size] = 10;
- /* And we are done processing. */
- break;
- }
+ /* Set the packet length. */
+ packet_ptr -> nx_packet_length = 43 + port_size;
- /* Wait for the data connection to connect. */
- nx_tcp_server_socket_accept(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_NO_WAIT);
+ /* Setup the packet append pointer. */
+ packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
- /* Reset the packet prepend pointer for alignment. */
- packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_data_start + NX_TCP_PACKET;
+ /* Send the EPSV response message. */
+ status = nx_tcp_socket_send(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, NX_FTP_SERVER_TIMEOUT);
- /* Setup pointer to packet buffer area. */
- buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
+ /* Determine if the send was unsuccessful. */
+ if (status != NX_SUCCESS)
+ {
- /* Now build EPSV response. "229 Entering Extended Passive Mode (|||6446|)." */
+ /* Delete data socket. */
+ nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, port);
+ nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
- /* Get port size. */
- port_size = _nx_ftp_server_utility_fill_port_number(temp_buffer, port);
-
- /* Verify packet payload. */
- if ((ULONG)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < (43 + port_size))
- {
+ /* Release the packet. */
+ nx_packet_release(packet_ptr);
+ }
- /* Delete data socket. */
- nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, port);
- nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ /* Yes, passive transfer enabled. */
+ client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled = NX_TRUE;
- /* Release the packet. */
- nx_packet_release(packet_ptr);
break;
}
+#endif /* FEATURE_NX_IPV6 */
- /* Build the string. "229 Entering Extended Passive Mode " */
- memcpy(buffer_ptr, "229 Entering Extended Passive Mode ", 35); /* Use case of memcpy is verified. */
+ case NX_FTP_CDUP:
+ case NX_FTP_CWD:
+ {
+
+ /* Change to the default directory of this connection. */
+ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr,
+ &(client_req_ptr -> nx_ftp_client_local_path));
- /* Build the IPv6 address and port. */
- buffer_ptr[35] = '(';
- buffer_ptr[36] = '|';
- buffer_ptr[37] = '|';
- buffer_ptr[38] = '|';
+ /* Setup pointer to packet buffer area. */
+ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- memcpy(&buffer_ptr[39], temp_buffer, port_size); /* Use case of memcpy is verified. */
+ /* If CDUP command, create the "up one directory" pathname string. */
+ if (ftp_command == NX_FTP_CDUP)
+ {
- buffer_ptr[39 + port_size] = '|';
- buffer_ptr[40 + port_size] = ')';
+ /* Move the pointer to make sure there is enough memory to store the data. */
+ buffer_ptr -= 3;
+ buffer_ptr[0] = '.';
+ buffer_ptr[1] = '.';
+ buffer_ptr[2] = NX_NULL;
+ }
- /* Set the CR/LF. */
- buffer_ptr[41 + port_size] = 13;
- buffer_ptr[42 + port_size] = 10;
+ /* Otherwise CWD command, parse the pathname string. */
+ else
+ {
- /* Set the packet length. */
- packet_ptr -> nx_packet_length = 43 + port_size;
+ /* Check packet length. */
+ if (packet_ptr -> nx_packet_length == 0)
+ {
- /* Setup the packet append pointer. */
- packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
+ /* Empty message. */
- /* Send the EPSV response message. */
- status = nx_tcp_socket_send(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, NX_FTP_SERVER_TIMEOUT);
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_FILE, "Change Dir Fail");
+ break;
+ }
- /* Determine if the send was unsuccessful. */
- if (status != NX_SUCCESS)
- {
+ /* Find the end of the message. */
+ j = 0;
+ while (j < packet_ptr -> nx_packet_length - 1)
+ {
- /* Delete data socket. */
- nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, port);
- nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket));
+ /* Determine if a CR/LF is present. */
+ if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
+ break;
- /* Release the packet. */
- nx_packet_release(packet_ptr);
- }
+ /* Move to next character. */
+ j++;
+ }
- /* Yes, passive transfer enabled. */
- client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled = NX_TRUE;
+ /* If specified path ends with slash or backslash, strip it. */
+ if ((j > 1) && ((buffer_ptr[j - 1] == '/') || (buffer_ptr[j - 1] == '\\')))
+ {
+ j--;
+ }
- break;
- }
-#endif /* FEATURE_NX_IPV6 */
+ /* Ensure the name is NULL terminated. */
+ buffer_ptr[j] = NX_NULL;
+ }
- case NX_FTP_CDUP:
- case NX_FTP_CWD:
- {
-
- /* Change to the default directory of this connection. */
- fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr,
- &(client_req_ptr -> nx_ftp_client_local_path));
+ /* Set the local path to the path specified. */
+ status = fx_directory_local_path_set(ftp_server_ptr -> nx_ftp_server_media_ptr,
+ &(client_req_ptr -> nx_ftp_client_local_path), (CHAR *) buffer_ptr);
- /* Setup pointer to packet buffer area. */
- buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
+ /* Determine if it was successful. */
+ if (status == NX_SUCCESS)
+ {
- /* If CDUP command, create the "up one directory" pathname string. */
- if (ftp_command == NX_FTP_CDUP)
- {
+ CHAR *local_dir;
- /* Move the pointer to make sure there is enough memory to store the data. */
- buffer_ptr -= 3;
- buffer_ptr[0] = '.';
- buffer_ptr[1] = '.';
- buffer_ptr[2] = NX_NULL;
- }
- /* Otherwise CWD command, parse the pathname string. */
- else
- {
+ /* Successful change directory. */
- /* Check packet length. */
- if (packet_ptr -> nx_packet_length == 0)
+ /* Get the actual path */
+ fx_directory_local_path_get(ftp_server_ptr -> nx_ftp_server_media_ptr, &local_dir);
+
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_directory_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_COMPLETED, "set successfully", local_dir);
+ }
+ else
{
- /* Empty message. */
+ /* Unsuccessful directory change. */
/* Now send an error response to the client. */
_nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
NX_FTP_CODE_BAD_FILE, "Change Dir Fail");
- break;
- }
-
- /* Find the end of the message. */
- j = 0;
- while (j < packet_ptr -> nx_packet_length - 1)
- {
-
- /* Determine if a CR/LF is present. */
- if ((buffer_ptr[j] == 13) || (buffer_ptr[j] == 10) || (buffer_ptr[j] == 0))
- break;
-
- /* Move to next character. */
- j++;
- }
-
- /* If specified path ends with slash or backslash, strip it. */
- if ((j > 1) && ((buffer_ptr[j - 1] == '/') || (buffer_ptr[j - 1] == '\\')))
- {
- j--;
}
-
- /* Ensure the name is NULL terminated. */
- buffer_ptr[j] = NX_NULL;
+ break;
}
- /* Set the local path to the path specified. */
- status = fx_directory_local_path_set(ftp_server_ptr -> nx_ftp_server_media_ptr,
- &(client_req_ptr -> nx_ftp_client_local_path), (CHAR *) buffer_ptr);
-
- /* Determine if it was successful. */
- if (status == NX_SUCCESS)
+ case NX_FTP_PWD:
{
+
+ /* Change to the default directory of this connection. */
+ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
- CHAR *local_dir;
-
-
- /* Successful change directory. */
+ {
- /* Get the actual path */
- fx_directory_local_path_get(ftp_server_ptr -> nx_ftp_server_media_ptr, &local_dir);
+ CHAR *local_dir;
- /* Now send a successful response to the client. */
- _nx_ftp_server_directory_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_COMPLETED, "set successfully", local_dir);
- }
- else
- {
+ /* Pickup the current directory. */
+ fx_directory_local_path_get(ftp_server_ptr -> nx_ftp_server_media_ptr, &local_dir);
- /* Unsuccessful directory change. */
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_directory_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_MADE_DIR, "is current Directory", local_dir);
+ }
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_FILE, "Change Dir Fail");
+ break;
}
- break;
- }
-
- case NX_FTP_PWD:
- {
-
- /* Change to the default directory of this connection. */
- fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path));
+ case NX_FTP_TYPE:
{
+
+ /* Setup pointer to packet buffer area. */
+ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- CHAR *local_dir;
+ /* Determine if a binary transfer is specified. */
+ if (buffer_ptr[0] == 'I')
+ {
- /* Pickup the current directory. */
- fx_directory_local_path_get(ftp_server_ptr -> nx_ftp_server_media_ptr, &local_dir);
+ /* Yes, a binary image is specified and supported. */
+ client_req_ptr -> nx_ftp_client_request_transfer_type = 'I';
- /* Now send a successful response to the client. */
- _nx_ftp_server_directory_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_MADE_DIR, "is current Directory", local_dir);
- }
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_CMD_OK, "Type Binary");
+ }
- break;
- }
+ /* Not Binary - check if ASCII type is specified */
+ else if (buffer_ptr[0] == 'A')
+ {
- case NX_FTP_TYPE:
- {
-
- /* Setup pointer to packet buffer area. */
- buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
+ /* Yes, a ASCII image is specified and supported. */
+ client_req_ptr -> nx_ftp_client_request_transfer_type = 'A';
- /* Determine if a binary transfer is specified. */
- if (buffer_ptr[0] == 'I')
- {
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_CMD_OK, "Type ASCII");
+ }
+ else
+ {
- /* Yes, a binary image is specified and supported. */
- client_req_ptr -> nx_ftp_client_request_transfer_type = 'I';
+ /* Otherwise, a non-binary type is requested. */
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_CMD_OK, "Type Binary");
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_TYPE, "Type Non ASCII or Binary");
+ }
+ break;
}
- /* Not Binary - check if ASCII type is specified */
- else if (buffer_ptr[0] == 'A')
+ case NX_FTP_MODE:
{
- /* Yes, a ASCII image is specified and supported. */
- client_req_ptr -> nx_ftp_client_request_transfer_type = 'A';
+ /* Setup pointer to packet buffer area. */
+ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_CMD_OK, "Type ASCII");
- }
- else
- {
+ /* Determine if stream mode is specified. */
+ if (buffer_ptr[0] == 'S')
+ {
- /* Otherwise, a non-binary type is requested. */
+ /* Yes, stream mode is specified and supported. */
+ client_req_ptr -> nx_ftp_client_request_transfer_mode = NX_FTP_TRANSFER_MODE_STREAM;
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_TYPE, "Type Non ASCII or Binary");
- }
- break;
- }
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_CMD_OK, "Mode Stream");
+ }
- case NX_FTP_MODE:
- {
+ /* Not stream - check if block mode is specified */
+ else if (buffer_ptr[0] == 'B')
+ {
- /* Setup pointer to packet buffer area. */
- buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
+ /* Yes, stream mode is specified and supported. */
+ client_req_ptr -> nx_ftp_client_request_transfer_mode = NX_FTP_TRANSFER_MODE_BLOCK;
- /* Determine if stream mode is specified. */
- if (buffer_ptr[0] == 'S')
- {
+ /* Now send a successful response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_CMD_OK, "Mode Block");
+ }
+ else
+ {
- /* Yes, stream mode is specified and supported. */
- client_req_ptr -> nx_ftp_client_request_transfer_mode = NX_FTP_TRANSFER_MODE_STREAM;
+ /* Now send an error response to the client. */
+ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
+ NX_FTP_CODE_BAD_TYPE, "Mode Non Stream or Block");
+ }
+ break;
+ }
+
+ case NX_FTP_NOOP:
/* Now send a successful response to the client. */
_nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_CMD_OK, "Mode Stream");
- }
+ NX_FTP_CODE_CMD_OK, "NOOP Success");
+ break;
- /* Not stream - check if block mode is specified */
- else if (buffer_ptr[0] == 'B')
- {
+ default:
- /* Yes, stream mode is specified and supported. */
- client_req_ptr -> nx_ftp_client_request_transfer_mode = NX_FTP_TRANSFER_MODE_BLOCK;
+ /* Unimplemented Command. */
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_CMD_OK, "Mode Block");
- }
- else
- {
+ /* Increment the number of unknown commands. */
+ ftp_server_ptr -> nx_ftp_server_unknown_commands++;
/* Now send an error response to the client. */
_nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_BAD_TYPE, "Mode Non Stream or Block");
+ NX_FTP_CODE_NOT_IMPLEMENTED, "Not Implemented");
+ break;
}
- break;
- }
-
- case NX_FTP_NOOP:
-
- /* Now send a successful response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_CMD_OK, "NOOP Success");
- break;
-
- default:
-
- /* Unimplemented Command. */
-
- /* Increment the number of unknown commands. */
- ftp_server_ptr -> nx_ftp_server_unknown_commands++;
-
- /* Now send an error response to the client. */
- _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr,
- NX_FTP_CODE_NOT_IMPLEMENTED, "Not Implemented");
- break;
}
}
}
@@ -5282,7 +5336,7 @@ NX_FTP_SERVER *server_ptr;
/* FUNCTION RELEASE */
/* */
/* _nx_ftp_server_timeout_processing PORTABLE C */
-/* 6.1.9 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -5327,6 +5381,10 @@ NX_FTP_SERVER *server_ptr;
/* fixed the issue of clearing */
/* data socket, */
/* resulting in version 6.1.9 */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), */
+/* fixed duplicate packet */
+/* release issue, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
VOID _nx_ftp_server_timeout_processing(NX_FTP_SERVER *ftp_server_ptr)
@@ -5389,6 +5447,7 @@ NX_FTP_CLIENT_REQUEST *client_req_ptr;
/* Yes, release it! */
nx_packet_release(client_req_ptr -> nx_ftp_client_request_packet);
+ client_req_ptr -> nx_ftp_client_request_packet = NX_NULL;
}
/* Relisten on this socket. This will probably fail, but it is needed just in case all available
@@ -5461,7 +5520,7 @@ NX_FTP_SERVER *server_ptr;
/* FUNCTION RELEASE */
/* */
/* _nx_ftp_server_control_disconnect_processing PORTABLE C */
-/* 6.1.9 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -5505,6 +5564,10 @@ NX_FTP_SERVER *server_ptr;
/* fixed the issue of clearing */
/* data socket, */
/* resulting in version 6.1.9 */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), */
+/* fixed duplicate packet */
+/* release issue, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
VOID _nx_ftp_server_control_disconnect_processing(NX_FTP_SERVER *ftp_server_ptr)
@@ -5598,6 +5661,7 @@ NX_FTP_CLIENT_REQUEST *client_req_ptr;
/* Yes, release it! */
nx_packet_release(client_req_ptr -> nx_ftp_client_request_packet);
+ client_req_ptr -> nx_ftp_client_request_packet = NX_NULL;
}
/* Relisten on this socket. This will probably fail, but it is needed just in case all available
diff --git a/addons/mdns/nxd_mdns.h b/addons/mdns/nxd_mdns.h
index de1fb586..6af899aa 100644
--- a/addons/mdns/nxd_mdns.h
+++ b/addons/mdns/nxd_mdns.h
@@ -25,7 +25,7 @@
/* APPLICATION INTERFACE DEFINITION RELEASE */
/* */
/* nxd_mdns.h PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -52,9 +52,9 @@
/* 04-25-2022 Yuxin Zhou Modified comment(s), */
/* fixed the issue of timer, */
/* resulting in version 6.1.11 */
-/* xx-xx-xxxx Bo Chen Modified comment(s), and */
+/* 10-31-2023 Bo Chen Modified comment(s), and */
/* corrected the symbols check,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
diff --git a/addons/mqtt/nxd_mqtt_client.c b/addons/mqtt/nxd_mqtt_client.c
index b05124fa..d8674b81 100644
--- a/addons/mqtt/nxd_mqtt_client.c
+++ b/addons/mqtt/nxd_mqtt_client.c
@@ -247,7 +247,7 @@ ULONG bytes_copied;
/* FUNCTION RELEASE */
/* */
/* _nxd_mqtt_client_sub_unsub PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -308,9 +308,9 @@ ULONG bytes_copied;
/* 10-31-2022 Bo Chen Modified comment(s), improved */
/* the logic of sending packet,*/
/* resulting in version 6.2.0 */
-/* xx-xx-xxxx Haiqing Zhao Modified comment(s), improved */
+/* 10-31-2023 Haiqing Zhao Modified comment(s), improved */
/* internal logic, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nxd_mqtt_client_sub_unsub(NXD_MQTT_CLIENT *client_ptr, UINT op,
@@ -489,7 +489,7 @@ UCHAR temp_data[2];
/* FUNCTION RELEASE */
/* */
/* _nxd_mqtt_client_packet_allocate PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -542,9 +542,9 @@ UCHAR temp_data[2];
/* 10-31-2022 Bo Chen Modified comment(s), supported*/
/* mqtt over websocket, */
/* resulting in version 6.2.0 */
-/* xx-xx-xxxx Haiqing Zhao Modified comment(s), improved */
+/* 10-31-2023 Haiqing Zhao Modified comment(s), improved */
/* internal logic, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nxd_mqtt_client_packet_allocate(NXD_MQTT_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG wait_option)
@@ -1351,7 +1351,7 @@ ULONG bytes_copied;
/* FUNCTION RELEASE */
/* */
/* _nxd_mqtt_process_publish PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -1397,9 +1397,9 @@ ULONG bytes_copied;
/* 10-31-2022 Bo Chen Modified comment(s), improved */
/* the logic of sending packet,*/
/* resulting in version 6.2.0 */
-/* xx-xx-xxxx Haiqing Zhao Modified comment(s), improved */
+/* 10-31-2023 Haiqing Zhao Modified comment(s), improved */
/* internal logic, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
static UINT _nxd_mqtt_process_publish(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr)
@@ -1611,7 +1611,7 @@ ULONG bytes_copied;
/* FUNCTION RELEASE */
/* */
/* _nxd_mqtt_process_publish_response PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -1654,9 +1654,9 @@ ULONG bytes_copied;
/* 10-31-2022 Bo Chen Modified comment(s), improved */
/* the logic of sending packet,*/
/* resulting in version 6.2.0 */
-/* xx-xx-xxxx Haiqing Zhao Modified comment(s), improved */
+/* 10-31-2023 Haiqing Zhao Modified comment(s), improved */
/* internal logic, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
static UINT _nxd_mqtt_process_publish_response(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr)
@@ -3877,7 +3877,7 @@ UCHAR fixed_header;
/* FUNCTION RELEASE */
/* */
/* _nxd_mqtt_client_connect PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -3949,8 +3949,8 @@ UCHAR fixed_header;
/* 10-31-2022 Bo Chen Modified comment(s), supported*/
/* mqtt over websocket, */
/* resulting in version 6.2.0 */
-/* xx-xx-xxxx Haiqing Zhao Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Haiqing Zhao Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nxd_mqtt_client_connect(NXD_MQTT_CLIENT *client_ptr, NXD_ADDRESS *server_ip, UINT server_port,
@@ -4234,7 +4234,7 @@ UINT old_priority;
/* FUNCTION RELEASE */
/* */
/* _nxd_mqtt_client_connect_packet_send PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -4285,9 +4285,9 @@ UINT old_priority;
/* 10-31-2022 Bo Chen Modified comment(s), improved */
/* the logic of sending packet,*/
/* resulting in version 6.2.0 */
-/* xx-xx-xxxx Haiqing Zhao Modified comment(s), improved */
+/* 10-31-2023 Haiqing Zhao Modified comment(s), improved */
/* internal logic, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nxd_mqtt_client_connect_packet_send(NXD_MQTT_CLIENT *client_ptr, ULONG wait_option)
@@ -4782,7 +4782,7 @@ UINT ret = NXD_MQTT_SUCCESS;
/* FUNCTION RELEASE */
/* */
/* _nxd_mqtt_client_publish PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -4834,9 +4834,9 @@ UINT ret = NXD_MQTT_SUCCESS;
/* 07-29-2022 Spencer McDonough Modified comment(s), */
/* improved internal logic, */
/* resulting in version 6.1.12 */
-/* xx-xx-xxxx Haiqing Zhao Modified comment(s), improved */
+/* 10-31-2023 Haiqing Zhao Modified comment(s), improved */
/* internal logic, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nxd_mqtt_client_publish(NXD_MQTT_CLIENT *client_ptr, CHAR *topic_name, UINT topic_name_length,
@@ -5115,7 +5115,7 @@ UINT _nxd_mqtt_client_unsubscribe(NXD_MQTT_CLIENT *client_ptr, CHAR *topic_name,
/* FUNCTION RELEASE */
/* */
/* _nxd_mqtt_send_simple_message PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -5162,9 +5162,9 @@ UINT _nxd_mqtt_client_unsubscribe(NXD_MQTT_CLIENT *client_ptr, CHAR *topic_name,
/* 10-31-2022 Bo Chen Modified comment(s), improved */
/* the logic of sending packet,*/
/* resulting in version 6.2.0 */
-/* xx-xx-xxxx Haiqing Zhao Modified comment(s), improved */
+/* 10-31-2023 Haiqing Zhao Modified comment(s), improved */
/* internal logic, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
static UINT _nxd_mqtt_send_simple_message(NXD_MQTT_CLIENT *client_ptr, UCHAR header_value)
diff --git a/addons/mqtt/nxd_mqtt_client.h b/addons/mqtt/nxd_mqtt_client.h
index 78c9e416..7a7f5ce2 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.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -58,10 +58,10 @@
/* 10-31-2022 Bo Chen Modified comment(s), supported*/
/* mqtt over websocket, */
/* resulting in version 6.2.0 */
-/* xx-xx-xxxx Haiqing Zhao Modified comment(s), added */
+/* 10-31-2023 Haiqing Zhao Modified comment(s), added */
/* the function prototype for */
/* packet allocation, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
diff --git a/addons/nat/nx_nat.c b/addons/nat/nx_nat.c
index c8eefb3d..aa5cdd56 100644
--- a/addons/nat/nx_nat.c
+++ b/addons/nat/nx_nat.c
@@ -1119,7 +1119,7 @@ NX_NAT_TRANSLATION_ENTRY *next_entry_ptr;
/* FUNCTION RELEASE */
/* */
/* _nx_nat_process_packet PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -1154,7 +1154,7 @@ NX_NAT_TRANSLATION_ENTRY *next_entry_ptr;
/* */
/* CALLED BY */
/* */
-/* _nx_ipv4_packet_receive Netx forwards packet to NAT first */
+/* _nx_ipv4_packet_receive NetX forwards packet to NAT first */
/* if forwarding is enabled. */
/* */
/* RELEASE HISTORY */
@@ -1164,6 +1164,9 @@ NX_NAT_TRANSLATION_ENTRY *next_entry_ptr;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), */
+/* fixed packet double release,*/
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
static UINT _nx_nat_process_packet(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT packet_process)
@@ -1218,18 +1221,20 @@ NX_INTERFACE *interface_ptr;
/* Check for valid packet length. */
if (packet_ptr -> nx_packet_length < header_size)
{
-
+ if (packet_process == NX_TRUE)
+ {
#ifndef NX_DISABLE_IP_INFO
- /* Increment the IP invalid packet error. */
- ip_ptr -> nx_ip_invalid_packets++;
+ /* Increment the IP invalid packet error. */
+ ip_ptr -> nx_ip_invalid_packets++;
- /* Increment the IP receive packets dropped count. */
- ip_ptr -> nx_ip_receive_packets_dropped++;
+ /* Increment the IP receive packets dropped count. */
+ ip_ptr -> nx_ip_receive_packets_dropped++;
#endif
- /* Invalid packet length, just release it. */
- _nx_packet_release(packet_ptr);
-
+ /* Invalid packet length, just release it. */
+ _nx_packet_release(packet_ptr);
+ }
+
/* Return NX_TRUE to indicate this packet has been processed. */
return (NX_TRUE);
}
diff --git a/addons/ppp/nx_ppp.c b/addons/ppp/nx_ppp.c
index d8abc57b..f29c3c86 100644
--- a/addons/ppp/nx_ppp.c
+++ b/addons/ppp/nx_ppp.c
@@ -783,7 +783,7 @@ UINT i;
/* FUNCTION RELEASE */
/* */
/* _nx_ppp_receive_packet_get PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -820,10 +820,10 @@ UINT i;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Wenhui Xie Modified comment(s), and */
+/* 10-31-2023 Wenhui Xie Modified comment(s), and */
/* supported processing */
/* compressed data, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
void _nx_ppp_receive_packet_get(NX_PPP *ppp_ptr, NX_PACKET **return_packet_ptr)
@@ -1447,7 +1447,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* _nx_ppp_receive_packet_process PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -1490,10 +1490,10 @@ UINT status;
/* improved packet length */
/* verification, */
/* resulting in version 6.1.2 */
-/* xx-xx-xxxx Wenhui Xie Modified comment(s), and */
+/* 10-31-2023 Wenhui Xie Modified comment(s), and */
/* supported processing */
/* compressed data, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
void _nx_ppp_receive_packet_process(NX_PPP *ppp_ptr, NX_PACKET *packet_ptr)
@@ -1941,7 +1941,7 @@ NX_PPP *ppp_ptr;
/* FUNCTION RELEASE */
/* */
/* _nx_ppp_netx_packet_transfer PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -1976,10 +1976,10 @@ NX_PPP *ppp_ptr;
/* 09-30-2020 Yuxin Zhou Modified comment(s), and */
/* verified memmove use cases, */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Wenhui Xie Modified comment(s), and */
+/* 10-31-2023 Wenhui Xie Modified comment(s), and */
/* supported processing */
/* compressed data, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
void _nx_ppp_netx_packet_transfer(NX_PPP *ppp_ptr, NX_PACKET *packet_ptr)
@@ -3344,7 +3344,7 @@ NX_PACKET *packet_ptr;
/* FUNCTION RELEASE */
/* */
/* _nx_ppp_lcp_configure_request_send PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -3377,10 +3377,10 @@ NX_PACKET *packet_ptr;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Wenhui Xie Modified comment(s), and */
+/* 10-31-2023 Wenhui Xie Modified comment(s), and */
/* supported processing */
/* compressed data, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
void _nx_ppp_lcp_configure_request_send(NX_PPP *ppp_ptr)
diff --git a/addons/ppp/nx_ppp.h b/addons/ppp/nx_ppp.h
index 835aa82c..ac2bc31e 100644
--- a/addons/ppp/nx_ppp.h
+++ b/addons/ppp/nx_ppp.h
@@ -26,7 +26,7 @@
/* APPLICATION INTERFACE DEFINITION RELEASE */
/* */
/* nx_ppp.h PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -52,10 +52,10 @@
/* 10-15-2021 Yuxin Zhou Modified comment(s), included */
/* necessary header file, */
/* resulting in version 6.1.9 */
-/* xx-xx-xxxx Wenhui Xie Modified comment(s), and */
+/* 10-31-2023 Wenhui Xie Modified comment(s), and */
/* supported processing */
/* compressed data, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
diff --git a/addons/rtp/nx_rtp_sender.c b/addons/rtp/nx_rtp_sender.c
new file mode 100644
index 00000000..45d8821b
--- /dev/null
+++ b/addons/rtp/nx_rtp_sender.c
@@ -0,0 +1,3981 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Real Time Transport Protocol (RTP) */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define NX_RTP_SENDER_SOURCE_CODE
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "nx_api.h"
+#include "nx_ip.h"
+#ifdef FEATURE_NX_IPV6
+#include "nx_ipv6.h"
+#endif /* FEATURE_NX_IPV6 */
+#include "nx_udp.h"
+#include "nx_rtp_sender.h"
+
+
+/* Define JPEG quantization table parameters. */
+#define NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_MAX_NUM (4)
+#define NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_LENGTH (64)
+
+/* Define H264 parameters. */
+#define NX_RTP_SENDER_H264_NRI_MASK_BITS (0x60) /* The mask bits of relative transport priority. */
+#define NX_RTP_SENDER_H264_TYPE_MASK_BITS (0x1F) /* The mask bits of NAL unit type.*/
+#define NX_RTP_SENDER_H264_TYPE_SEI (6)
+#define NX_RTP_SENDER_H264_TYPE_SPS (7)
+#define NX_RTP_SENDER_H264_TYPE_PPS (8)
+#define NX_RTP_SENDER_H264_TYPE_FU_A (28)
+#define NX_RTP_SENDER_H264_FU_A_S_MASK_BIT (0x80)
+#define NX_RTP_SENDER_H264_FU_A_E_MASK_BIT (0x40)
+
+/* Define AAC parameters. */
+#define NX_RTP_SENDER_AAC_HBR_MODE_MAX_DATA_SIZE (8191) /* RFC 3640, p25, section 3.3.6. */
+#define NX_RTP_SENDER_AAC_FRAME_DATA_LENGTH_HIGH_BITS_MASK (0x1FE0)
+#define NX_RTP_SENDER_AAC_FRAME_DATA_LENGTH_LOW_BITS_MASK (0x1F)
+
+/* Declare rtp sender internal functions */
+static UINT _nx_rtp_sender_cleanup(NX_RTP_SENDER *rtp_sender);
+static UINT _nx_rtp_sender_session_find(NX_RTP_SENDER *rtp_sender, UINT ssrc, NX_RTP_SESSION **session);
+static VOID _nx_rtp_sender_session_link(NX_RTP_SENDER *rtp_sender, NX_RTP_SESSION *session);
+static UINT _nx_rtp_sender_session_unlink(NX_RTP_SENDER *rtp_sender, NX_RTP_SESSION *session);
+
+static UINT _nx_rtcp_packet_process(NX_RTP_SENDER *rtp_sender, NX_PACKET *packet_ptr);
+static UINT _nx_rtcp_packet_rr_process(NX_RTP_SENDER *rtp_sender, NX_RTCP_HEADER *header);
+static UINT _nx_rtcp_packet_sdes_process(NX_RTP_SENDER *rtp_sender, NX_RTCP_HEADER *header);
+static UINT _nx_rtcp_sr_data_append(NX_RTP_SESSION *session, NX_PACKET *packet_ptr);
+static UINT _nx_rtcp_sdes_data_append(NX_RTP_SESSION *session, NX_PACKET *packet_ptr);
+static UINT _nx_rtcp_packet_send(NX_RTP_SESSION *session);
+static VOID _nx_rtcp_packet_receive_notify(NX_UDP_SOCKET *socket_ptr);
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtp_sender_create PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks errors in the RTP sender create function call. */
+/* */
+/* INPUT */
+/* */
+/* rtp_sender Pointer to RTP Sender instance */
+/* ip_ptr Pointer to IP instance */
+/* pool_ptr Pointer to the packet pool */
+/* cname Pointer to the name string */
+/* shown in rtcp SDES report */
+/* cname_length The length of the name string */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* NX_PTR_ERROR Invalid pointer input */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_create Create rtp sender */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtp_sender_create(NX_RTP_SENDER *rtp_sender, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, CHAR *cname, UCHAR cname_length)
+{
+
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((rtp_sender == NX_NULL) || (ip_ptr == NX_NULL) || (pool_ptr == NX_NULL) || (rtp_sender -> nx_rtp_sender_id == NX_RTP_SENDER_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual RTP sender create service. */
+ status = _nx_rtp_sender_create(rtp_sender, ip_ptr, pool_ptr, cname, cname_length);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtp_sender_create PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function creates a RTP sender on the specified IP. */
+/* */
+/* INPUT */
+/* */
+/* rtp_sender Pointer to RTP Sender instance */
+/* ip_ptr Pointer to IP instance */
+/* pool_ptr Pointer to the packet pool */
+/* cname Pointer to the name string */
+/* shown in rtcp SDES report */
+/* cname_length The length of the name string */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* memset Reset memory */
+/* tx_mutex_create Create RTP sender mutex */
+/* tx_mutex_delete Delete RTP sender mutex */
+/* nx_udp_socket_create Create RTP sender UDP socket */
+/* nx_udp_socket_delete Delete RTP sender UDP socket */
+/* nx_udp_free_port_find Find a free UDP port for RTP */
+/* or RTCP socket */
+/* nx_udp_socket_bind Bind a UDP port for RTP */
+/* or RTCP socket */
+/* nx_udp_socket_unbind Unbind UDP port for RTP socket */
+/* _nx_rtp_sender_cleanup Clean-up resources */
+/* nx_udp_socket_receive_notify Set callback function for UDP */
+/* data receive notify */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtp_sender_create(NX_RTP_SENDER *rtp_sender, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, CHAR *cname, UCHAR cname_length)
+{
+
+UINT status;
+UINT free_port;
+
+
+ /* Reset the rtp_sender data structure. */
+ memset(rtp_sender, 0, sizeof(NX_RTP_SENDER));
+
+ /* Create mutex protection. */
+ status = tx_mutex_create(&(rtp_sender -> nx_rtp_sender_protection), "RTP sender protection", TX_INHERIT);
+ if (status)
+ {
+ return(status);
+ }
+
+ /* Create RTP UDP socket. */
+ status = nx_udp_socket_create(ip_ptr, &(rtp_sender -> nx_rtp_sender_rtp_socket), "RTP Socket",
+ NX_RTP_SENDER_TYPE_OF_SERVICE, NX_RTP_SENDER_FRAGMENT_OPTION,
+ NX_RTP_SENDER_TIME_TO_LIVE, NX_RTP_SENDER_QUEUE_DEPTH);
+ if (status)
+ {
+
+ /* Delete already created resources and return error status. */
+ tx_mutex_delete(&(rtp_sender -> nx_rtp_sender_protection));
+ return(status);
+ }
+
+ /* Create RTCP UDP socket. */
+ status = nx_udp_socket_create(ip_ptr, &(rtp_sender -> nx_rtp_sender_rtcp_socket), "RTCP Socket",
+ NX_RTP_SENDER_TYPE_OF_SERVICE, NX_RTP_SENDER_FRAGMENT_OPTION,
+ NX_RTP_SENDER_TIME_TO_LIVE, NX_RTP_SENDER_QUEUE_DEPTH);
+ if (status)
+ {
+
+ /* Delete already created resources and return error status. */
+ tx_mutex_delete(&(rtp_sender -> nx_rtp_sender_protection));
+ nx_udp_socket_delete(&(rtp_sender -> nx_rtp_sender_rtp_socket));
+ return(status);
+ }
+
+ /* Start from the suggested default port number. */
+ rtp_sender -> nx_rtp_sender_rtp_port = NX_RTP_SENDER_INITIAL_RTP_PORT;
+
+ while (1)
+ {
+
+ /* Try to find an available port for RTP. */
+ status = nx_udp_free_port_find(ip_ptr, rtp_sender -> nx_rtp_sender_rtp_port, &free_port);
+ if (status)
+ {
+ break;
+ }
+ else if (rtp_sender -> nx_rtp_sender_rtp_port > free_port)
+ {
+
+ /* Return since there will be no even number port obtained. */
+ status = NX_NO_FREE_PORTS;
+ break;
+ }
+
+ /* Check if free_port is an odd number. */
+ if ((free_port & 1) != 0)
+ {
+
+ /* Check if the found free port reaches maximum. */
+ if (free_port == NX_MAX_PORT)
+ {
+
+ /* Return since there will be no even number port obtained. */
+ status = NX_NO_FREE_PORTS;
+ break;
+ }
+
+ /* Free UDP port is not the one we expected for RTP. Move to the next port number and try again. */
+ rtp_sender -> nx_rtp_sender_rtp_port = (USHORT)(free_port + 1);
+ }
+ else
+ {
+
+ /* Set RTP port. */
+ rtp_sender -> nx_rtp_sender_rtp_port = (USHORT)free_port;
+ }
+
+ /* Both RTP and RTCP ports are available. Now do a real RTP bind. */
+ status = nx_udp_socket_bind(&(rtp_sender -> nx_rtp_sender_rtp_socket), rtp_sender -> nx_rtp_sender_rtp_port, NX_NO_WAIT);
+ if (status == NX_SUCCESS)
+ {
+
+ /* RTP socket was bound successfully. Now try RTCP socket. */
+
+ /* Set RTCP port to be the next odd port of RTP port and bind. */
+ rtp_sender -> nx_rtp_sender_rtcp_port = (USHORT)(rtp_sender -> nx_rtp_sender_rtp_port + 1);
+ status = nx_udp_socket_bind(&(rtp_sender -> nx_rtp_sender_rtcp_socket), rtp_sender -> nx_rtp_sender_rtcp_port, NX_NO_WAIT);
+ if (status == NX_SUCCESS)
+ {
+
+ /* Jump out since both ports are found. */
+ break;
+ }
+
+ /* RTCP port is unavailable. Unbind the RTP port and try again. */
+ nx_udp_socket_unbind(&(rtp_sender -> nx_rtp_sender_rtp_socket));
+ }
+
+ /* Move and check next possible even port. */
+ rtp_sender -> nx_rtp_sender_rtp_port = (USHORT)(rtp_sender -> nx_rtp_sender_rtp_port + 2);
+ if (rtp_sender -> nx_rtp_sender_rtp_port == 0)
+ {
+ status = NX_NO_FREE_PORTS;
+ break;
+ }
+ }
+
+ /* Clean-up generated resources if fails to find a rtp/rtcp port pair. */
+ if (status)
+ {
+ _nx_rtp_sender_cleanup(rtp_sender);
+ return(status);
+ }
+
+ /* Store pool pointer. */
+ rtp_sender -> nx_rtp_sender_packet_pool_ptr = pool_ptr;
+
+ /* Set application-specific filed indicating the socket is associated with this RTP sender instance. */
+ rtp_sender -> nx_rtp_sender_rtcp_socket.nx_udp_socket_reserved_ptr = (void *)rtp_sender;
+
+ /* Install RTCP callback. */
+ nx_udp_socket_receive_notify(&(rtp_sender -> nx_rtp_sender_rtcp_socket), _nx_rtcp_packet_receive_notify);
+
+ /* Update rtp variables. */
+ rtp_sender -> nx_rtp_sender_id = NX_RTP_SENDER_ID;
+ rtp_sender -> nx_rtp_sender_ip_ptr = ip_ptr;
+ rtp_sender -> nx_rtp_sender_cname = cname;
+ rtp_sender -> nx_rtp_sender_cname_length = cname_length;
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtp_sender_delete PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks errors in the RTP sender delete function call. */
+/* */
+/* INPUT */
+/* */
+/* rtp_sender Pointer to RTP Sender instance */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* NX_PTR_ERROR Invalid pointer input */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_delete Delete RTP sender */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtp_sender_delete(NX_RTP_SENDER *rtp_sender)
+{
+
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((rtp_sender == NX_NULL) || (rtp_sender -> nx_rtp_sender_id != NX_RTP_SENDER_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual RTP sender delete service. */
+ status = _nx_rtp_sender_delete(rtp_sender);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtp_sender_delete PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function deletes a previous created RTP sender */
+/* */
+/* INPUT */
+/* */
+/* rtp_sender Pointer to RTP Sender instance */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* NX_DELETE_ERROR Fail to delete RTP sender */
+/* */
+/* CALLS */
+/* */
+/* tx_mutex_get Obtain protection mutex */
+/* tx_mutex_put Release protection mutex */
+/* _nx_rtp_sender_cleanup Clean-up resources */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtp_sender_delete(NX_RTP_SENDER *rtp_sender)
+{
+
+ /* Obtain the mutex. */
+ tx_mutex_get(&(rtp_sender -> nx_rtp_sender_protection), TX_WAIT_FOREVER);
+
+ /* rtp sender can only be deleted when all sessions have been deleted. */
+ if (rtp_sender -> nx_rtp_sender_session_created_ptr)
+ {
+
+ /* Release the mutex and return error status. */
+ tx_mutex_put(&(rtp_sender -> nx_rtp_sender_protection));
+ return(NX_DELETE_ERROR);
+ }
+
+ /* Set the id to be 0 to make sure other api functions (except create) cannot execute after deleting. */
+ rtp_sender -> nx_rtp_sender_id = 0;
+
+ /* Release the mutex */
+ tx_mutex_put(&(rtp_sender -> nx_rtp_sender_protection));
+
+ /* Clean-up all generated resources. */
+ _nx_rtp_sender_cleanup(rtp_sender);
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtp_sender_port_get PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks errors in the RTP sender port get function */
+/* call. */
+/* */
+/* INPUT */
+/* */
+/* rtp_sender Pointer to RTP Sender instance */
+/* rtp_port Pointer to returned RTP port */
+/* rtcp_port Pointer to returned RTCP port */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* NX_PTR_ERROR Invalid pointer input */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_port_get Get the bound RTP port and */
+/* RTCP port in RTP sender */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtp_sender_port_get(NX_RTP_SENDER *rtp_sender, UINT *rtp_port, UINT *rtcp_port)
+{
+
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((rtp_sender == NX_NULL) || (rtp_sender -> nx_rtp_sender_id != NX_RTP_SENDER_ID) ||
+ (rtp_port == NX_NULL) || (rtcp_port == NX_NULL))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual RTP sender port get service. */
+ status = _nx_rtp_sender_port_get(rtp_sender, rtp_port, rtcp_port);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtp_sender_port_get PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function returns bound RTP and RTCP port pair in RTP sender. */
+/* */
+/* INPUT */
+/* */
+/* rtp_sender Pointer to RTP Sender instance */
+/* rtp_port Pointer to returned RTP port */
+/* rtcp_port Pointer to returned RTCP port */
+/* */
+/* OUTPUT */
+/* */
+/* NX_SUCCESS Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_port_get Get the bound RTP port and */
+/* RTCP port in RTP sender */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtp_sender_port_get(NX_RTP_SENDER *rtp_sender, UINT *rtp_port, UINT *rtcp_port)
+{
+
+ /* Set RTP port and RTCP port. */
+ *rtp_port = rtp_sender -> nx_rtp_sender_rtp_port;
+ *rtcp_port = rtp_sender -> nx_rtp_sender_rtcp_port;
+
+ /* All done. Return success code. */
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtp_sender_session_create PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks errors in the RTP sender session create */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* rtp_sender Pointer to RTP Sender instance */
+/* session Pointer to RTP session */
+/* payload_type Payload type number */
+/* interface_index IP interface index */
+/* receiver_ip_address The receiver's IP address */
+/* receiver_rtp_port_number The receiver's RTP port */
+/* receiver_rtcp_port_number The receiver's RTCP port */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* NX_PTR_ERROR Invalid pointer input */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_session_create Create RTP session with */
+/* specific arguments */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtp_sender_session_create(NX_RTP_SENDER *rtp_sender, NX_RTP_SESSION *session, ULONG payload_type,
+ UINT interface_index, NXD_ADDRESS *receiver_ip_address,
+ UINT receiver_rtp_port_number, UINT receiver_rtcp_port_number)
+{
+
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((rtp_sender == NX_NULL) || (rtp_sender -> nx_rtp_sender_id != NX_RTP_SENDER_ID) ||
+ (session == NX_NULL) || (session -> nx_rtp_session_id == NX_RTP_SESSION_ID) ||
+ (receiver_ip_address == NX_NULL))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
+ {
+ return(NX_INVALID_INTERFACE);
+ }
+
+ /* Call actual RTP sender session create service. */
+ status = _nx_rtp_sender_session_create(rtp_sender, session, payload_type,
+ interface_index, receiver_ip_address,
+ receiver_rtp_port_number, receiver_rtcp_port_number);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtp_sender_session_create PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function creates a RTP session with specific arguments. */
+/* */
+/* INPUT */
+/* */
+/* rtp_sender Pointer to RTP Sender instance */
+/* session Pointer to RTP session */
+/* payload_type Payload type number */
+/* interface_index IP interface index */
+/* receiver_ip_address The receiver's IP address */
+/* receiver_rtp_port_number The receiver's RTP port */
+/* receiver_rtcp_port_number The receiver's RTCP port */
+/* */
+/* OUTPUT */
+/* */
+/* NX_SUCCESS Completion status */
+/* NX_INVALID_PARAMETERS Payload type out of range */
+/* NX_IP_ADDRESS_ERROR Unsupported IP version */
+/* */
+/* CALLS */
+/* */
+/* memset Reset memory */
+/* COPY_IPV6_ADDRESS Make a copy of an IPv6 address */
+/* NX_RAND Generate a random number */
+/* tx_mutex_get Obtain protection mutex */
+/* tx_mutex_put Release protection mutex */
+/* _nx_rtp_sender_session_link Link the created session into */
+/* RTP sender control block */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtp_sender_session_create(NX_RTP_SENDER *rtp_sender, NX_RTP_SESSION *session, ULONG payload_type,
+ UINT interface_index, NXD_ADDRESS *receiver_ip_address,
+ UINT receiver_rtp_port_number, UINT receiver_rtcp_port_number)
+{
+
+ /* Check and validate rtp payload type with valid range from 0 to 127 (7 bits). */
+ if (payload_type > 127)
+ {
+ return(NX_INVALID_PARAMETERS);
+ }
+
+ /* Reset rtp session members. */
+ memset(session, 0, sizeof(NX_RTP_SESSION));
+
+ /* Record peer's ip address and rtp/rtcp port pair. */
+ session -> nx_rtp_session_peer_ip_address.nxd_ip_version = receiver_ip_address -> nxd_ip_version;
+
+ /* Store the receiver's ip interface index into the session. */
+ session -> nx_rtp_session_interface_index = interface_index;
+
+ if (receiver_ip_address -> nxd_ip_version == NX_IP_VERSION_V4)
+ {
+#ifndef NX_DISABLE_IPV4
+ session -> nx_rtp_session_peer_ip_address.nxd_ip_address.v4 = receiver_ip_address -> nxd_ip_address.v4;
+
+ /* Compute the maximum frame packet length based on mtu size. */
+ session -> nx_rtp_session_max_packet_size = rtp_sender -> nx_rtp_sender_ip_ptr -> nx_ip_interface[interface_index].nx_interface_ip_mtu_size
+ - sizeof(NX_UDP_HEADER) - NX_RTP_HEADER_LENGTH - sizeof(NX_IPV4_HEADER);
+#else
+ return(NX_IP_ADDRESS_ERROR);
+#endif /* NX_DISABLE_IPV4 */
+ }
+ else if (receiver_ip_address -> nxd_ip_version == NX_IP_VERSION_V6)
+ {
+#ifdef FEATURE_NX_IPV6
+ COPY_IPV6_ADDRESS(receiver_ip_address -> nxd_ip_address.v6, session -> nx_rtp_session_peer_ip_address.nxd_ip_address.v6);
+
+ /* Compute the maximum frame packet length based on mtu size. */
+ session -> nx_rtp_session_max_packet_size = rtp_sender -> nx_rtp_sender_ip_ptr -> nx_ip_interface[interface_index].nx_interface_ip_mtu_size
+ - sizeof(NX_UDP_HEADER) - NX_RTP_HEADER_LENGTH - sizeof(NX_IPV6_HEADER);
+#else
+ return(NX_IP_ADDRESS_ERROR);
+#endif /* #ifdef FEATURE_NX_IPV6 */
+ }
+ else
+ {
+ return(NX_IP_ADDRESS_ERROR);
+ }
+
+ /* Store the receiver's rtp/rtcp ports number. */
+ session -> nx_rtp_session_peer_rtp_port = (USHORT)receiver_rtp_port_number;
+ session -> nx_rtp_session_peer_rtcp_port = (USHORT)receiver_rtcp_port_number;
+
+ /* Record session payload type. */
+ session -> nx_rtp_session_payload_type = (UCHAR)(payload_type);
+
+ /* Generate random values for the ssrc and sequence number. */
+ session -> nx_rtp_session_ssrc = (ULONG)NX_RAND();
+ session -> nx_rtp_session_sequence_number = (USHORT)NX_RAND();
+
+ /* Record the rtp sender pointer in the session. */
+ session -> nx_rtp_sender = rtp_sender;
+
+ /* Obtain the mutex */
+ tx_mutex_get(&(rtp_sender -> nx_rtp_sender_protection), TX_WAIT_FOREVER);
+
+ _nx_rtp_sender_session_link(rtp_sender, session);
+
+ /* Release the mutex and return success status. */
+ tx_mutex_put(&(rtp_sender -> nx_rtp_sender_protection));
+
+ /* Set session magic number to indicate the session is created successfully. */
+ session -> nx_rtp_session_id = NX_RTP_SESSION_ID;
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtp_sender_session_delete PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks errors in the rtp sender session delete */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* NX_PTR_ERROR Invalid pointer input */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_session_delete Delete RTP session */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtp_sender_session_delete(NX_RTP_SESSION *session)
+{
+
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((session == NX_NULL) || (session -> nx_rtp_sender == NX_NULL) || (session -> nx_rtp_session_id != NX_RTP_SESSION_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual RTP sender session delete service. */
+ status = _nx_rtp_sender_session_delete(session);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtp_sender_session_delete PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function deletes a RTP session. */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* */
+/* OUTPUT */
+/* */
+/* NX_SUCCESS Completion status */
+/* */
+/* CALLS */
+/* */
+/* tx_mutex_get Obtain protection mutex */
+/* tx_mutex_put Release protection mutex */
+/* _nx_rtp_sender_session_unlink Unlink the session from */
+/* RTP sender control block */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtp_sender_session_delete(NX_RTP_SESSION *session)
+{
+
+ /* Reset the rtp session id. */
+ session -> nx_rtp_session_id = 0;
+
+ /* Obtain the mutex. */
+ tx_mutex_get(&(session -> nx_rtp_sender -> nx_rtp_sender_protection), TX_WAIT_FOREVER);
+
+ _nx_rtp_sender_session_unlink(session -> nx_rtp_sender, session);
+
+ /* Release the mutex and return success status. */
+ tx_mutex_put(&(session -> nx_rtp_sender -> nx_rtp_sender_protection));
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtp_sender_rtcp_receiver_report_callback_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Ting Zhu, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks errors in rtcp receiver report callback set */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* rtp_sender Pointer to RTP sender */
+/* rtcp_rr_cb Application specified */
+/* callback function */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_rtcp_receiver_report_callback_set */
+/* Set RTCP RR packet receive */
+/* notify function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtp_sender_rtcp_receiver_report_callback_set(NX_RTP_SENDER *rtp_sender, UINT (*rtcp_rr_cb)(NX_RTP_SESSION *, NX_RTCP_RECEIVER_REPORT *))
+{
+
+UINT status;
+
+
+ /* Validate user input parameter. */
+ if ((rtp_sender == NX_NULL) || (rtp_sender -> nx_rtp_sender_id != NX_RTP_SENDER_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual RTP sender rtcp receiver report callback service. */
+ status = _nx_rtp_sender_rtcp_receiver_report_callback_set(rtp_sender, rtcp_rr_cb);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtp_sender_rtcp_receiver_report_callback_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Ting Zhu, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sets a callback routine for RTCP RR packet receive */
+/* notification. If a NULL pointer is supplied the receive notify */
+/* function is disabled. Note that this callback function is invoked */
+/* from the IP thread, Application shall not block the thread. */
+/* */
+/* INPUT */
+/* */
+/* rtp_sender Pointer to RTP sender */
+/* rtcp_rr_cb Application specified */
+/* callback function */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtp_sender_rtcp_receiver_report_callback_set(NX_RTP_SENDER *rtp_sender, UINT (*rtcp_rr_cb)(NX_RTP_SESSION *, NX_RTCP_RECEIVER_REPORT *))
+{
+ rtp_sender -> nx_rtp_sender_rtcp_receiver_report_cb = rtcp_rr_cb;
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtp_sender_rtcp_sdes_callback_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Ting Zhu, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks errors in rtcp sdes callback set function call.*/
+/* */
+/* INPUT */
+/* */
+/* rtp_sender Pointer to RTP sender */
+/* rtcp_sdes_cb Application specified */
+/* callback function */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_rtcp_sdes_callback_set Set RTCP SDES packet receive */
+/* notify function */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtp_sender_rtcp_sdes_callback_set(NX_RTP_SENDER *rtp_sender, UINT (*rtcp_sdes_cb)(NX_RTCP_SDES_INFO *))
+{
+
+UINT status;
+
+
+ /* Validate user input parameter. */
+ if ((rtp_sender == NX_NULL) || (rtp_sender -> nx_rtp_sender_id != NX_RTP_SENDER_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual RTP sender rtcp sdes callback service. */
+ status = _nx_rtp_sender_rtcp_sdes_callback_set(rtp_sender, rtcp_sdes_cb);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtp_sender_rtcp_sdes_callback_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Ting Zhu, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sets a callback routine for RTCP SDES packet receive */
+/* notification. If a NULL pointer is supplied the receive notify */
+/* function is disabled. Note that this callback function is invoked */
+/* from the IP thread, Application shall not block the thread. */
+/* */
+/* INPUT */
+/* */
+/* rtp_sender Pointer to RTP sender */
+/* rtcp_sdes_cb Application specified */
+/* callback function */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtp_sender_rtcp_sdes_callback_set(NX_RTP_SENDER *rtp_sender, UINT (*rtcp_sdes_cb)(NX_RTCP_SDES_INFO *))
+{
+ rtp_sender -> nx_rtp_sender_rtcp_sdes_cb = rtcp_sdes_cb;
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtp_sender_session_packet_allocate PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks errors in the RTP sender session packet */
+/* allocate function call. */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* packet_ptr Pointer to allocated packet */
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* NX_PTR_ERROR Invalid pointer input */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_session_packet_allocate */
+/* Allocate a packet for the user */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtp_sender_session_packet_allocate(NX_RTP_SESSION *session, NX_PACKET **packet_ptr, ULONG wait_option)
+{
+
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((session == NX_NULL) || (session -> nx_rtp_sender == NX_NULL) || (session -> nx_rtp_session_id != NX_RTP_SESSION_ID) || (packet_ptr == NX_NULL))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual RTP sender session packet allocate service. */
+ status = _nx_rtp_sender_session_packet_allocate(session, packet_ptr, wait_option);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtp_sender_session_packet_allocate PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function allocate a RTP packet from the packet pool given */
+/* by rtp_sender_create, and returns this packet to the user. */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* packet_ptr Pointer to allocated packet */
+/* wait_option Suspension option */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* nx_packet_allocate Allocate a new packet */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtp_sender_session_packet_allocate(NX_RTP_SESSION *session, NX_PACKET **packet_ptr, ULONG wait_option)
+{
+
+UINT status;
+
+
+ /* Allocate and get the packet from IP default packet pool. */
+ status = nx_packet_allocate(session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, packet_ptr, NX_RTP_PACKET, wait_option);
+
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtp_sender_session_packet_send PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks errors in the RTP sender session packet send */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* packet_ptr Pointer to packet data to send */
+/* timestamp RTP timestamp for current data */
+/* ntp_msw Most significant word of */
+/* network time */
+/* ntp_lsw Least significant word of */
+/* network time */
+/* marker Marker bit for significant */
+/* event such as frame boundary */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* NX_PTR_ERROR Invalid pointer input */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_session_packet_send Send packet data */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtp_sender_session_packet_send(NX_RTP_SESSION *session, NX_PACKET *packet_ptr, ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker)
+{
+
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((session == NX_NULL) || (session -> nx_rtp_sender == NX_NULL) || (session -> nx_rtp_session_id != NX_RTP_SESSION_ID) || (packet_ptr == NX_NULL))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Check for an invalid packet prepend pointer. */
+ if ((INT)(packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_data_start) < (INT)(NX_RTP_PACKET))
+ {
+ return(NX_UNDERFLOW);
+ }
+
+ /* Call actual RTP sender session packet send service. */
+ status = _nx_rtp_sender_session_packet_send(session, packet_ptr, timestamp, ntp_msw, ntp_lsw, marker);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtp_sender_session_packet_send PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sends passed packet data in RTP format, and calls */
+/* RTP sender rctp send function as the entry to send RTCP report */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* packet_ptr Pointer to packet data to send */
+/* timestamp RTP timestamp for current data */
+/* ntp_msw Most significant word of */
+/* network time */
+/* ntp_lsw Least significant word of */
+/* network time */
+/* marker Marker bit for significant */
+/* event such as frame boundary */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* NX_CHANGE_USHORT_ENDIAN Adjust USHORT variable endian */
+/* _nx_rtcp_packet_send Send RTCP report */
+/* nxd_udp_socket_source_send Send RTP packet through UDP */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtp_sender_session_packet_send(NX_RTP_SESSION *session, NX_PACKET *packet_ptr, ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker)
+{
+
+UINT status;
+NX_RTP_HEADER *rtp_header_ptr;
+NX_PACKET *send_packet;
+NX_PACKET *data_packet = packet_ptr;
+UCHAR *data_ptr = data_packet -> nx_packet_prepend_ptr;
+UINT sample_factor = session -> nx_rtp_session_sample_factor;
+ULONG fragment_size = session -> nx_rtp_session_max_packet_size;
+ULONG remaining_bytes = packet_ptr -> nx_packet_length;
+ULONG payload_data_length;
+ULONG copy_size;
+UINT fragmentation = NX_FALSE;
+
+
+ /* Transfer marker bit into rtp header field. */
+ if (marker)
+ {
+ marker = (UINT)NX_RTP_HEADER_MARKER_BIT;
+ }
+
+ /* Compare and set the fragmentation flag. */
+ if (packet_ptr -> nx_packet_length > fragment_size)
+ {
+ fragmentation = NX_TRUE;
+ }
+
+ while (remaining_bytes)
+ {
+ if (fragmentation == NX_FALSE)
+ {
+
+ /* No fragmentation needed, set send packet to user passed packet directly. */
+ send_packet = packet_ptr;
+ }
+ else
+ {
+
+ /* Allocate a rtp packet for fragmentation. */
+ status = _nx_rtp_sender_session_packet_allocate(session, &send_packet, NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ return(status);
+ }
+
+ /* Copy data. */
+ while (send_packet -> nx_packet_length < fragment_size)
+ {
+
+ /* Compute how many data bytes to copy in the current packet. */
+ copy_size = (ULONG)(data_packet -> nx_packet_append_ptr - data_ptr);
+ if ((send_packet -> nx_packet_length + copy_size) > fragment_size)
+ {
+
+ /* Compute copy size with the remaining packet space in the send packet. */
+ copy_size = fragment_size - send_packet -> nx_packet_length;
+ }
+
+ /* Copy data into the send packet. */
+ status = nx_packet_data_append(send_packet, data_ptr, copy_size, session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+
+ /* Release the allocated send packet and return error status. */
+ nx_packet_release(send_packet);
+ return(status);
+ }
+
+ /* Move the data pointer after a success copy. */
+ data_ptr += copy_size;
+
+ /* Make sure all data in current packet finish copying. */
+ if (data_ptr >= data_packet -> nx_packet_append_ptr)
+ {
+ if (data_packet -> nx_packet_next == NX_NULL)
+ {
+
+ /* Jump out current while loop when finding all data packets finish copying. */
+ break;
+ }
+ else
+ {
+
+ /* Move to the next packet. */
+ data_packet = data_packet -> nx_packet_next;
+
+ /* Move the data pointer to the initial position of the next packet. */
+ data_ptr = data_packet -> nx_packet_prepend_ptr;
+ }
+ }
+ }
+ }
+
+ /* Obtain payload data length and decrease remaining bytes with it. */
+ payload_data_length = send_packet -> nx_packet_length;
+ remaining_bytes -= payload_data_length;
+
+ /* Add rtp header information.
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |V=2|P|X| CC |M| PT | sequence number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | timestamp |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | synchronization source (SSRC) identifier |
+ +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ */
+
+ /* Update the overall packet length, assign rtp_header pointer to the initial position. */
+ send_packet -> nx_packet_length += NX_RTP_HEADER_LENGTH;
+ send_packet -> nx_packet_prepend_ptr -= NX_RTP_HEADER_LENGTH;
+ rtp_header_ptr = (NX_RTP_HEADER *)(send_packet -> nx_packet_prepend_ptr);
+
+ /* Fill field 0 which contains following 4 sub-fields (3 of them are considered no need to support so far).
+ 1) The RTP protocol version number is always 2.
+ 2) The padding feature is ignored (i.e not supported) by using lower level padding if required (e.g. tls)
+ 3) The extension bit/feature is set to zero (i.e. not supported)
+ 4) The contributing source identifiers count is set to zero (i.e. not supported) */
+ rtp_header_ptr -> nx_rtp_header_field0 = (NX_RTP_VERSION << 6);
+
+ /* Fill the second byte by the payload type recorded in the session context. */
+ rtp_header_ptr -> nx_rtp_header_field1 = session -> nx_rtp_session_payload_type;
+
+ /* Set the marker bit which is intended to allow significant events such as frame boundaries to be marked in the packet stream.
+ This is a user selectable flag and allow the user to choose whether to set it. */
+ if ((remaining_bytes == 0) || (sample_factor))
+ {
+ rtp_header_ptr -> nx_rtp_header_field1 |= (UCHAR)marker;
+ }
+
+ /* Fill the sequence number from the session context, convert it from host byte order to network byte order. Increase recorded sequence number by 1. */
+ rtp_header_ptr -> nx_rtp_header_sequence_number = session -> nx_rtp_session_sequence_number;
+ NX_CHANGE_USHORT_ENDIAN(rtp_header_ptr -> nx_rtp_header_sequence_number);
+ session -> nx_rtp_session_sequence_number++;
+
+ /* Fill the timestamp passed as an argument from the user, convert it from host byte order to network byte order. */
+ rtp_header_ptr -> nx_rtp_header_timestamp = timestamp;
+ NX_CHANGE_ULONG_ENDIAN(rtp_header_ptr -> nx_rtp_header_timestamp);
+
+ /* Fill the ssrc from the session context, convert it from host byte order to network byte order. */
+ rtp_header_ptr -> nx_rtp_header_ssrc = session -> nx_rtp_session_ssrc;
+ NX_CHANGE_ULONG_ENDIAN(rtp_header_ptr -> nx_rtp_header_ssrc);
+
+ /* Store timestamps for rtcp send report. */
+ session -> nx_rtp_session_rtp_timestamp = timestamp;
+ session -> nx_rtp_session_ntp_timestamp_msw = ntp_msw;
+ session -> nx_rtp_session_ntp_timestamp_lsw = ntp_lsw;
+
+ _nx_rtcp_packet_send(session);
+
+ /* Send out rtp packet */
+ status = nxd_udp_socket_source_send(&(session -> nx_rtp_sender -> nx_rtp_sender_rtp_socket), send_packet,
+ &(session -> nx_rtp_session_peer_ip_address), session -> nx_rtp_session_peer_rtp_port,
+ session -> nx_rtp_session_interface_index);
+ if (status)
+ {
+ if (fragmentation)
+ {
+
+ /* Release the send packet when fragmentation applied. */
+ nx_packet_release(send_packet);
+ }
+ else
+ {
+
+ /* Reset the user packet prepend pointer and the total packet length. */
+ packet_ptr -> nx_packet_prepend_ptr += NX_RTP_HEADER_LENGTH;
+ packet_ptr -> nx_packet_length -= NX_RTP_HEADER_LENGTH;
+ }
+
+ /* Return error status and let the user to determine when to release the packet. */
+ return(status);
+ }
+
+ /* Update sender report statistic. */
+ session -> nx_rtp_session_packet_count++;
+ session -> nx_rtp_session_octet_count += payload_data_length;
+
+ /* Update timestamp when sample-based mode enabled and there are more data bytes to transmit. */
+ if (sample_factor && remaining_bytes)
+ {
+ timestamp += payload_data_length / sample_factor;
+ }
+ }
+
+ if (fragmentation)
+ {
+
+ /* Release the user passed packet when fragmentation applied. */
+ nx_packet_release(packet_ptr);
+ }
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtp_sender_session_sequence_number_get PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks errors in the RTP sender session sequence */
+/* number get function call. */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* sequence_number Pointer to the sequence number */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* NX_PTR_ERROR Invalid pointer input */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_session_sequence_number_get */
+/* Get the sequence number value */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtp_sender_session_sequence_number_get(NX_RTP_SESSION *session, UINT *sequence_number)
+{
+
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((session == NX_NULL) || (session -> nx_rtp_session_id != NX_RTP_SESSION_ID) || (sequence_number == NX_NULL))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual RTP sender session sequence number get service. */
+ status = _nx_rtp_sender_session_sequence_number_get(session, sequence_number);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtp_sender_session_sequence_number_get PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function provides the current sequence number value. */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* sequence_number Pointer to the sequence number */
+/* */
+/* OUTPUT */
+/* */
+/* NX_SUCCESS Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtp_sender_session_sequence_number_get(NX_RTP_SESSION *session, UINT *sequence_number)
+{
+
+ /* Assign return value with the current sequence number of the session. */
+ *sequence_number = session -> nx_rtp_session_sequence_number;
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtp_sender_session_sample_factor_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks errors in the RTP sender session sampling */
+/* factor set function call. */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* factor The sampling factor */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* NX_PTR_ERROR Invalid pointer input */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_session_sample_factor_set */
+/* Set the sampling factor value */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtp_sender_session_sample_factor_set(NX_RTP_SESSION *session, UINT factor)
+{
+
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((session == NX_NULL) || (session -> nx_rtp_session_id != NX_RTP_SESSION_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual RTP sender session sampling factor set service. */
+ status = _nx_rtp_sender_session_sample_factor_set(session, factor);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtp_sender_session_sample_factor_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sets the sample factor value for sample-based payload */
+/* in rtp. The sample factor determines the timestamp increasing rate */
+/* in the function _nx_rtp_sender_session_packet_send when the */
+/* fragmentation feature triggered in sample-based mode since timestamp*/
+/* shall be increased in a pace for each fragmentation packet. */
+/* */
+/* The default sample factor value 0, representing frame-based mode. */
+/* User can use this function to set a non-zero sample factor, with */
+/* automatically triggering sample-based mode. */
+/* Examples about how the sample factor is computed for audio: */
+/* 1) sample bits: 8, channel number: 1, factor = 1 * (8/8) = 1 */
+/* 2) sample bits: 16, channel number: 1, factor = 1 * (16/8) = 2 */
+/* 3) sample bits: 16, channel number: 2, factor = 2 * (16/8) = 4 */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* factor The sampling factor */
+/* */
+/* OUTPUT */
+/* */
+/* NX_SUCCESS Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtp_sender_session_sample_factor_set(NX_RTP_SESSION *session, UINT factor)
+{
+
+ /* Store the factor value into the session. */
+ session -> nx_rtp_session_sample_factor = factor;
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtp_sender_session_ssrc_get PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks errors in the RTP sender session ssrc get */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* ssrc Pointer to ssrc */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* NX_PTR_ERROR Invalid pointer input */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_session_ssrc_get Get ssrc value */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtp_sender_session_ssrc_get(NX_RTP_SESSION *session, ULONG *ssrc)
+{
+
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((session == NX_NULL) || (session -> nx_rtp_session_id != NX_RTP_SESSION_ID) || (ssrc == NX_NULL))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual RTP sender session ssrc get service. */
+ status = _nx_rtp_sender_session_ssrc_get(session, ssrc);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtp_sender_session_ssrc_get PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function provides the current ssrc value. */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* ssrc Pointer to ssrc */
+/* */
+/* OUTPUT */
+/* */
+/* NX_SUCCESS Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtp_sender_session_ssrc_get(NX_RTP_SESSION *session, ULONG *ssrc)
+{
+
+ /* Assign return value with the current ssrc of the session */
+ *ssrc = session -> nx_rtp_session_ssrc;
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtp_sender_cleanup PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function cleans up resources created in rtp sender. */
+/* */
+/* INPUT */
+/* */
+/* rtp_sender Pointer to RTP sender instance */
+/* */
+/* OUTPUT */
+/* */
+/* NX_SUCCESS Completion status */
+/* */
+/* CALLS */
+/* */
+/* nx_udp_socket_unbind Unbind RTP/RTCP sockets */
+/* nx_udp_socket_delete Delete RTP/RTCP sockets */
+/* tx_mutex_delete Delete RTP sender mutex */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtp_sender_create Create RTP sender */
+/* _nx_rtp_sender_delete Delete RTP sender */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtp_sender_cleanup(NX_RTP_SENDER *rtp_sender)
+{
+
+ /* Unbind and delete created rtp and rtcp sockets */
+ nx_udp_socket_unbind(&(rtp_sender -> nx_rtp_sender_rtp_socket));
+ nx_udp_socket_delete(&(rtp_sender -> nx_rtp_sender_rtp_socket));
+ nx_udp_socket_unbind(&(rtp_sender -> nx_rtp_sender_rtcp_socket));
+ nx_udp_socket_delete(&(rtp_sender -> nx_rtp_sender_rtcp_socket));
+
+ /* Delete generated mutex */
+ tx_mutex_delete(&(rtp_sender -> nx_rtp_sender_protection));
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtp_sender_session_find PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Ting Zhu, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function finds a RTP session through the specified ssrc. */
+/* */
+/* INPUT */
+/* */
+/* rtp_sender Pointer to RTP sender */
+/* ssrc The specified session ssrc */
+/* session Pointer to RTP session */
+/* destination */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtcp_packet_rr_process Handle RTCP RR packet */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtp_sender_session_find(NX_RTP_SENDER *rtp_sender, UINT ssrc, NX_RTP_SESSION **session)
+{
+
+NX_RTP_SESSION *start = rtp_sender -> nx_rtp_sender_session_created_ptr;
+
+
+ while (start)
+ {
+ if (start -> nx_rtp_session_ssrc == ssrc)
+ {
+ *session = start;
+ return(NX_SUCCESS);
+ }
+ start = start -> nx_rtp_session_next;
+ }
+
+ return(NX_NOT_FOUND);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtp_sender_session_link PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Ting Zhu, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function links a RTP session to the RTP sender control block. */
+/* */
+/* INPUT */
+/* */
+/* rtp_sender Pointer to RTP sender */
+/* session Pointer to RTP session */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtp_sender_session_create Create RTP session */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+VOID _nx_rtp_sender_session_link(NX_RTP_SENDER *rtp_sender, NX_RTP_SESSION *session)
+{
+
+NX_RTP_SESSION *tail;
+
+
+ if (rtp_sender -> nx_rtp_sender_session_created_ptr)
+ {
+
+ /* Search the tail ptr. */
+ tail = rtp_sender -> nx_rtp_sender_session_created_ptr;
+
+ while (tail -> nx_rtp_session_next)
+ {
+ tail = tail -> nx_rtp_session_next;
+ }
+
+ /* Put the session at the end of the list. */
+ tail -> nx_rtp_session_next = session;
+ }
+ else
+ {
+
+ /* The created session list is empty, simply add the session. */
+ rtp_sender -> nx_rtp_sender_session_created_ptr = session;
+ }
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtp_sender_session_unlink PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Ting Zhu, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function unlinks a RTP session from the RTP sender control */
+/* block. */
+/* */
+/* INPUT */
+/* */
+/* rtp_sender Pointer to RTP sender */
+/* session Pointer to RTP session */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtp_sender_session_delete Delete RTP session */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtp_sender_session_unlink(NX_RTP_SENDER *rtp_sender, NX_RTP_SESSION *session)
+{
+
+NX_RTP_SESSION *current;
+NX_RTP_SESSION *pre;
+
+
+ /* Find the session and unlink it from the list. */
+ if (rtp_sender -> nx_rtp_sender_session_created_ptr == session)
+ {
+ rtp_sender -> nx_rtp_sender_session_created_ptr = session -> nx_rtp_session_next;
+ }
+ else
+ {
+ pre = rtp_sender -> nx_rtp_sender_session_created_ptr;
+ current = pre -> nx_rtp_session_next;
+
+ while (current)
+ {
+ if (current == session)
+ {
+ pre -> nx_rtp_session_next = current -> nx_rtp_session_next;
+ break;
+ }
+
+ pre = current;
+ current = pre -> nx_rtp_session_next;
+ }
+ }
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtcp_packet_process PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Ting Zhu, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function handles reception of RTCP packet. */
+/* */
+/* INPUT */
+/* */
+/* rtp_sender Pointer to RTP sender */
+/* packet_ptr Pointer to packet */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtcp_packet_rr_process Handle RR packet */
+/* _nx_rtcp_packet_sdes_process Handle SDES packet */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtcp_packet_receive_notify RTCP packet receive notify */
+/* service */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtcp_packet_process(NX_RTP_SENDER *rtp_sender, NX_PACKET *packet_ptr)
+{
+
+UINT status = NX_SUCCESS;
+NX_RTCP_HEADER *header;
+NX_RTCP_HEADER *next;
+UCHAR *end;
+
+
+ if (rtp_sender -> nx_rtp_sender_id != NX_RTP_SENDER_ID)
+ {
+
+ /* Not valid RTP sender. */
+ return(NX_PTR_ERROR);
+ }
+
+#ifndef NX_DISABLE_PACKET_CHAIN
+ if (packet_ptr -> nx_packet_next)
+ {
+
+ /* Chained packet, not supported. */
+ return(NX_NOT_SUPPORTED);
+ }
+#endif /* NX_DISABLE_PACKET_CHAIN */
+
+ header = (NX_RTCP_HEADER *)(packet_ptr -> nx_packet_prepend_ptr);
+ end = packet_ptr -> nx_packet_append_ptr;
+
+ if ((UCHAR *)header + sizeof(NX_RTCP_HEADER) > end)
+ {
+ return(NX_INVALID_PACKET);
+ }
+
+ /* Check the first RTCP packet header:
+ 1) The Padding bit should be zero for the first packet of a compound RTCP packet.
+ 2) The payload type field of the first RTCP packet in a compound packet must be equal to SR or RR.
+ */
+ if (((header -> nx_rtcp_byte0 & NX_RTCP_PAD_MASK) != NX_RTCP_PAD_VALUE) ||
+ ((header -> nx_rtcp_packet_type & NX_RTCP_TYPE_MASK) != NX_RTCP_TYPE_SR))
+ {
+
+ /* Wrong packet format. */
+ return(NX_INVALID_PACKET);
+ }
+
+ do
+ {
+ NX_CHANGE_USHORT_ENDIAN(header -> nx_rtcp_length);
+
+ next = (NX_RTCP_HEADER *)((ULONG *)header + header -> nx_rtcp_length + 1);
+
+ /* RTP version field must equal 2. */
+ if (((header -> nx_rtcp_byte0 & NX_RTCP_VERSION_MASK) != NX_RTCP_VERSION_VALUE) || ((UCHAR *)next > end))
+ {
+ status = NX_INVALID_PACKET;
+ break;
+ }
+
+ switch (header -> nx_rtcp_packet_type)
+ {
+ case NX_RTCP_TYPE_RR:
+
+ /* Process rr packet. */
+ status = _nx_rtcp_packet_rr_process(rtp_sender, header);
+ break;
+
+ case NX_RTCP_TYPE_SDES:
+
+ /* Process sdes packet. */
+ status = _nx_rtcp_packet_sdes_process(rtp_sender, header);
+ break;
+ }
+
+ if (status != NX_SUCCESS)
+ {
+ break;
+ }
+
+ header = next;
+ } while ((UCHAR *)header + sizeof(NX_RTCP_HEADER) <= end);
+
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtcp_packet_rr_process PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Ting Zhu, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function handles RTCP RR packet. */
+/* */
+/* INPUT */
+/* */
+/* rtp_sender Pointer to RTP sender */
+/* header Pointer to RTCP packet header */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_session_find Find rtp session */
+/* tx_mutex_get Get mutex */
+/* tx_mutex_put Release mutex */
+/* nx_rtp_sender_rtcp_receiver_report_cb Application's RTCP RR packet */
+/* notify callback */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtcp_packet_process Handle RTCP packet */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtcp_packet_rr_process(NX_RTP_SENDER *rtp_sender, NX_RTCP_HEADER *header)
+{
+
+UINT status;
+NX_RTCP_RR *rtcp_rr;
+NX_RTCP_RECEIVER_REPORT report;
+UINT (*rr_callback)(struct NX_RTP_SESSION_STRUCT *, NX_RTCP_RECEIVER_REPORT *);
+NX_RTP_SESSION *session;
+
+
+ rr_callback = rtp_sender -> nx_rtp_sender_rtcp_receiver_report_cb;
+ if (rr_callback == NX_NULL)
+ {
+
+ /* No RTCP receiver report callback set. */
+ return(NX_SUCCESS);
+ }
+
+ if ((header -> nx_rtcp_byte0 & NX_RTCP_COUNT_MASK) &&
+ ((sizeof(NX_RTCP_RR) >> 2) <= (UINT)((header -> nx_rtcp_length + 1))))
+ {
+ rtcp_rr = (NX_RTCP_RR *)header;
+
+ /* Take care of endian-ness. */
+ NX_CHANGE_ULONG_ENDIAN(rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_ssrc);
+
+ /* Obtain the mutex. */
+ status = tx_mutex_get(&(rtp_sender -> nx_rtp_sender_protection), TX_NO_WAIT);
+
+ if (status != NX_SUCCESS)
+ {
+ return(status);
+ }
+
+ if (_nx_rtp_sender_session_find(rtp_sender, rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_ssrc, &session) == NX_SUCCESS)
+ {
+ NX_CHANGE_ULONG_ENDIAN(rtcp_rr -> nx_rtcp_rr_ssrc);
+ NX_CHANGE_ULONG_ENDIAN(rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_loss);
+ NX_CHANGE_ULONG_ENDIAN(rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_extended_max);
+ NX_CHANGE_ULONG_ENDIAN(rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_jitter);
+ NX_CHANGE_ULONG_ENDIAN(rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_last_sr);
+ NX_CHANGE_ULONG_ENDIAN(rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_delay);
+
+ /* Copy the values out for the callback function. */
+ report.receiver_ssrc = rtcp_rr -> nx_rtcp_rr_ssrc;
+ report.fraction_loss = rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_loss >> 24;
+ report.packet_loss = ((((INT)rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_loss) << 8) >> 8);
+ report.extended_max = rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_extended_max;
+ report.jitter = rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_jitter;
+ report.last_sr = rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_last_sr;
+ report.delay = rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_delay;
+
+ /* Invoke the callback function to process data inside the RTCP RR packet. */
+ rr_callback(session, &report);
+ }
+
+ /* Release the mutex. */
+ tx_mutex_put(&(rtp_sender -> nx_rtp_sender_protection));
+ }
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtcp_packet_sdes_process PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Ting Zhu, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function handles RTCP SDES packet. */
+/* */
+/* INPUT */
+/* */
+/* rtp_sender Pointer to RTP sender */
+/* header Pointer to RTCP packet header */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* nx_rtp_sender_rtcp_sdes_cb Application's RTCP SDES */
+/* packet notify callback */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtcp_packet_process Handle RTCP packet */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtcp_packet_sdes_process(NX_RTP_SENDER *rtp_sender, NX_RTCP_HEADER *header)
+{
+
+UINT (*sdes_callback)(NX_RTCP_SDES_INFO *);
+NX_RTCP_SDES_CHUNK *chunk;
+NX_RTCP_SDES_ITEM *item;
+UCHAR *end;
+NX_RTCP_SDES_INFO sdes_info;
+INT count;
+
+
+ sdes_callback = rtp_sender -> nx_rtp_sender_rtcp_sdes_cb;
+ if (sdes_callback == NX_NULL)
+ {
+
+ /* No RTCP receiver report callback set. */
+ return(NX_SUCCESS);
+ }
+
+ chunk = (NX_RTCP_SDES_CHUNK *)((UCHAR *)header + sizeof(NX_RTCP_HEADER));
+ count = (header -> nx_rtcp_byte0 & NX_RTCP_COUNT_MASK);
+
+ end = (UCHAR *)((ULONG *)header + header -> nx_rtcp_length + 1);
+
+ while (((UCHAR *)chunk + sizeof(NX_RTCP_SDES_CHUNK) <= end) && (count-- > 0))
+ {
+ item = &chunk -> nx_rtcp_sdes_item[0];
+
+ NX_CHANGE_ULONG_ENDIAN(chunk -> nx_rtcp_sdes_ssrc);
+
+ while (((UCHAR *)item + sizeof(NX_RTCP_SDES_ITEM) <= end) && item -> nx_rtcp_sdes_type)
+ {
+
+ if (item -> nx_rtcp_sdes_data + item -> nx_rtcp_sdes_length > end)
+ {
+ return(NX_INVALID_PACKET);
+ }
+
+ if (item -> nx_rtcp_sdes_type == NX_RTCP_SDES_TYPE_CNAME)
+ {
+
+ /* Copy the values out for the callback function. */
+ sdes_info.ssrc = chunk -> nx_rtcp_sdes_ssrc;
+ sdes_info.cname_length = item -> nx_rtcp_sdes_length;
+
+ /* CNAME string is UTF-8 encoded and is not null terminated. */
+ sdes_info.cname = &item -> nx_rtcp_sdes_data[0];
+
+ /* Invoke the callback function to process data inside the RTCP SDES packet. */
+ sdes_callback(&sdes_info);
+
+ break;
+ }
+
+ /* Advance to the next item. */
+ item = (NX_RTCP_SDES_ITEM *)((UCHAR *)item + 2 + item -> nx_rtcp_sdes_length);
+ }
+
+ /* RFC 3550, chapter 6.5.
+ The list of items in each chunk MUST be terminated by one or more null octets,
+ the first of which is interpreted as an item type of zero to denote the end of the list. */
+ chunk = (NX_RTCP_SDES_CHUNK *)((UCHAR *)chunk + (((UCHAR *)item - (UCHAR *)chunk) >> 2) + 1);
+ }
+
+ return(NX_SUCCESS);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtcp_sr_data_append PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Ting Zhu, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function generates an RTCP SR packet and copies it to the end */
+/* of the specifed RTCP packet. */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* packet_ptr Pointer to RTCP packet */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* nx_packet_data_append Copy the specified data to */
+/* the end of specified packet */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtcp_packet_send Send RTCP packet */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtcp_sr_data_append(NX_RTP_SESSION *session, NX_PACKET *packet_ptr)
+{
+
+NX_RTCP_SR rtcp_sr;
+
+
+ /* Pack SR packet. */
+ rtcp_sr.nx_rtcp_sr_header.nx_rtcp_byte0 = (NX_RTP_VERSION << 6); /* Version 2 */
+ rtcp_sr.nx_rtcp_sr_header.nx_rtcp_packet_type = NX_RTCP_TYPE_SR;
+ rtcp_sr.nx_rtcp_sr_header.nx_rtcp_length = sizeof(NX_RTCP_SR) / sizeof(ULONG) - 1; /* RTCP SR size. */
+ rtcp_sr.nx_rtcp_sr_ssrc = session -> nx_rtp_session_ssrc;
+ rtcp_sr.nx_rtcp_sr_ntp_timestamp_msw = session -> nx_rtp_session_ntp_timestamp_msw;
+ rtcp_sr.nx_rtcp_sr_ntp_timestamp_lsw = session -> nx_rtp_session_ntp_timestamp_lsw;
+ rtcp_sr.nx_rtcp_sr_rtp_timestamp = session -> nx_rtp_session_rtp_timestamp;
+ rtcp_sr.nx_rtcp_sr_rtp_packet_count = session -> nx_rtp_session_packet_count;
+ rtcp_sr.nx_rtcp_sr_rtp_octet_count = session -> nx_rtp_session_octet_count;
+
+ /* Take care of endian-ness. */
+ NX_CHANGE_USHORT_ENDIAN(rtcp_sr.nx_rtcp_sr_header.nx_rtcp_length);
+ NX_CHANGE_ULONG_ENDIAN(rtcp_sr.nx_rtcp_sr_ssrc);
+ NX_CHANGE_ULONG_ENDIAN(rtcp_sr.nx_rtcp_sr_ntp_timestamp_msw);
+ NX_CHANGE_ULONG_ENDIAN(rtcp_sr.nx_rtcp_sr_ntp_timestamp_lsw);
+ NX_CHANGE_ULONG_ENDIAN(rtcp_sr.nx_rtcp_sr_rtp_timestamp);
+ NX_CHANGE_ULONG_ENDIAN(rtcp_sr.nx_rtcp_sr_rtp_packet_count);
+ NX_CHANGE_ULONG_ENDIAN(rtcp_sr.nx_rtcp_sr_rtp_octet_count);
+
+ /* Append SR packet. */
+ nx_packet_data_append(packet_ptr, &rtcp_sr, sizeof(rtcp_sr), session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_RTP_SENDER_PACKET_TIMEOUT);
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtcp_sdes_data_append PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Ting Zhu, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function generates an RTCP SDES packet and copies it to the */
+/* end of the specifed RTCP packet. */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* packet_ptr Pointer to RTCP packet */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* nx_packet_data_append Copy the specified data to */
+/* the end of specified packet */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtcp_packet_send Send RTCP packet */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtcp_sdes_data_append(NX_RTP_SESSION *session, NX_PACKET *packet_ptr)
+{
+
+UINT status;
+NX_RTCP_HEADER header;
+NX_RTCP_SDES_CHUNK sdes_chunk;
+NX_PACKET_POOL *packet_pool = session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr;
+NX_RTP_SENDER *sender = session -> nx_rtp_sender;
+ULONG pad = 0;
+UCHAR pad_value[] = {0, 0, 0};
+UINT length;
+
+
+/*
+SDES packet format:
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+header |V=2|P| SC | PT=SDES=202 | length |
+ +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+chunk | SSRC/CSRC_1 |
+ 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | SDES items |
+ | ... |
+ +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+chunk | SSRC/CSRC_2 |
+ 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | SDES items |
+ | ... |
+ +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+
+SDES item format for CNAME:
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | CNAME=1 | length | user and domain name ...
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+ /* packet size = rtcp header size + 4 bytes ssrc + 1 byte type + 1 byte length + data length. */
+ length = sizeof(NX_RTCP_HEADER) + 6 + sender -> nx_rtp_sender_cname_length;
+
+ if (length & 0x3)
+ {
+ pad = 4 - (length & 0x3);
+ }
+
+ /* Pack SDES packet header. */
+ header.nx_rtcp_byte0 = (NX_RTP_VERSION << 6) | 1; /* Sender Desc with 1 item */
+ header.nx_rtcp_packet_type = NX_RTCP_TYPE_SDES;
+ header.nx_rtcp_length = (USHORT)(((length + pad) / sizeof(ULONG)) - 1);
+
+ NX_CHANGE_USHORT_ENDIAN(header.nx_rtcp_length);
+
+ /* Append SDES packet header. */
+ status = nx_packet_data_append(packet_ptr, &header, sizeof(header), packet_pool, NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ return(status);
+ }
+
+ /* Pack CNAME item. */
+ sdes_chunk.nx_rtcp_sdes_ssrc = session -> nx_rtp_session_ssrc;
+ sdes_chunk.nx_rtcp_sdes_item[0].nx_rtcp_sdes_type = NX_RTCP_SDES_TYPE_CNAME;
+ sdes_chunk.nx_rtcp_sdes_item[0].nx_rtcp_sdes_length = sender -> nx_rtp_sender_cname_length;
+
+ NX_CHANGE_ULONG_ENDIAN(sdes_chunk.nx_rtcp_sdes_ssrc);
+
+ /* Append 4 bytes ssrc + 1 byte item type + 1 byte data length. */
+ status = nx_packet_data_append(packet_ptr, &sdes_chunk, 6, packet_pool, NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ return(status);
+ }
+
+ /* Append cname string. */
+ status = nx_packet_data_append(packet_ptr, sender -> nx_rtp_sender_cname, sender -> nx_rtp_sender_cname_length, packet_pool, NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ return(status);
+ }
+
+ if (pad)
+ {
+ status = nx_packet_data_append(packet_ptr, pad_value, pad, packet_pool, NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ return(status);
+ }
+ }
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtcp_packet_send PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Ting Zhu, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sends a compound RTCP packet through the UDP layer to */
+/* the supplied IP address and rtcp port. */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* tx_time_get Get current system clock */
+/* nx_packet_allocate Allocate packet */
+/* nx_packet_release Release packet */
+/* nxd_udp_socket_source_send Send a UDP packet */
+/* _nx_rtcp_sr_data_append Append SR packet */
+/* _nx_rtcp_sdes_data_append Append SDES packet */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtp_sender_session_packet_send Send rtp packet */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtcp_packet_send(NX_RTP_SESSION *session)
+{
+
+UINT status = NX_SUCCESS;
+NX_PACKET *packet_ptr;
+UINT current_time = tx_time_get();
+
+
+ if (session -> nx_rtp_session_rtcp_time &&
+ ((current_time - session -> nx_rtp_session_rtcp_time) / TX_TIMER_TICKS_PER_SECOND < NX_RTCP_INTERVAL))
+ {
+ return(NX_SUCCESS);
+ }
+
+ status = nx_packet_allocate(session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, &packet_ptr, NX_UDP_PACKET, NX_RTP_SENDER_PACKET_TIMEOUT);
+
+ if (status != NX_SUCCESS)
+ {
+ return(status);
+ }
+
+ /* Chain rtcp packets into one compound packet. */
+ status = _nx_rtcp_sr_data_append(session, packet_ptr);
+
+ if (status == NX_SUCCESS)
+ {
+ status = _nx_rtcp_sdes_data_append(session, packet_ptr);
+ }
+
+ if (status == NX_SUCCESS)
+ {
+
+ /* Send the packet. */
+ status = nxd_udp_socket_source_send(&session -> nx_rtp_sender -> nx_rtp_sender_rtcp_socket, packet_ptr,
+ &(session -> nx_rtp_session_peer_ip_address), session -> nx_rtp_session_peer_rtcp_port,
+ session -> nx_rtp_session_interface_index);
+ }
+
+ /* Check the status. */
+ if (status == NX_SUCCESS)
+ {
+ session -> nx_rtp_session_rtcp_time = tx_time_get();
+ }
+ else
+ {
+ nx_packet_release(packet_ptr);
+ }
+
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtcp_packet_receive_notify PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Ting Zhu, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function serves as RTCP packet receive notify routine, which */
+/* is called whenever a packet is received on the rtcp port. */
+/* */
+/* INPUT */
+/* */
+/* socket_ptr Pointer to RTCP port */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* nx_udp_socket_receive Check for UDP packet on the */
+/* specified port */
+/* nx_packet_release Release packet */
+/* _nx_rtcp_packet_process Handle rtcp packet */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtp_sender_create Create RTP sender */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+VOID _nx_rtcp_packet_receive_notify(NX_UDP_SOCKET *socket_ptr)
+{
+
+/* Drain the packet */
+NX_PACKET *packet_ptr;
+NX_RTP_SENDER *rtp_sender;
+
+
+ /* Get packet(s) from the passed socket. */
+ if (nx_udp_socket_receive(socket_ptr, &packet_ptr, NX_NO_WAIT) != NX_SUCCESS)
+ {
+ return;
+ }
+
+ /* Check and determine whether to process received rtcp packet. */
+ rtp_sender = (NX_RTP_SENDER *)socket_ptr -> nx_udp_socket_reserved_ptr;
+ if ((rtp_sender) &&
+ (rtp_sender -> nx_rtp_sender_rtcp_receiver_report_cb || rtp_sender -> nx_rtp_sender_rtcp_sdes_cb))
+ {
+ _nx_rtcp_packet_process(rtp_sender, packet_ptr);
+ }
+
+ /* Release the packet and return. */
+ nx_packet_release(packet_ptr);
+ return;
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtp_sender_session_jpeg_send PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks errors in the RTP sender session jpeg send */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* frame_data Pointer to data buffer to send */
+/* frame_data_size Size of data to send */
+/* timestamp RTP timestamp for current data */
+/* ntp_msw Most significant word of */
+/* network time */
+/* ntp_lsw Least significant word of */
+/* network time */
+/* marker Marker bit for significant */
+/* event such as frame boundary */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* NX_PTR_ERROR Invalid pointer input */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_session_jpeg_send Send packet data */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtp_sender_session_jpeg_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
+ ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker)
+{
+
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((session == NX_NULL) || (session -> nx_rtp_sender == NX_NULL) || (session -> nx_rtp_session_id != NX_RTP_SESSION_ID) || (frame_data == NX_NULL))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual RTP sender session packet send service. */
+ status = _nx_rtp_sender_session_jpeg_send(session, frame_data, frame_data_size, timestamp, ntp_msw, ntp_lsw, marker);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtp_sender_session_jpeg_send PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function parses and makes the passed data in RTP/JPEG format, */
+/* and then calls RTP session send function to send these data in RTP */
+/* packet. */
+/* The function references RFC 2435 as the standard with below notes: */
+/* 1) A complete jpeg scan file inside frame data buffer is required. */
+/* 2) Use dynamic quantization table mapping. */
+/* 3) The provided jpeg scan file shall be 8-bit sample precision, */
+/* YUV420 or YUV422 type, and encoded with standard huffman tables. */
+/* 4) Restart marker is not supported. */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* frame_data Pointer to data buffer to send */
+/* frame_data_size Size of data to send */
+/* timestamp RTP timestamp for current data */
+/* ntp_msw Most significant word of */
+/* network time */
+/* ntp_lsw Least significant word of */
+/* network time */
+/* marker Marker bit for significant */
+/* event such as frame boundary */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_session_packet_allocate */
+/* Allocate a packet for the user */
+/* nx_packet_data_append Copy the specified data to */
+/* the end of specified packet */
+/* nx_packet_data_release Release the packet */
+/* _nx_rtp_sender_session_packet_send Send RTP packet */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtp_sender_session_jpeg_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
+ ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker)
+{
+
+UINT status;
+UCHAR *data_ptr;
+UCHAR *data_end_ptr;
+UCHAR jpeg_header[8];
+UCHAR quantization_header[4];
+USHORT section_length;
+UCHAR type = 255; /* type field for main jpeg header. */
+UCHAR marker_code; /* jpeg marker code to indicate different sections. */
+USHORT width = 0, height = 0; /* resolution information for main jpeg header. */
+ULONG q_table_num = 0;
+ULONG q_overall_table_num = 0;
+UCHAR *q_table_ptr[NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_MAX_NUM];
+ULONG data_payload_length = 0;
+ULONG transferred_data_size = 0;
+ULONG single_frame_length;
+ULONG copy_length;
+UINT temp_rtp_marker = NX_FALSE;
+NX_PACKET *send_packet = NX_NULL;
+
+
+ /* In current design, the marker bit shall be always 1 (i.e. a complete jpeg scan file required to be passed). */
+ if (marker != NX_TRUE)
+ {
+ return(NX_NOT_SUPPORTED);
+ }
+
+ /* Initialize local variables for searching. */
+ data_ptr = frame_data;
+ data_end_ptr = frame_data + frame_data_size;
+
+ /* Check jpeg constant file header. */
+ if ((frame_data_size < 2) || ((data_ptr[0] != 0xFF) || (data_ptr[1] != 0xD8)))
+ {
+ return(NX_NOT_SUCCESSFUL);
+ }
+
+ /* Skip the 2 bytes jpeg file header. */
+ data_ptr += 2;
+
+ do
+ {
+
+ /* Check there are enough bytes remaining in the data buffer for 2 bytes section marker and 2 bytes section length. */
+ if ((data_ptr + 4) > data_end_ptr)
+ {
+ return(NX_SIZE_ERROR);
+ }
+
+ /* Check the first byte for section marker. */
+ if (data_ptr[0] != 0xFF)
+ {
+ return(NX_NOT_SUCCESSFUL);
+ }
+
+ /* Update the marker code. */
+ marker_code = data_ptr[1];
+
+ /* Update and skip the whole 2 bytes section marker. */
+ data_ptr += 2;
+
+ /* Compute data length in this section. */
+ section_length = (USHORT)((data_ptr[0] << 8) | data_ptr[1]);
+
+ /* Check there are enough bytes remaining in the data buffer. */
+ if ((data_ptr + section_length) > data_end_ptr)
+ {
+ return(NX_SIZE_ERROR);
+ }
+
+ /* Now it is time to parse the marker code and its corresponding section. */
+ switch (marker_code)
+ {
+
+ /* SOF0: image baseline information. */
+ case 0xC0:
+ {
+
+ /* For a standard RTP/JPEG image baseline information, this section length shall be
+ at least 17, in order to contain enough baseline information for the image. */
+ if (section_length < 17)
+ {
+ return(NX_SIZE_ERROR);
+ }
+
+ /* Skip 2 bytes section length. */
+ data_ptr += 2;
+
+ /* 8-bit sample precision is required. */
+ if (data_ptr[0] != 8)
+ {
+ return(NX_NOT_SUPPORTED);
+ }
+
+ /* Check the number of image components which shall be 3 for YUV. */
+ if (data_ptr[5] != 3)
+ {
+ return(NX_NOT_SUPPORTED);
+ }
+
+ /* Check the quantization table number for all YUV dimensions. */
+ if ((data_ptr[8] != 0x00) || (data_ptr[11] != 0x01) || (data_ptr[14] != 0x01))
+ {
+ return(NX_NOT_SUPPORTED);
+ }
+
+ /* Check the horizontal and vertical sampling factor for both U dimension and V dimension. */
+ if ((data_ptr[10] != 0x11) || (data_ptr[13] != 0x11))
+ {
+ return(NX_NOT_SUPPORTED);
+ }
+
+ /* Determine the RTP/JPEG type in jpeg main header through different vertical sampling factor of Y dimension. */
+ if (data_ptr[7] == 0x21)
+ {
+ type = 0; /* YUV420. */
+ }
+ else if (data_ptr[7] == 0x22)
+ {
+ type = 1; /* YUV422. */
+ }
+ else
+ {
+ return(NX_NOT_SUPPORTED);
+ }
+
+ /* Compute width and height. */
+ height = (USHORT)((data_ptr[1] << 8) | data_ptr[2]);
+ width = (USHORT)((data_ptr[3] << 8) | data_ptr[4]);
+
+ /* Skip the current section. */
+ data_ptr += 15; /* 15 bytes section data. */
+ break;
+ }
+
+ /* DQT: define quantization table. */
+ case 0xDB:
+ {
+
+ /* Skip 2 bytes section length. */
+ data_ptr += 2;
+
+ /* Compute the number of quantization tables (each table shall contain 65 bytes). */
+ q_table_num = section_length / (NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_LENGTH + 1);
+
+ /* Check current table number. */
+ if ((q_table_num == 0) || ((q_table_num + q_overall_table_num) > NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_MAX_NUM))
+ {
+ return(NX_NOT_SUCCESSFUL);
+ }
+
+ for (UINT i = q_overall_table_num; i < (q_overall_table_num + q_table_num); i++)
+ {
+
+ /* Skip the first no meaning byte. */
+ data_ptr++;
+
+ /* Record the current table position. */
+ q_table_ptr[i] = data_ptr;
+
+ /* Move to the next table position. */
+ data_ptr += NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_LENGTH;
+ }
+
+ /* Update overall number of tables. This variable is introduced because there may be more than 1 DQT come. */
+ q_overall_table_num += q_table_num;
+ break;
+ }
+
+ /* SOS: the start of the scan. */
+ case 0xDA:
+ {
+
+ /* Skip the scan header. */
+ data_ptr += section_length;
+
+ /* Move the end pointer to the last 2 byte to make the check easier */
+ data_end_ptr -= 2;
+
+ /* Search and try to find EOI in current packet. */
+ while (data_ptr < data_end_ptr)
+ {
+ if ((data_end_ptr[0] == 0xFF) && (data_end_ptr[1] == 0xD9))
+ {
+ break;
+ }
+ else
+ {
+ data_end_ptr--;
+ }
+ }
+
+ /* Check if EOI has been found. */
+ if (data_ptr < data_end_ptr)
+ {
+ data_payload_length = (ULONG)(data_end_ptr - data_ptr);
+ }
+ else /* data_ptr == data_end_ptr */
+ {
+
+ /* If EOI has not been found, consider all remaining data are scan data. */
+ data_payload_length = frame_data_size - (ULONG)(data_ptr - frame_data);
+ }
+
+ /* When SOS found, the while loop will also be jumped out. */
+ break;
+ }
+
+ /* EOI */
+ case 0xD9:
+ {
+
+ /* SOS shall be found before EOI. */
+ return(NX_NOT_SUCCESSFUL);
+ }
+
+ /* Unsupported SOFs or other markers. */
+ case 0xC1: /* Extended sequential DCT */
+ case 0xC2: /* Progressive DCT */
+ case 0xC3: /* Lossless (sequential) */
+ case 0xC5: /* Differential sequential DCT */
+ case 0xC6: /* Differential progressive DCT */
+ case 0xC7: /* Differential lossless (sequential) */
+ case 0xC8: /* Reserved for JPEG extensions */
+ case 0xC9: /* Extended sequential DCT */
+ case 0xCA: /* Progressive DCT */
+ case 0xCB: /* Lossless (sequential) */
+ case 0xCC: /* Define arithmetic coding conditionings */
+ case 0xCD: /* Differential sequential DCT */
+ case 0xCE: /* Differential progressive DCT */
+ case 0xCF: /* Differential lossless (sequential) */
+ case 0xDD: /* DRI */
+ {
+ return(NX_NOT_SUPPORTED);
+ }
+
+ /* Possible sections in default:
+ 1) APP0 ~ APPn: define exchange format and image identifications.
+ 2) Huffman table: it is assumed that standard Huffman table applied. */
+ default:
+ {
+
+ /* Marker code 0x01 is not supported. Marker codes inside 0x02 ~ 0xBF are reserved. */
+ if (marker_code < 0xC0)
+ {
+ return(NX_NOT_SUPPORTED);
+ }
+
+ /* Move the data_ptr and offset to skip the whole section. */
+ data_ptr += section_length;
+ break;
+ }
+ }
+
+ } while (marker_code != 0xDA); /* Jump out when find SOS. */
+
+ /* Check the type has been confirmed, and quantization. */
+ if (((type != 0) && (type != 1)) || (q_overall_table_num == 0))
+ {
+ return(NX_NOT_SUCCESSFUL);
+ }
+
+ /* Check there is any scan data to send. */
+ if (data_payload_length == 0)
+ {
+ return(NX_SIZE_ERROR);
+ }
+
+ /* Allocate a packet for the first data packet to transmit. */
+ status = _nx_rtp_sender_session_packet_allocate(session, &send_packet, NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ return(NX_NOT_SUCCESSFUL);
+ }
+
+ /* Initialize main JPEG header, and append it into the send packet. */
+ jpeg_header[0] = 0; /* Always 0 since no interpretation is specified. */
+ jpeg_header[1] = 0; /* High byte of 24 bytes size offset. */
+ jpeg_header[2] = 0; /* Middle byte 24 bytes size offset. */
+ jpeg_header[3] = 0; /* Low byte of 24 bytes size offset. */
+ jpeg_header[4] = type;
+ jpeg_header[5] = 255; /* Q values 255 indicates the quantization table header appears after the main JPEG header,
+ and the quantization table is allowed to be changeable among different frames. */
+ jpeg_header[6] = (UCHAR)(width >> 3); /* Maximum width: 2040 pixels. */
+ jpeg_header[7] = (UCHAR)(height >> 3); /* Maximum height: 2040 pixels. */
+
+ status = nx_packet_data_append(send_packet, (void *)jpeg_header, sizeof(jpeg_header),
+ session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ nx_packet_release(send_packet);
+ return(NX_NOT_SUCCESSFUL);
+ }
+
+ /* Update quantization table header, and append it into the send packet. */
+ quantization_header[0] = 0; /* MBZ. */
+ quantization_header[1] = 0; /* Precision: 8 bits. */
+ quantization_header[2] = (UCHAR)((NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_LENGTH * q_overall_table_num) >> 8); /* High byte if tables length. */
+ quantization_header[3] = (UCHAR)(NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_LENGTH * q_overall_table_num); /* Low byte if tables length. */
+
+ status = nx_packet_data_append(send_packet, (void *)quantization_header, sizeof(quantization_header),
+ session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ nx_packet_release(send_packet);
+ return(NX_NOT_SUCCESSFUL);
+ }
+
+ /* Copy quantization table(s) into the packet. It is assume that these table(s) are not in different packets of a chain packet. */
+ for (UINT i = 0; i < q_overall_table_num; i++)
+ {
+ status = nx_packet_data_append(send_packet, (void *)(q_table_ptr[i]), NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_LENGTH,
+ session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ nx_packet_release(send_packet);
+ return(NX_NOT_SUCCESSFUL);
+ }
+ }
+
+ /* Compute the current single frame length and check if mtu size match the requirement for putting all jpeg header info into one packet. */
+ single_frame_length = sizeof(jpeg_header) + sizeof(quantization_header) + NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_LENGTH * q_overall_table_num;
+ if (single_frame_length > session -> nx_rtp_session_max_packet_size)
+ {
+ nx_packet_release(send_packet);
+ return(NX_NOT_SUPPORTED);
+ }
+
+ /* Begin data frame(s) transmit. */
+ while (1)
+ {
+
+ /* Check and execute packet fragmentation. */
+ copy_length = session -> nx_rtp_session_max_packet_size - single_frame_length;
+ if (data_payload_length <= copy_length)
+ {
+ copy_length = data_payload_length;
+ temp_rtp_marker = NX_TRUE;
+ }
+
+ /* Copy payload data into the packet. */
+ status = nx_packet_data_append(send_packet, (void *)data_ptr, copy_length,
+ session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ nx_packet_release(send_packet);
+ return(status);
+ }
+
+ /* Send the data packet. */
+ status = _nx_rtp_sender_session_packet_send(session, send_packet, timestamp, ntp_msw, ntp_lsw, temp_rtp_marker);
+ if (status)
+ {
+ nx_packet_release(send_packet);
+ return(status);
+ }
+
+ /* Decrease transmitted data payload length and check whether all data finish transmitting. */
+ data_payload_length -= copy_length;
+ if (data_payload_length == 0)
+ {
+
+ /* Jump out the while loop when all data finish transmitting. */
+ break;
+ }
+
+ /* Move data pointer to the begin of remaining data. */
+ data_ptr += copy_length;
+
+ /* Update 24-bit transferred data offset with bytes order. */
+ transferred_data_size += copy_length;
+ jpeg_header[1] = (UCHAR)(transferred_data_size >> 16);
+ jpeg_header[2] = (UCHAR)(transferred_data_size >> 8);
+ jpeg_header[3] = (UCHAR)(transferred_data_size);
+
+ /* Allocate a packet for next packet. */
+ status = _nx_rtp_sender_session_packet_allocate(session, &send_packet, NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ return(status);
+ }
+
+ /* Copy jpeg header into the packet. */
+ status = nx_packet_data_append(send_packet, (void *)jpeg_header, sizeof(jpeg_header),
+ session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ nx_packet_release(send_packet);
+ return(status);
+ }
+
+ /* Update single frame length. */
+ single_frame_length = sizeof(jpeg_header);
+ }
+
+ /* Return success status. */
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtp_sender_session_h264_send PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks errors in the RTP sender session h264 send */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* frame_data Pointer to data buffer to send */
+/* frame_data_size Size of data to send */
+/* timestamp RTP timestamp for current data */
+/* ntp_msw Most significant word of */
+/* network time */
+/* ntp_lsw Least significant word of */
+/* network time */
+/* marker Marker bit for significant */
+/* event such as frame boundary */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* NX_PTR_ERROR Invalid pointer input */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_session_h264_send Send h264 frame data */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtp_sender_session_h264_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
+ ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker)
+{
+
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((session == NX_NULL) || (session -> nx_rtp_sender == NX_NULL) || (session -> nx_rtp_session_id != NX_RTP_SESSION_ID) || (frame_data == NX_NULL))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual RTP sender session frame send service. */
+ status = _nx_rtp_sender_session_h264_send(session, frame_data, frame_data_size, timestamp, ntp_msw, ntp_lsw, marker);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtp_sender_session_h264_send PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function parses and separates the passed data into h264 frames */
+/* or slices, and processes each frame/slice from VCL format to NAL */
+/* format, and finally calls RTP session send function to send these */
+/* frame/slice(s) in RTP packet. */
+/* The function references RFC 6184 as the standard with below notes: */
+/* 1) A complete h264 data frame shall be inside the frame data buffer.*/
+/* 2) Special frame(s) such as SEI, SPS and PPS can be inside the */
+/* frame data buffer. */
+/* 3) Each H264 frame/slice inside the frame data buffer shall be in */
+/* VCL (video coding layer) format. */
+/* 4) SDP shall indicate that non-interleaved mode is applied (i.e. */
+/* packetization-mode=1), which supports the use of single NAL unit */
+/* packet and FU-A packets. */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* frame_data Pointer to data buffer to send */
+/* frame_data_size Size of data to send */
+/* timestamp RTP timestamp for current data */
+/* ntp_msw Most significant word of */
+/* network time */
+/* ntp_lsw Least significant word of */
+/* network time */
+/* marker Marker bit for significant */
+/* event such as frame boundary */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_session_packet_allocate */
+/* Allocate a packet for the user */
+/* nx_packet_data_append Copy the specified data to */
+/* the end of specified packet */
+/* nx_packet_data_release Release the packet */
+/* _nx_rtp_sender_session_packet_send Send RTP packet */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtp_sender_session_h264_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
+ ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker)
+{
+
+UINT status;
+UINT i;
+ULONG nal_unit_size;
+ULONG max_packet_length;
+ULONG send_packet_length;
+UCHAR *frame_end;
+UCHAR *nal_unit_start;
+UCHAR *data_ptr = frame_data;
+UINT send_marker = NX_FALSE;
+UINT temp_marker = NX_FALSE;
+UCHAR nal_unit_type;
+UCHAR fu_a_header[2];
+ULONG packet_num;
+ULONG last_packet_size;
+NX_PACKET *send_packet = NX_NULL;
+
+
+ /* In current design, the marker bit shall be always 1 (i.e. a complete h264 frame required to be passed). */
+ if (marker != NX_TRUE)
+ {
+ return(NX_NOT_SUPPORTED);
+ }
+
+ /* Obtain the maximum frame packet length. */
+ max_packet_length = session -> nx_rtp_session_max_packet_size;
+
+ /* Check frame minimum length. */
+ if (frame_data_size <= 4)
+ {
+ return(NX_SIZE_ERROR);
+ }
+
+ /* Record frame end position. */
+ frame_end = frame_data + frame_data_size - 1;
+
+ /* Is the h264 4 bytes or 3 bytes header found. */
+ if ((data_ptr[0] == 0x00) && (data_ptr[1] == 0x00) && (data_ptr[2] == 0x00) && (data_ptr[3] == 0x01))
+ {
+
+ /* Yes, skip the 4 bytes header. */
+ data_ptr += 4;
+ }
+ else if ((data_ptr[0] == 0x00) && (data_ptr[1] == 0x00) && (data_ptr[2] == 0x01))
+ {
+
+ /* Yes, skip the 3 bytes header. */
+ data_ptr += 3;
+ }
+ else
+ {
+
+ /* Wrong h264 header, return not successful. */
+ return(NX_NOT_SUCCESSFUL);
+ }
+
+ /* There are conditions requiring below while loop to guarantee the procedure of separation and transmission:
+ 1) Special frame(s) such as SEI, SPS and PPS are passed with a data frame.
+ 2) The data frame is composed of several slices
+ */
+ while (data_ptr <= (frame_end - 4))
+ {
+
+ /* Set the start position and reset the single frame size. */
+ nal_unit_start = data_ptr;
+ nal_unit_size = 0;
+
+ /* Extract a complete frame from the raw source file through finding the next 4/3 bytes header or the end of data buffer. */
+ while (1)
+ {
+
+ /* Check if there is a new slice header found */
+ if ((data_ptr[0] == 0x00) && (data_ptr[1] == 0x00))
+ {
+
+ if ((data_ptr[2] == 0x00) && (data_ptr[3] == 0x01))
+ {
+
+ /* Jump out if 4 bytes header of next frame/slice found. */
+ nal_unit_size = (ULONG)(data_ptr - nal_unit_start + 1);
+ data_ptr += 4;
+ break;
+ }
+ else if (data_ptr[2] == 0x01)
+ {
+
+ /* Jump out if 3 bytes header of next frame/slice found. */
+ nal_unit_size = (ULONG)(data_ptr - nal_unit_start + 1);
+ data_ptr += 3;
+ break;
+ }
+ }
+
+ /* Skip the check last 4 bytes if no header found is current position. */
+ if (data_ptr >= (frame_end - 4))
+ {
+
+ /* Compute nal unit size and move data pointer to the end. */
+ nal_unit_size = (ULONG)(frame_end - nal_unit_start + 1);
+ data_ptr = frame_end;
+
+ /* Set the send marker and jump out. */
+ send_marker = NX_TRUE;
+ break;
+ }
+
+ /* Move and check next byte. */
+ data_ptr++;
+ }
+
+ /* Initialize NAL unit type with the first byte after the h264 header. */
+ nal_unit_type = nal_unit_start[0];
+
+ /* Check NAL unit type. */
+ if (((nal_unit_type & NX_RTP_SENDER_H264_TYPE_MASK_BITS) == NX_RTP_SENDER_H264_TYPE_SEI) ||
+ ((nal_unit_type & NX_RTP_SENDER_H264_TYPE_MASK_BITS) == NX_RTP_SENDER_H264_TYPE_SPS) ||
+ ((nal_unit_type & NX_RTP_SENDER_H264_TYPE_MASK_BITS) == NX_RTP_SENDER_H264_TYPE_PPS))
+ {
+
+ /* Clear the send marker for special frames. */
+ send_marker = NX_FALSE;
+ }
+
+ /* Check the frame size and determine if more than 1 packet are needed. */
+ if (nal_unit_size <= max_packet_length)
+ {
+
+ /* RTP payload format for single NAL unit packet (in this case, the NAL header byte is the same as VCL header byte):
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |F|NRI| Type | |
+ +-+-+-+-+-+-+-+-+ |
+ | |
+ | Bytes 2..n of a single NAL unit |
+ | |
+ | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | :...OPTIONAL RTP padding |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+ /* Allocate a rtp packet */
+ status = _nx_rtp_sender_session_packet_allocate(session, &send_packet, NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ return(status);
+ }
+
+ /* Copy payload data into the packet. */
+ status = nx_packet_data_append(send_packet, (void*)nal_unit_start, nal_unit_size,
+ session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr,
+ NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ nx_packet_release(send_packet);
+ return(status);
+ }
+
+ /* Send packet data */
+ status = _nx_rtp_sender_session_packet_send(session, send_packet, timestamp, ntp_msw, ntp_lsw, send_marker);
+ if (status)
+ {
+ nx_packet_release(send_packet);
+ return(status);
+ }
+ }
+ else
+ {
+
+ /* RTP payload format for FU-A packets (in this case, 1 byte VCL header extends to 2 bytes NAL header):
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | FU indicator | FU header | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
+ | |
+ | FU payload |
+ | |
+ | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | :...OPTIONAL RTP padding |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ 1) Format for FU indicator octet: 2) Format for FU header:
+ +---------------+ +---------------+
+ |0|1|2|3|4|5|6|7| |0|1|2|3|4|5|6|7|
+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
+ |F|NRI| Type | |S|E|R| Type |
+ +---------------+ +---------------+
+ */
+
+ /* Reserve the bytes space for fu-a header. */
+ max_packet_length -= sizeof(fu_a_header);
+
+ /* Compute the number of packets with the size of the last packet. */
+ packet_num = ((nal_unit_size - 1) / max_packet_length) + 1;
+ last_packet_size = nal_unit_size % max_packet_length;
+
+ /* Initialize fu-a header's first byte with the source priority and fu-a type. */
+ fu_a_header[0] = (UCHAR)((nal_unit_type & NX_RTP_SENDER_H264_NRI_MASK_BITS) | NX_RTP_SENDER_H264_TYPE_FU_A);
+
+ /* Initialize fu-a header's second byte with the source nal unit type. */
+ fu_a_header[1] = (UCHAR)(nal_unit_type & NX_RTP_SENDER_H264_TYPE_MASK_BITS);
+
+ for (i = 0; i < packet_num; i++)
+ {
+
+ /* Check which packet to transmit and execute different corresponding logic. */
+ if (i == 0)
+ {
+
+ /* Set the fu-a start bit for the first frame fragment. */
+ fu_a_header[1] |= NX_RTP_SENDER_H264_FU_A_S_MASK_BIT;
+
+ /* Set the send marker as false. */
+ temp_marker = NX_FALSE;
+
+ /* Skip the first NAL unit type byte, and update the send packet length. */
+ nal_unit_start++;
+ send_packet_length = max_packet_length - 1;
+ }
+ else if (i == (packet_num - 1))
+ {
+
+ /* Clear the fu-a start bit and set fu-a end bit for the last frame fragment. */
+ fu_a_header[1] &= (UCHAR)(~NX_RTP_SENDER_H264_FU_A_S_MASK_BIT);
+ fu_a_header[1] |= NX_RTP_SENDER_H264_FU_A_E_MASK_BIT;
+
+ /* Update send marker by the final data frame flag. */
+ temp_marker = send_marker;
+
+ /* Update packet length based on whether the last packet size is not zero. */
+ send_packet_length = last_packet_size ? last_packet_size : max_packet_length;
+ }
+ else
+ {
+
+ /* Clear the fu-a start bit for middle slices. */
+ fu_a_header[1] &= (UCHAR)(~NX_RTP_SENDER_H264_FU_A_S_MASK_BIT);
+
+ /* Update the send packet length. */
+ send_packet_length = max_packet_length;
+ }
+
+ /* Allocate a packet */
+ status = _nx_rtp_sender_session_packet_allocate(session, &send_packet, NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ return(status);
+ }
+
+ /* Copy fu-a header into the packet. */
+ status = nx_packet_data_append(send_packet, (void *)fu_a_header, sizeof(fu_a_header),
+ session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr,
+ NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ nx_packet_release(send_packet);
+ return(status);
+ }
+
+ /* Copy payload data into the packet. */
+ status = nx_packet_data_append(send_packet, (void *)nal_unit_start, send_packet_length,
+ session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr,
+ NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ nx_packet_release(send_packet);
+ return(status);
+ }
+
+ /* Send packet data */
+ status = _nx_rtp_sender_session_packet_send(session, send_packet, timestamp, ntp_msw, ntp_lsw, temp_marker);
+ if (status)
+ {
+ nx_packet_release(send_packet);
+ return(status);
+ }
+
+ /* Move start pointer to following position. */
+ nal_unit_start += send_packet_length;
+ }
+ }
+ }
+
+ /* Return success status. */
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtp_sender_session_aac_send PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks errors in the RTP sender session aac send */
+/* function call. */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* frame_data Pointer to data buffer to send */
+/* frame_data_size Size of data to send */
+/* timestamp RTP timestamp for current data */
+/* ntp_msw Most significant word of */
+/* network time */
+/* ntp_lsw Least significant word of */
+/* network time */
+/* marker Marker bit for significant */
+/* event such as frame boundary */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* NX_PTR_ERROR Invalid pointer input */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_session_aac_send Send aac frame data */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtp_sender_session_aac_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
+ ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker)
+{
+
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((session == NX_NULL) || (session -> nx_rtp_sender == NX_NULL) || (session -> nx_rtp_session_id != NX_RTP_SESSION_ID) || (frame_data == NX_NULL))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual RTP sender session frame send service. */
+ status = _nx_rtp_sender_session_aac_send(session, frame_data, frame_data_size, timestamp, ntp_msw, ntp_lsw, marker);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtp_sender_session_aac_send PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function parses and makes the passed data in RTP/AAC format, */
+/* and then calls RTP session send function to send these data in RTP */
+/* packet, with AAC-HBR mode. */
+/* The function references RFC 3640 as the standard with below notes: */
+/* 1) A complete aac frame data shall be inside frame data buffer */
+/* 2) SDP shall indicate that aac-hbr mode is applied, with SizeLength */
+/* field to be 13 since 13-bit frame length is applied for */
+/* computing the length in AU header. */
+/* */
+/* INPUT */
+/* */
+/* session Pointer to RTP session */
+/* frame_data Pointer to data buffer to send */
+/* frame_data_size Size of data to send */
+/* timestamp RTP timestamp for current data */
+/* ntp_msw Most significant word of */
+/* network time */
+/* ntp_lsw Least significant word of */
+/* network time */
+/* marker Marker bit for significant */
+/* event such as frame boundary */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtp_sender_session_packet_allocate */
+/* Allocate a packet for the user */
+/* nx_packet_data_append Copy the specified data to */
+/* the end of specified packet */
+/* nx_packet_data_release Release the packet */
+/* _nx_rtp_sender_session_packet_send Send RTP packet */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtp_sender_session_aac_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
+ ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker)
+{
+
+UINT status;
+UCHAR au_header[4] = {0x00, 0x10, 0x00, 0x00}; /* First 2 bytes represent au header length, with default 16 bits. */
+ULONG send_packet_length;
+ULONG max_packet_length = session -> nx_rtp_session_max_packet_size - sizeof(au_header);
+NX_PACKET *send_packet = NX_NULL;
+UCHAR *data_ptr;
+UINT temp_marker;
+
+
+ /* In current design, the marker bit shall be always 1 (i.e. a complete aac frame required to be passed). */
+ if (marker != NX_TRUE)
+ {
+ return(NX_NOT_SUPPORTED);
+ }
+
+ /* When frame data exceeds maximum defined value, it requires access unit fragment feature which is not supported so far.
+ This check is specific for aac-hbr mode. */
+ if (frame_data_size > NX_RTP_SENDER_AAC_HBR_MODE_MAX_DATA_SIZE)
+ {
+ return(NX_NOT_SUPPORTED);
+ }
+
+ /* Initialize data_ptr to where data bytes begin. */
+ data_ptr = frame_data;
+
+ while (frame_data_size > 0)
+ {
+
+ /* Allocate a rtp packet. */
+ status = _nx_rtp_sender_session_packet_allocate(session, &send_packet, NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ return(status);
+ }
+
+ /* Check if fragmentation needed, and assign data length. */
+ if (frame_data_size > max_packet_length)
+ {
+ send_packet_length = max_packet_length;
+ temp_marker = NX_FALSE;
+ }
+ else
+ {
+ send_packet_length = frame_data_size;
+ temp_marker = NX_TRUE;
+ }
+
+ /* Compute the data length inside the current packet. */
+ au_header[2] = (UCHAR)((send_packet_length & NX_RTP_SENDER_AAC_FRAME_DATA_LENGTH_HIGH_BITS_MASK) >> 5);
+ au_header[3] = (UCHAR)((send_packet_length & NX_RTP_SENDER_AAC_FRAME_DATA_LENGTH_LOW_BITS_MASK) << 3);
+
+ /* Copy aac header data into the packet. */
+ status = nx_packet_data_append(send_packet, (void *)au_header, sizeof(au_header),
+ session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ nx_packet_release(send_packet);
+ return(status);
+ }
+
+ /* Copy payload data into the packet. */
+ status = nx_packet_data_append(send_packet, (void *)data_ptr, send_packet_length,
+ session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_RTP_SENDER_PACKET_TIMEOUT);
+ if (status)
+ {
+ nx_packet_release(send_packet);
+ return(status);
+ }
+
+ /* Send AAC frame through rtp; passed marker bit with true when this is the last frame packet. */
+ status = _nx_rtp_sender_session_packet_send(session, send_packet, timestamp, ntp_msw, ntp_lsw, temp_marker);
+ if (status)
+ {
+ nx_packet_release(send_packet);
+ return(status);
+ }
+
+ /* Compute remaining frame length and move data pointer. */
+ frame_data_size -= send_packet_length;
+ data_ptr += send_packet_length;
+ }
+
+ /* Return success status. */
+ return(NX_SUCCESS);
+}
diff --git a/addons/rtp/nx_rtp_sender.h b/addons/rtp/nx_rtp_sender.h
new file mode 100644
index 00000000..fe07bff2
--- /dev/null
+++ b/addons/rtp/nx_rtp_sender.h
@@ -0,0 +1,495 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Real Time Transport Protocol (RTP) */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* APPLICATION INTERFACE DEFINITION RELEASE */
+/* */
+/* nx_rtp_sender.h PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the NetX RTP Sender component, including all */
+/* data types and external references. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+
+#ifndef _NX_RTP_SENDER_H_
+#define _NX_RTP_SENDER_H_
+
+#include "tx_api.h"
+#include "nx_api.h"
+
+/* Determine if a C++ compiler is being used. If so, ensure that standard
+ C is used to process the API information. */
+
+#ifdef __cplusplus
+/* Yes, C++ compiler is present. Use standard C. */
+extern "C" {
+
+#endif
+
+#ifdef NX_DISABLE_PACKET_CHAIN
+#error "NX_DISABLE_PACKET_CHAIN must not be defined"
+#endif /* NX_DISABLE_PACKET_CHAIN */
+
+/* Define UDP socket create options. */
+#ifndef NX_RTP_SENDER_TYPE_OF_SERVICE
+#define NX_RTP_SENDER_TYPE_OF_SERVICE NX_IP_NORMAL
+#endif /* NX_RTP_SENDER_TYPE_OF_SERVICE */
+
+#ifndef NX_RTP_SENDER_FRAGMENT_OPTION
+#define NX_RTP_SENDER_FRAGMENT_OPTION NX_FRAGMENT_OKAY
+#endif /* NX_RTP_SENDER_FRAGMENT_OPTION */
+
+#ifndef NX_RTP_SENDER_TIME_TO_LIVE
+#define NX_RTP_SENDER_TIME_TO_LIVE 0x80
+#endif /* NX_RTP_SENDER_TIME_TO_LIVE */
+
+#ifndef NX_RTP_SENDER_QUEUE_DEPTH
+#define NX_RTP_SENDER_QUEUE_DEPTH 5
+#endif /* NX_RTP_SENDER_QUEUE_DEPTH */
+
+#ifndef NX_RTP_SENDER_PACKET_TIMEOUT
+#define NX_RTP_SENDER_PACKET_TIMEOUT (1 * NX_IP_PERIODIC_RATE)
+#endif /* NX_RTP_SENDER_PACKET_TIMEOUT */
+
+/* 5 seconds is the recommended minimum interval by RFC 3550, Chapter 6.2. */
+#ifndef NX_RTCP_INTERVAL
+#define NX_RTCP_INTERVAL 5
+#endif /* NX_RTCP_INTERVAL */
+
+/* RTP Payload Type Table - Reference RFC 3551, Page33-34, Table 4-5 */
+#define NX_RTP_SENDER_PAYLOAD_TYPE_AUDIO_PCMU 0 /* G.711 */
+#define NX_RTP_SENDER_PAYLOAD_TYPE_AUDIO_GSM 3
+#define NX_RTP_SENDER_PAYLOAD_TYPE_AUDIO_G723 4
+#define NX_RTP_SENDER_PAYLOAD_TYPE_AUDIO_DVI4_8000HZ 5
+#define NX_RTP_SENDER_PAYLOAD_TYPE_AUDIO_DVI4_16000HZ 6
+#define NX_RTP_SENDER_PAYLOAD_TYPE_AUDIO_LPC 7
+#define NX_RTP_SENDER_PAYLOAD_TYPE_AUDIO_PCMA 8 /* G.711 */
+#define NX_RTP_SENDER_PAYLOAD_TYPE_AUDIO_G722 9
+#define NX_RTP_SENDER_PAYLOAD_TYPE_AUDIO_L16_2_CHANNELS 10
+#define NX_RTP_SENDER_PAYLOAD_TYPE_AUDIO_L16_1_CHANNEL 11
+#define NX_RTP_SENDER_PAYLOAD_TYPE_AUDIO_QCELP 12
+#define NX_RTP_SENDER_PAYLOAD_TYPE_AUDIO_CN 13
+#define NX_RTP_SENDER_PAYLOAD_TYPE_AUDIO_MPA 14 /* RFC 2250 */
+#define NX_RTP_SENDER_PAYLOAD_TYPE_AUDIO_G728 15
+#define NX_RTP_SENDER_PAYLOAD_TYPE_AUDIO_DVI4_11025HZ 16
+#define NX_RTP_SENDER_PAYLOAD_TYPE_AUDIO_DVI4_22050HZ 17
+#define NX_RTP_SENDER_PAYLOAD_TYPE_AUDIO_G729 18
+#define NX_RTP_SENDER_PAYLOAD_TYPE_VIDEO_CELB 25 /* RFC 2029 */
+#define NX_RTP_SENDER_PAYLOAD_TYPE_VIDEO_JPEG 26 /* RFC 2435 */
+#define NX_RTP_SENDER_PAYLOAD_TYPE_VIDEO_NV 28
+#define NX_RTP_SENDER_PAYLOAD_TYPE_VIDEO_H261 31 /* RFC 2032 */
+#define NX_RTP_SENDER_PAYLOAD_TYPE_VIDEO_MPV 32 /* RFC 2250 */
+#define NX_RTP_SENDER_PAYLOAD_TYPE_AUDIO_VIDEO_MP2T 33 /* RFC 2250 */
+#define NX_RTP_SENDER_PAYLOAD_TYPE_VIDEO_H263 34 /* RFC 2190 */
+#define NX_RTP_SENDER_PAYLOAD_TYPE_DYNAMIC_MIN 96
+#define NX_RTP_SENDER_PAYLOAD_TYPE_DYNAMIC_MAX 127
+
+/* Use the string "RTPS" as a magic number for RTP sender */
+#define NX_RTP_SENDER_ID 0x52545053
+#define NX_RTP_SESSION_ID 0x52545054
+
+/* The initial target rtp port to use - Reference RFC3551, section 8, p35 */
+#define NX_RTP_SENDER_INITIAL_RTP_PORT 5004
+
+/* The rtp header length and corresponding rtp packet header size */
+#define NX_RTP_HEADER_LENGTH 12
+#define NX_RTP_PACKET (NX_UDP_PACKET + NX_RTP_HEADER_LENGTH)
+
+/* Define RTP protocol version. */
+#define NX_RTP_VERSION 2
+
+/* Define RTP header field(s) */
+#define NX_RTP_HEADER_MARKER_BIT 0x80
+
+/* Define RTCP packet types. */
+#define NX_RTCP_TYPE_SR 200
+#define NX_RTCP_TYPE_RR 201
+#define NX_RTCP_TYPE_SDES 202
+
+/* Define SDES types. */
+#define NX_RTCP_SDES_TYPE_CNAME 1
+
+/* Define mask for version and padding bit pair. */
+#define NX_RTCP_COUNT_MASK 0x1F
+#define NX_RTCP_VERSION_MASK 0xC0
+#define NX_RTCP_PAD_MASK 0x20
+#define NX_RTCP_TYPE_MASK 0xFE
+#define NX_RTCP_VERSION_VALUE (NX_RTP_VERSION << 6)
+#define NX_RTCP_PAD_VALUE 0
+
+/* Define receiver report structure for user callback. */
+typedef struct NX_RTCP_RECEIVER_REPORT_STRUCT
+{
+ UINT receiver_ssrc;
+ UINT fraction_loss;
+ INT packet_loss;
+ UINT extended_max;
+ UINT jitter;
+ UINT last_sr;
+ UINT delay;
+} NX_RTCP_RECEIVER_REPORT;
+
+/* Define SDES information structure for user callback. */
+typedef struct NX_RTCP_SDES_INFO_STRUCT
+{
+ UINT ssrc;
+ UCHAR *cname;
+ ULONG cname_length;
+} NX_RTCP_SDES_INFO;
+
+/* Define RTCP packet header structure for internal packet processing. */
+typedef struct NX_RTCP_HEADER_STRUCT
+{
+ /* V(2), P(1), RC(5). */
+ UCHAR nx_rtcp_byte0;
+
+ /* RTCP packet type. */
+ UCHAR nx_rtcp_packet_type;
+
+ /* Packet length in words. */
+ USHORT nx_rtcp_length;
+} NX_RTCP_HEADER;
+
+/* Define RTCP report block structure for internal packet processing. */
+typedef struct NX_RTCP_REPORT_STRUCT
+{
+
+ /* Data source being reported. */
+ ULONG nx_rtcp_report_ssrc;
+
+ /* Fraction loss + cumulative number of packets lost. */
+ ULONG nx_rtcp_report_loss;
+
+ /* Extended hightest sequence number received. */
+ ULONG nx_rtcp_report_extended_max;
+
+ /* Data packet inter-arrival time. */
+ ULONG nx_rtcp_report_jitter;
+
+ /* The middle 32 bits out of 64 in the NTP timestamp. */
+ ULONG nx_rtcp_report_last_sr;
+
+ /* Delay since last SR timestamp. */
+ ULONG nx_rtcp_report_delay;
+} NX_RTCP_REPORT;
+
+/* Define RTCP RR block for internal packet processing. */
+typedef struct NX_RTCP_RR_STRUCT
+{
+ /* Packet header. */
+ NX_RTCP_HEADER nx_rtcp_rr_header;
+
+ /* RTCP packet type. */
+ ULONG nx_rtcp_rr_ssrc;
+
+ /* Reception report block. */
+ NX_RTCP_REPORT nx_rtcp_rr_report;
+} NX_RTCP_RR;
+
+/* Define RTCP SR structure for internal packet processing. */
+typedef struct NX_RTCP_SR_STRUCT
+{
+ NX_RTCP_HEADER nx_rtcp_sr_header;
+ ULONG nx_rtcp_sr_ssrc;
+ ULONG nx_rtcp_sr_ntp_timestamp_msw;
+ ULONG nx_rtcp_sr_ntp_timestamp_lsw;
+ ULONG nx_rtcp_sr_rtp_timestamp;
+ ULONG nx_rtcp_sr_rtp_packet_count;
+ ULONG nx_rtcp_sr_rtp_octet_count;
+} NX_RTCP_SR;
+
+/* Define RTCP SDES item structure for internal packet processing. */
+typedef struct NX_RTCP_SDES_ITEM_STRUCT
+{
+ UCHAR nx_rtcp_sdes_type; /* Chunk type. */
+ UCHAR nx_rtcp_sdes_length;
+ UCHAR nx_rtcp_sdes_data[1];
+} NX_RTCP_SDES_ITEM;
+
+/* Define RTCP SDES chunk structure for internal packet processing. */
+typedef struct NX_RTCP_SDES_CHUNK_STRUCT
+{
+ ULONG nx_rtcp_sdes_ssrc;
+ NX_RTCP_SDES_ITEM nx_rtcp_sdes_item[1];
+} NX_RTCP_SDES_CHUNK;
+
+typedef struct NX_RTP_SESSION_STRUCT NX_RTP_SESSION;
+
+typedef struct NX_RTP_SENDER_STRUCT
+{
+
+ /* Store the magic number for RTP sender service */
+ ULONG nx_rtp_sender_id;
+
+ /* Pointer to IP structure of the corresponding IP instance. */
+ NX_IP *nx_rtp_sender_ip_ptr;
+
+ /* Pointer to RTP sender packet pool */
+ NX_PACKET_POOL *nx_rtp_sender_packet_pool_ptr;
+
+ /* Mutex to protect critical section such as sequence number and so on */
+ TX_MUTEX nx_rtp_sender_protection;
+
+ /* Local RTP/RTCP port & socket */
+ USHORT nx_rtp_sender_rtp_port;
+ USHORT nx_rtp_sender_rtcp_port;
+ NX_UDP_SOCKET nx_rtp_sender_rtp_socket;
+ NX_UDP_SOCKET nx_rtp_sender_rtcp_socket;
+
+ /* Callback function to process rtcp messages. */
+ UINT (*nx_rtp_sender_rtcp_receiver_report_cb)(NX_RTP_SESSION *rtp_session, NX_RTCP_RECEIVER_REPORT *rtcp_receiver_report);
+ UINT (*nx_rtp_sender_rtcp_sdes_cb)(NX_RTCP_SDES_INFO *sdes_info);
+
+ /* RTP sender name */
+ CHAR *nx_rtp_sender_cname;
+ UCHAR nx_rtp_sender_cname_length;
+
+ NX_RTP_SESSION *nx_rtp_sender_session_created_ptr;
+} NX_RTP_SENDER;
+
+struct NX_RTP_SESSION_STRUCT
+{
+
+ /* Store the pointer for the corresponding rtp sender */
+ NX_RTP_SENDER *nx_rtp_sender;
+
+ /* Store the magic number for the specific RTP session */
+ ULONG nx_rtp_session_id;
+
+ /* Store the ip interface index when session created. */
+ UINT nx_rtp_session_interface_index;
+
+ /* Receiver's IP address and port number */
+ NXD_ADDRESS nx_rtp_session_peer_ip_address;
+ USHORT nx_rtp_session_peer_rtp_port;
+ USHORT nx_rtp_session_peer_rtcp_port;
+
+ /* RTP header */
+ UCHAR nx_rtp_session_reserved; /* Alignment */
+ UCHAR nx_rtp_session_payload_type; /* Type, to be programmed into payload type field in RTP header */
+ USHORT nx_rtp_session_sequence_number; /* Session sequence number */
+ ULONG nx_rtp_session_ssrc;
+
+ /* The maximum frame packet size computed corresponding to mtu. */
+ ULONG nx_rtp_session_max_packet_size;
+
+ /* None zero value: sample-based encoding
+ Default zero value: frame-based encoding */
+ ULONG nx_rtp_session_sample_factor;
+
+ /* RTCP statistics */
+
+ /* The total number of RTP data packets transmitted by the sender. */
+ ULONG nx_rtp_session_packet_count;
+
+ /* The total number of payload octets transmitted by the sender. */
+ ULONG nx_rtp_session_octet_count;
+
+ /* The timestamp of last sent RTP packet. */
+ ULONG nx_rtp_session_rtp_timestamp;
+
+ /* The most significant word of the NTP timestamp corresponds to the same time as the RTP timestamp. */
+ ULONG nx_rtp_session_ntp_timestamp_msw;
+
+ /* The least significant word of the NTP timestamp corresponds to the same time as the RTP timestamp. */
+ ULONG nx_rtp_session_ntp_timestamp_lsw;
+
+ /* The last time an RTCP packet was transmitted. */
+ ULONG nx_rtp_session_rtcp_time;
+
+ struct NX_RTP_SESSION_STRUCT *nx_rtp_session_next;
+};
+
+typedef struct NX_RTP_HEADER_STRUCT
+{
+ UCHAR nx_rtp_header_field0;
+ UCHAR nx_rtp_header_field1;
+ USHORT nx_rtp_header_sequence_number;
+ ULONG nx_rtp_header_timestamp;
+ ULONG nx_rtp_header_ssrc;
+} NX_RTP_HEADER;
+
+
+#ifndef NX_RTP_SENDER_SOURCE_CODE
+
+/* Application caller is present, perform API mapping. */
+
+/* Determine if error checking is desired. If so, map API functions
+ to the appropriate error checking front-ends. Otherwise, map API
+ functions to the core functions that actually perform the work.
+ Note: error checking is enabled by default. */
+#ifdef NX_DISABLE_ERROR_CHECKING
+
+/* Services without error checking. */
+#define nx_rtp_sender_create _nx_rtp_sender_create
+#define nx_rtp_sender_delete _nx_rtp_sender_delete
+#define nx_rtp_sender_port_get _nx_rtp_sender_port_get
+#define nx_rtp_sender_session_create _nx_rtp_sender_session_create
+#define nx_rtp_sender_session_delete _nx_rtp_sender_session_delete
+#define nx_rtp_sender_session_sample_factor_set _nx_rtp_sender_session_sample_factor_set
+#define nx_rtp_sender_session_packet_allocate _nx_rtp_sender_session_packet_allocate
+#define nx_rtp_sender_session_packet_send _nx_rtp_sender_session_packet_send
+#define nx_rtp_sender_session_jpeg_send _nx_rtp_sender_session_jpeg_send
+#define nx_rtp_sender_session_h264_send _nx_rtp_sender_session_h264_send
+#define nx_rtp_sender_session_aac_send _nx_rtp_sender_session_aac_send
+#define nx_rtp_sender_session_sequence_number_get _nx_rtp_sender_session_sequence_number_get
+#define nx_rtp_sender_session_ssrc_get _nx_rtp_sender_session_ssrc_get
+#define nx_rtp_sender_rtcp_receiver_report_callback_set _nx_rtp_sender_rtcp_receiver_report_callback_set
+#define nx_rtp_sender_rtcp_sdes_callback_set _nx_rtp_sender_rtcp_sdes_callback_set
+
+#else
+
+/* Services with error checking. */
+#define nx_rtp_sender_create _nxe_rtp_sender_create
+#define nx_rtp_sender_delete _nxe_rtp_sender_delete
+#define nx_rtp_sender_port_get _nxe_rtp_sender_port_get
+#define nx_rtp_sender_session_create _nxe_rtp_sender_session_create
+#define nx_rtp_sender_session_delete _nxe_rtp_sender_session_delete
+#define nx_rtp_sender_session_sample_factor_set _nxe_rtp_sender_session_sample_factor_set
+#define nx_rtp_sender_session_packet_allocate _nxe_rtp_sender_session_packet_allocate
+#define nx_rtp_sender_session_packet_send _nxe_rtp_sender_session_packet_send
+#define nx_rtp_sender_session_jpeg_send _nxe_rtp_sender_session_jpeg_send
+#define nx_rtp_sender_session_h264_send _nxe_rtp_sender_session_h264_send
+#define nx_rtp_sender_session_aac_send _nxe_rtp_sender_session_aac_send
+#define nx_rtp_sender_session_sequence_number_get _nxe_rtp_sender_session_sequence_number_get
+#define nx_rtp_sender_session_ssrc_get _nxe_rtp_sender_session_ssrc_get
+#define nx_rtp_sender_rtcp_receiver_report_callback_set _nxe_rtp_sender_rtcp_receiver_report_callback_set
+#define nx_rtp_sender_rtcp_sdes_callback_set _nxe_rtp_sender_rtcp_sdes_callback_set
+
+#endif /* NX_DISABLE_ERROR_CHECKING */
+
+/* Define the prototypes accessible to the application software. */
+
+/* Initiate RTP sender service, create UDP sockets. */
+UINT nx_rtp_sender_create(NX_RTP_SENDER *rtp_sender, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, CHAR *cname, UCHAR cname_length);
+
+/* Terminate the RTP service */
+UINT nx_rtp_sender_delete(NX_RTP_SENDER *rtp_sender);
+
+/* Obtain RTP/RTCP port numbers. The port numbers may be used by RTSP */
+UINT nx_rtp_sender_port_get(NX_RTP_SENDER *rtp_sender, UINT *rtp_port, UINT *rtcp_port);
+
+/* Setup a session, find and bind to available ports. */
+UINT nx_rtp_sender_session_create(NX_RTP_SENDER *rtp_sender, NX_RTP_SESSION *session, ULONG payload_type,
+ UINT interface_index, NXD_ADDRESS *receiver_ip_address,
+ UINT receiver_rtp_port_number, UINT receiver_rtcp_port_number);
+
+/* Delete a session, and then it is available to re-setup the session */
+UINT nx_rtp_sender_session_delete(NX_RTP_SESSION *session);
+
+/* Set the sample factor for sample-based mode inside the specific session. */
+UINT nx_rtp_sender_session_sample_factor_set(NX_RTP_SESSION *session, UINT factor);
+
+/* Allocate and obtain a rtp session packet. */
+UINT nx_rtp_sender_session_packet_allocate(NX_RTP_SESSION *session, NX_PACKET **packet_ptr, ULONG wait_option);
+
+/* Send payload data through a specific session. */
+UINT nx_rtp_sender_session_packet_send(NX_RTP_SESSION *session, NX_PACKET *packet_ptr, ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker);
+
+/* API functions for sending video payload over rtp. */
+UINT nx_rtp_sender_session_jpeg_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
+ ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker);
+UINT nx_rtp_sender_session_h264_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
+ ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker);
+
+/* API functions for sending audio payload over rtp. */
+UINT nx_rtp_sender_session_aac_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size, ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker);
+
+/* Obtain the current sequence number inside the specific session. */
+UINT nx_rtp_sender_session_sequence_number_get(NX_RTP_SESSION *session, UINT *sequence_number);
+
+/* Obtain the current ssrc inside the specific session. */
+UINT nx_rtp_sender_session_ssrc_get(NX_RTP_SESSION *session, ULONG *ssrc);
+
+/* Set a callback function to handle incoming RTCP message. */
+UINT nx_rtp_sender_rtcp_receiver_report_callback_set(NX_RTP_SENDER *rtp_sender, UINT (*rtcp_rr_cb)(NX_RTP_SESSION *, NX_RTCP_RECEIVER_REPORT *));
+UINT nx_rtp_sender_rtcp_sdes_callback_set(NX_RTP_SENDER *rtp_sender, UINT (*rtcp_sdes_cb)(NX_RTCP_SDES_INFO *));
+
+#else
+
+/* Define the prototypes accessible to the application software. */
+
+UINT _nxe_rtp_sender_create(NX_RTP_SENDER *rtp_sender, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, CHAR *cname, UCHAR cname_length);
+UINT _nx_rtp_sender_create(NX_RTP_SENDER *rtp_sender, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, CHAR *cname, UCHAR cname_length);
+UINT _nxe_rtp_sender_delete(NX_RTP_SENDER *rtp_sender);
+UINT _nx_rtp_sender_delete(NX_RTP_SENDER *rtp_sender);
+UINT _nxe_rtp_sender_port_get(NX_RTP_SENDER *rtp_sender, UINT *rtp_port, UINT *rtcp_port);
+UINT _nx_rtp_sender_port_get(NX_RTP_SENDER *rtp_sender, UINT *rtp_port, UINT *rtcp_port);
+UINT _nxe_rtp_sender_session_create(NX_RTP_SENDER *rtp_sender, NX_RTP_SESSION *session, ULONG payload_type,
+ UINT interface_index, NXD_ADDRESS *receiver_ip_address,
+ UINT receiver_rtp_port_number, UINT receiver_rtcp_port_number);
+UINT _nx_rtp_sender_session_create(NX_RTP_SENDER *rtp_sender, NX_RTP_SESSION *session, ULONG payload_type,
+ UINT interface_index, NXD_ADDRESS *receiver_ip_address,
+ UINT receiver_rtp_port_number, UINT receiver_rtcp_port_number);
+UINT _nxe_rtp_sender_session_delete(NX_RTP_SESSION *session);
+UINT _nx_rtp_sender_session_delete(NX_RTP_SESSION *session);
+UINT _nxe_rtp_sender_session_sample_factor_set(NX_RTP_SESSION *session, UINT factor);
+UINT _nx_rtp_sender_session_sample_factor_set(NX_RTP_SESSION *session, UINT factor);
+UINT _nxe_rtp_sender_session_packet_allocate(NX_RTP_SESSION *session, NX_PACKET **packet_ptr, ULONG wait_option);
+UINT _nx_rtp_sender_session_packet_allocate(NX_RTP_SESSION *session, NX_PACKET **packet_ptr, ULONG wait_option);
+UINT _nxe_rtp_sender_session_packet_send(NX_RTP_SESSION *session, NX_PACKET *packet_ptr, ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker);
+UINT _nx_rtp_sender_session_packet_send(NX_RTP_SESSION *session, NX_PACKET *packet_ptr, ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker);
+UINT _nxe_rtp_sender_session_sequence_number_get(NX_RTP_SESSION *session, UINT *sequence_number);
+UINT _nx_rtp_sender_session_sequence_number_get(NX_RTP_SESSION *session, UINT *sequence_number);
+UINT _nxe_rtp_sender_session_jpeg_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
+ ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker);
+UINT _nx_rtp_sender_session_jpeg_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
+ ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker);
+UINT _nxe_rtp_sender_session_h264_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
+ ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker);
+UINT _nx_rtp_sender_session_h264_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
+ ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker);
+UINT _nxe_rtp_sender_session_aac_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
+ ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker);
+UINT _nx_rtp_sender_session_aac_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
+ ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker);
+UINT _nxe_rtp_sender_session_ssrc_get(NX_RTP_SESSION *session, ULONG *ssrc);
+UINT _nx_rtp_sender_session_ssrc_get(NX_RTP_SESSION *session, ULONG *ssrc);
+UINT _nxe_rtp_sender_rtcp_receiver_report_callback_set(NX_RTP_SENDER *rtp_sender, UINT (*rtcp_rr_cb)(NX_RTP_SESSION *, NX_RTCP_RECEIVER_REPORT *));
+UINT _nx_rtp_sender_rtcp_receiver_report_callback_set(NX_RTP_SENDER *rtp_sender, UINT (*rtcp_rr_cb)(NX_RTP_SESSION *, NX_RTCP_RECEIVER_REPORT *));
+UINT _nxe_rtp_sender_rtcp_sdes_callback_set(NX_RTP_SENDER *rtp_sender, UINT (*rtcp_sdes_cb)(NX_RTCP_SDES_INFO *));
+UINT _nx_rtp_sender_rtcp_sdes_callback_set(NX_RTP_SENDER *rtp_sender, UINT (*rtcp_sdes_cb)(NX_RTCP_SDES_INFO *));
+
+#endif /* NX_RTP_SENDER_SOURCE_CODE */
+
+/* Determine if a C++ compiler is being used. If so, complete the standard
+ C conditional started above. */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NX_RTP_SENDER_H_ */
+
diff --git a/addons/rtsp/nx_rtsp_server.c b/addons/rtsp/nx_rtsp_server.c
new file mode 100644
index 00000000..ef8eb768
--- /dev/null
+++ b/addons/rtsp/nx_rtsp_server.c
@@ -0,0 +1,4854 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Real Time Streaming Protocol (RTSP) */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+#define NX_RTSP_SERVER_SOURCE_CODE
+
+/* Force error checking to be disabled in this module. */
+
+#ifndef NX_DISABLE_ERROR_CHECKING
+#define NX_DISABLE_ERROR_CHECKING
+#endif
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "nx_api.h"
+#include "nx_ip.h"
+#ifdef FEATURE_NX_IPV6
+#include "nx_ipv6.h"
+#endif /* #ifdef FEATURE_NX_IPV6 */
+#include "nx_rtsp_server.h"
+
+/* Define the internal functions. */
+
+static VOID _nx_rtsp_server_thread_entry(ULONG);
+
+static VOID _nx_rtsp_server_connect_present(NX_TCP_SOCKET *request_socket_ptr, UINT port);
+static VOID _nx_rtsp_server_connect_process(NX_RTSP_SERVER *rtsp_server_ptr);
+
+static VOID _nx_rtsp_server_disconnect_present(NX_TCP_SOCKET *request_socket_ptr);
+static VOID _nx_rtsp_server_disconnect_process(NX_RTSP_SERVER *rtsp_server_ptr);
+
+static VOID _nx_rtsp_server_request_present(NX_TCP_SOCKET *request_socket_ptr);
+static VOID _nx_rtsp_server_request_process(NX_RTSP_SERVER *rtsp_server_ptr);
+
+static VOID _nx_rtsp_server_timeout(ULONG rtsp_server_address);
+static VOID _nx_rtsp_server_timeout_process(NX_RTSP_SERVER *rtsp_server_ptr);
+
+static UINT _nx_rtsp_server_request_receive(NX_RTSP_SERVER *rtsp_server_ptr, NX_RTSP_CLIENT *rtsp_client_ptr);
+static UINT _nx_rtsp_server_request_parse(NX_RTSP_CLIENT *rtsp_client_ptr, NX_RTSP_CLIENT_REQUEST *rtsp_client_request_ptr);
+static UINT _nx_rtsp_server_request_line_parse(NX_RTSP_CLIENT_REQUEST *rtsp_client_request_ptr, UCHAR **request_buffer, UCHAR *request_buffer_end);
+static UINT _nx_rtsp_server_request_header_parse(NX_RTSP_CLIENT *rtsp_client_ptr, NX_RTSP_CLIENT_REQUEST *rtsp_client_request_ptr, UCHAR **request_buffer, UCHAR *request_buffer_end);
+static UINT _nx_rtsp_server_response_create(NX_RTSP_SERVER *rtsp_server_ptr, NX_RTSP_CLIENT *rtsp_client_ptr, NX_RTSP_CLIENT_REQUEST *rtsp_client_request_ptr);
+static UINT _nx_rtsp_server_response_send(NX_RTSP_SERVER *rtsp_server_ptr, NX_RTSP_CLIENT *rtsp_client_ptr, NX_RTSP_CLIENT_REQUEST *rtsp_client_request_ptr);
+
+static VOID _nx_rtsp_server_disconnect(NX_RTSP_SERVER *rtsp_server_ptr, NX_RTSP_CLIENT *rtsp_client_ptr);
+
+static UINT _nx_rtsp_server_memicmp(UCHAR *src, ULONG src_length, UCHAR *dest, ULONG dest_length);
+static UCHAR *_nx_rtsp_server_strstr(UCHAR *src, ULONG src_length, UCHAR *dest, ULONG dest_length);
+
+/* Define macros. */
+
+#define NX_RTSP_SERVER_STRING_SIZE(str) sizeof(str) - 1
+#define NX_RTSP_SERVER_STRING_WITH_SIZE(str) (UCHAR *)str, NX_RTSP_SERVER_STRING_SIZE(str)
+
+/* Bring in externs for caller checking code. */
+
+NX_CALLER_CHECKING_EXTERNS
+
+/* Define description table for the RTSP response status code. */
+
+const NX_RTSP_RESPONSE nx_rtsp_server_response_description_table[] =
+{
+ { NX_RTSP_STATUS_CODE_OK , "OK" },
+ { NX_RTSP_STATUS_CODE_CREATED , "CREATED" },
+ { NX_RTSP_STATUS_CODE_LOW_ON_STORAGE_SPACE , "LOW ON STORAGE SPACE" },
+ { NX_RTSP_STATUS_CODE_MULTIPLE_CHOICES , "MULTIPLE CHOICES" },
+ { NX_RTSP_STATUS_CODE_MOVED_PERMANENTLY , "MOVED PERMANENTLY" },
+ { NX_RTSP_STATUS_CODE_MOVED_TEMPORARILY , "MOVED TEMPORARILY" },
+ { NX_RTSP_STATUS_CODE_SEE_OTHER , "SEE OTHER" },
+ { NX_RTSP_STATUS_CODE_NOT_MODIFIED , "NOT MODIFIED" },
+ { NX_RTSP_STATUS_CODE_USE_PROXY , "USE PROXY" },
+ { NX_RTSP_STATUS_CODE_GOING_AWAY , "GOING AWAY" },
+ { NX_RTSP_STATUS_CODE_LOAD_BALANCING , "LOAD BALANCING" },
+ { NX_RTSP_STATUS_CODE_BAD_REQUEST , "BAD REQUEST" },
+ { NX_RTSP_STATUS_CODE_UNAUTHORIZED , "UNAUTHORIZED" },
+ { NX_RTSP_STATUS_CODE_PAYMENT_REQUIRED , "PAYMENT REQUIRED" },
+ { NX_RTSP_STATUS_CODE_FORBIDDEN , "FORBIDDEN" },
+ { NX_RTSP_STATUS_CODE_NOT_FOUND , "NOT FOUND" },
+ { NX_RTSP_STATUS_CODE_METHOD_NOT_ALLOWED , "METHOD NOT ALLOWED" },
+ { NX_RTSP_STATUS_CODE_NOT_ACCEPTABLE , "NOT ACCEPTABLE" },
+ { NX_RTSP_STATUS_CODE_PROXY_AUTHENTICATION_REQUIRED , "PROXY AUTHENTICATION REQUIRED" },
+ { NX_RTSP_STATUS_CODE_REQUEST_TIMEOUT , "REQUEST TIMEOUT" },
+ { NX_RTSP_STATUS_CODE_GONE , "GONE" },
+ { NX_RTSP_STATUS_CODE_LENGTH_REQUIRED , "LENGTH REQUIRED" },
+ { NX_RTSP_STATUS_CODE_PRECONDITION_FAILED , "PRECONDITION FAILED" },
+ { NX_RTSP_STATUS_CODE_REQUEST_ENTITY_TOO_LARGE , "REQUEST ENTITY TOO LARGE" },
+ { NX_RTSP_STATUS_CODE_REQUESTURI_TOO_LARGE , "REQUESTURI TOO LARGE" },
+ { NX_RTSP_STATUS_CODE_UNSUPPORTED_MEDIA_TYPE , "UNSUPPORTED MEDIA TYPE" },
+ { NX_RTSP_STATUS_CODE_PARAMETER_NOT_UNDERSTOOD , "PARAMETER NOT UNDERSTOOD" },
+ { NX_RTSP_STATUS_CODE_RESERVED , "RESERVED" },
+ { NX_RTSP_STATUS_CODE_NOT_ENOUGH_BANDWIDTH , "NOT ENOUGH BANDWIDTH" },
+ { NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND , "SESSION NOT FOUND" },
+ { NX_RTSP_STATUS_CODE_METHOD_NOT_VALID_IN_THIS_STATE , "METHOD NOT VALID IN THIS STATE" },
+ { NX_RTSP_STATUS_CODE_HEADER_FIELD_NOT_VALID_FOR_RESOURCE , "HEADER FIELD NOT VALID FOR RESOURCE" },
+ { NX_RTSP_STATUS_CODE_INVALID_RANGE , "INVALID RANGE" },
+ { NX_RTSP_STATUS_CODE_PARAMETER_IS_READONLY , "PARAMETER IS READONLY" },
+ { NX_RTSP_STATUS_CODE_AGGREGATE_OPERATION_NOT_ALLOWED , "AGGREGATE OPERATION NOT ALLOWED" },
+ { NX_RTSP_STATUS_CODE_ONLY_AGGREGATE_OPERATION_ALLOWED , "ONLY AGGREGATE OPERATION ALLOWED" },
+ { NX_RTSP_STATUS_CODE_UNSUPPORTED_TRANSPORT , "UNSUPPORTED TRANSPORT" },
+ { NX_RTSP_STATUS_CODE_DESTINATION_UNREACHABLE , "DESTINATION UNREACHABLE" },
+ { NX_RTSP_STATUS_CODE_INTERNAL_SERVER_ERROR , "INTERNAL SERVER ERROR" },
+ { NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED , "NOT IMPLEMENTED" },
+ { NX_RTSP_STATUS_CODE_BAD_GATEWAY , "BAD GATEWAY" },
+ { NX_RTSP_STATUS_CODE_SERVICE_UNAVAILABLE , "SERVICE UNAVAILABLE" },
+ { NX_RTSP_STATUS_CODE_GATEWAY_TIMEOUT , "GATEWAY TIMEOUT" },
+ { NX_RTSP_STATUS_CODE_RTSP_VERSION_NOT_SUPPORTED , "RTSP VERSION NOT SUPPORTED" },
+ { NX_RTSP_STATUS_CODE_OPTION_NOT_SUPPORTED , "OPTION NOT SUPPORTED" },
+ { NX_NULL , "" }
+};
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtsp_server_create PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in RTSP server create function call.*/
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* server_name Name of RTSP server */
+/* server_name_length Length of RTSP server name */
+/* ip_ptr Pointer to IP instance */
+/* rtsp_packet_pool Pointer to packet pool */
+/* stack_ptr Server thread's stack pointer */
+/* stack_size Server thread's stack size */
+/* priority The priority of the thread */
+/* server_port Listening port */
+/* disconnect_callback Disconnect callback function */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_create Create RTSP server */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtsp_server_create(NX_RTSP_SERVER *rtsp_server_ptr, CHAR *server_name, UINT server_name_length,
+ NX_IP *ip_ptr, NX_PACKET_POOL *rtsp_packet_pool,
+ VOID *stack_ptr, ULONG stack_size, UINT priority, UINT server_port,
+ UINT (*disconnect_callback)(NX_RTSP_CLIENT *rtsp_client_ptr))
+{
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((ip_ptr == NX_NULL) || (ip_ptr -> nx_ip_id != NX_IP_ID) ||
+ (rtsp_server_ptr == NX_NULL) || (stack_ptr == NX_NULL) ||
+ (rtsp_packet_pool == NX_NULL) || rtsp_server_ptr -> nx_rtsp_server_id == NX_RTSP_SERVER_ID)
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual RTSP server create function. */
+ status = _nx_rtsp_server_create(rtsp_server_ptr,server_name, server_name_length, ip_ptr, rtsp_packet_pool,
+ stack_ptr, stack_size, priority, server_port, disconnect_callback);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_create PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function creates a RTSP server on the specified IP and port. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* server_name Name of RTSP server */
+/* server_name_length Length of RTSP server name */
+/* ip_ptr Pointer to IP instance */
+/* rtsp_packet_pool Pointer to packet pool */
+/* stack_ptr Server thread's stack pointer */
+/* stack_size Server thread's stack size */
+/* priority The priority of the thread */
+/* server_port Listening port */
+/* disconnect_callback Disconnect callback function */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* memset Reset memory */
+/* tx_event_flags_create Create thread event flags */
+/* tx_thread_create Create the server thread */
+/* tx_timer_create Create the timeout timer */
+/* tx_event_flags_delete Delete thread event flags */
+/* tx_thread_delete Delete the server thread */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtsp_server_create(NX_RTSP_SERVER *rtsp_server_ptr, CHAR *server_name, UINT server_name_length,
+ NX_IP *ip_ptr, NX_PACKET_POOL *rtsp_packet_pool,
+ VOID *stack_ptr, ULONG stack_size, UINT priority, UINT server_port,
+ UINT (*disconnect_callback)(NX_RTSP_CLIENT *rtsp_client_ptr))
+{
+UINT status;
+
+
+ /* Clear RTSP server object. */
+ memset((VOID *)rtsp_server_ptr, 0, sizeof(NX_RTSP_SERVER));
+
+ /* Set the RTSP server name. */
+ rtsp_server_ptr -> nx_rtsp_server_name = server_name;
+ rtsp_server_ptr -> nx_rtsp_server_name_length = server_name_length;
+
+ /* Record our packet pool. */
+ rtsp_server_ptr -> nx_rtsp_server_packet_pool = rtsp_packet_pool;
+
+ /* Create the ThreadX event flags. These will be used to drive the RTSP server thread. */
+ status = tx_event_flags_create(&(rtsp_server_ptr -> nx_rtsp_server_event_flags), "RTSP Server Thread Events");
+
+ if (status)
+ {
+ return(status);
+ }
+
+ /* Create the RTSP server thread and start the RTSP server. */
+ status = tx_thread_create(&(rtsp_server_ptr -> nx_rtsp_server_thread), server_name,
+ _nx_rtsp_server_thread_entry, (ULONG)rtsp_server_ptr,
+ stack_ptr, stack_size, priority, priority,
+ NX_RTSP_SERVER_TIME_SLICE, TX_NO_ACTIVATE);
+
+ if (status)
+ {
+
+ /* Delete the event flag. */
+ tx_event_flags_delete(&(rtsp_server_ptr -> nx_rtsp_server_event_flags));
+ return(status);
+ }
+
+ /* Create the timeout timer. */
+ status = tx_timer_create(&(rtsp_server_ptr -> nx_rtsp_server_timer), "RTSP Server Timer",
+ _nx_rtsp_server_timeout, (ULONG)rtsp_server_ptr,
+ NX_IP_PERIODIC_RATE, NX_IP_PERIODIC_RATE, TX_NO_ACTIVATE);
+
+ if (status)
+ {
+
+ /* Delete the thread. */
+ tx_thread_delete(&(rtsp_server_ptr -> nx_rtsp_server_thread));
+
+ /* Delete the event flag. */
+ tx_event_flags_delete(&(rtsp_server_ptr -> nx_rtsp_server_event_flags));
+
+ return(status);
+ }
+
+ /* Set the IP pointer. */
+ rtsp_server_ptr -> nx_rtsp_server_ip_ptr = ip_ptr;
+
+ /* Set the TCP port of RTSP server. */
+ rtsp_server_ptr -> nx_rtsp_server_port = (USHORT)server_port;
+
+ /* Set disconnect callback function. */
+ rtsp_server_ptr -> nx_rtsp_server_disconnect_callback = disconnect_callback;
+
+ /* Set the RTSP server ID. */
+ rtsp_server_ptr -> nx_rtsp_server_id = NX_RTSP_SERVER_ID;
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtsp_server_delete PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in RTSP server delete function call.*/
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_delete Delete the RTSP server */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtsp_server_delete(NX_RTSP_SERVER *rtsp_server_ptr)
+{
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((rtsp_server_ptr == NX_NULL) || (rtsp_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual RTSP server delete function. */
+ status = _nx_rtsp_server_delete(rtsp_server_ptr);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_delete PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function deletes a previously created RTSP server on specified */
+/* IP and port. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_stop Stop the RTSP server */
+/* tx_thread_terminate Terminate server thread */
+/* tx_event_flags_delete Delete thread event flags */
+/* tx_thread_delete Delete the server thread */
+/* tx_timer_delete Delete the timeout timer */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtsp_server_delete(NX_RTSP_SERVER *rtsp_server_ptr)
+{
+
+
+ /* Stop the RTSP server if not done yet. */
+ if (rtsp_server_ptr -> nx_rtsp_server_started)
+ {
+ _nx_rtsp_server_stop(rtsp_server_ptr);
+ }
+
+ /* Terminate server thread. */
+ tx_thread_terminate(&(rtsp_server_ptr -> nx_rtsp_server_thread));
+
+ /* Delete server thread. */
+ tx_thread_delete(&(rtsp_server_ptr -> nx_rtsp_server_thread));
+
+ /* Delete the server event flags. */
+ tx_event_flags_delete(&(rtsp_server_ptr -> nx_rtsp_server_event_flags));
+
+ /* Delete the timer. */
+ tx_timer_delete(&(rtsp_server_ptr -> nx_rtsp_server_timer));
+
+ /* Clear the RTSP server ID. */
+ rtsp_server_ptr -> nx_rtsp_server_id = 0;
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtsp_server_start PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in RTSP server start function call. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_start Start the RTSP server */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtsp_server_start(NX_RTSP_SERVER *rtsp_server_ptr)
+{
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((rtsp_server_ptr == NX_NULL) || (rtsp_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual RTSP server start function. */
+ status = _nx_rtsp_server_start(rtsp_server_ptr);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_start PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function starts a previously created RTSP server. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* nx_tcp_socket_create Create TCP socket */
+/* nx_tcp_socket_receive_notify Set TCP notification callback */
+/* nx_tcp_socket_delete Delete TCP socket */
+/* nx_tcp_server_socket_listen Listen on free TCP socket */
+/* tx_thread_resume Resume the RTSP server thread */
+/* tx_timer_activate Activate the timeout timer */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtsp_server_start(NX_RTSP_SERVER *rtsp_server_ptr)
+{
+UINT status;
+int i, j;
+
+
+ /* Check if the RTSP server is started. */
+ if (rtsp_server_ptr -> nx_rtsp_server_started)
+ {
+ return(NX_RTSP_SERVER_ALREADY_STARTED);
+ }
+
+ /* Check if the required method callbacks are set. */
+ if ((rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_setup_callback == NX_NULL) ||
+ (rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_play_callback == NX_NULL) ||
+ (rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_teardown_callback == NX_NULL))
+ {
+ return(NX_RTSP_SERVER_MISSING_REQUIRED_CALLBACKS);
+ }
+
+ /* Loop to create all the RTSP client control sockets. */
+ for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
+ {
+
+ /* Create an RTSP client control socket. */
+ status = nx_tcp_socket_create(rtsp_server_ptr -> nx_rtsp_server_ip_ptr, &(rtsp_server_ptr -> nx_rtsp_server_client_list[i].nx_rtsp_client_socket),
+ "RTSP Client Control Socket", NX_RTSP_SERVER_TYPE_OF_SERVICE, NX_RTSP_SERVER_FRAGMENT_OPTION,
+ NX_RTSP_SERVER_TIME_TO_LIVE, NX_RTSP_SERVER_WINDOW_SIZE, NX_NULL,
+ _nx_rtsp_server_disconnect_present);
+
+ /* If no error is present, register the receive notify function. */
+ if (status == NX_SUCCESS)
+ {
+
+ /* Register the receive function. */
+ nx_tcp_socket_receive_notify(&(rtsp_server_ptr -> nx_rtsp_server_client_list[i].nx_rtsp_client_socket),
+ _nx_rtsp_server_request_present);
+ }
+ else
+ {
+ break;
+ }
+
+ /* Make sure each socket points to the RTSP server. */
+ rtsp_server_ptr -> nx_rtsp_server_client_list[i].nx_rtsp_client_socket.nx_tcp_socket_reserved_ptr = rtsp_server_ptr;
+ }
+
+ /* Determine if an error has occurred. */
+ if (status)
+ {
+
+ /* Loop to delete any created sockets. */
+ for (j = 0; j < i; j++)
+ {
+
+ /* Delete the RTSP socket. */
+ nx_tcp_socket_delete(&(rtsp_server_ptr -> nx_rtsp_server_client_list[j].nx_rtsp_client_socket));
+ }
+
+ /* Return an error. */
+ return(status);
+ }
+
+
+ /* Start listening on the RTSP socket. */
+ status = nx_tcp_server_socket_listen(rtsp_server_ptr -> nx_rtsp_server_ip_ptr, rtsp_server_ptr -> nx_rtsp_server_port,
+ &(rtsp_server_ptr -> nx_rtsp_server_client_list[0].nx_rtsp_client_socket),
+ NX_RTSP_SERVER_MAX_CLIENTS, _nx_rtsp_server_connect_present);
+
+ if (status)
+ {
+ return(status);
+ }
+
+ /* Start thread. */
+ tx_thread_resume(&rtsp_server_ptr -> nx_rtsp_server_thread);
+
+ /* Activate timer. */
+ tx_timer_activate(&rtsp_server_ptr -> nx_rtsp_server_timer);
+
+ rtsp_server_ptr -> nx_rtsp_server_started = NX_TRUE;
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtsp_server_stop PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in RTSP server stop function call. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_stop Stop the RTSP server */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtsp_server_stop(NX_RTSP_SERVER *rtsp_server_ptr)
+{
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((rtsp_server_ptr == NX_NULL) || (rtsp_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual RTSP server stop function. */
+ status = _nx_rtsp_server_stop(rtsp_server_ptr);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_stop PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function stops a previously started RTSP server. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* tx_thread_suspend Suspend server thread */
+/* tx_timer_deactivate Stop server timeout timer */
+/* nx_tcp_socket_disconnect Disconnect TCP socket */
+/* nx_tcp_server_socket_unaccept Clear accepted socket */
+/* nx_tcp_socket_delete Delete TCP socket */
+/* nx_tcp_server_socket_unlisten Stop listening on TCP socket */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtsp_server_stop(NX_RTSP_SERVER *rtsp_server_ptr)
+{
+UINT client_index;
+
+
+ /* Check if the server is started. */
+ if (rtsp_server_ptr -> nx_rtsp_server_started != NX_TRUE)
+ {
+ return(NX_RTSP_SERVER_NOT_STARTED);
+ }
+
+ /* Suspend thread. */
+ tx_thread_suspend(&(rtsp_server_ptr -> nx_rtsp_server_thread));
+
+ /* Deactivate the timer. */
+ tx_timer_deactivate(&(rtsp_server_ptr -> nx_rtsp_server_timer));
+
+ /* Walk through to close the sockets. */
+ for (client_index = 0; client_index < NX_RTSP_SERVER_MAX_CLIENTS; client_index++)
+ {
+
+ /* Disconnect the socket. */
+ nx_tcp_socket_disconnect(&(rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_socket), NX_NO_WAIT);
+
+ /* Unaccept the socket. */
+ nx_tcp_server_socket_unaccept(&(rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_socket));
+
+ /* Delete the socket. */
+ nx_tcp_socket_delete(&(rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_socket));
+
+ /* Check to see if a packet is queued up. */
+ if (rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_request_packet)
+ {
+
+ /* Yes, release it! */
+ nx_packet_release(rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_request_packet);
+ rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_request_packet = NX_NULL;
+ rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_request_bytes_total = 0;
+ }
+
+ /* Check to see if a packet is queued up. */
+ if (rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_response_packet)
+ {
+
+ /* Yes, release it! */
+ nx_packet_release(rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_response_packet);
+ rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_response_packet = NX_NULL;
+ }
+ }
+
+ /* Unlisten for the RTSP server port. */
+ nx_tcp_server_socket_unlisten(rtsp_server_ptr -> nx_rtsp_server_ip_ptr, rtsp_server_ptr -> nx_rtsp_server_port);
+
+ /* Clear the RTSP server started flag. */
+ rtsp_server_ptr -> nx_rtsp_server_started = NX_FALSE;
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtsp_server_sdp_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in SDP set function call. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_client_ptr Pointer to RTSP client */
+/* sdp_string Pointer to SDP string */
+/* sdp_length The length of the SDP string */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_sdp_set Set SDP string in response */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtsp_server_sdp_set(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *sdp_string, UINT sdp_length)
+{
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((rtsp_client_ptr == NX_NULL) || (sdp_string == NX_NULL) || (sdp_length == 0) ||
+ (rtsp_client_ptr -> nx_rtsp_client_server_ptr == NX_NULL) ||
+ (rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual SDP set function. */
+ status = _nx_rtsp_server_sdp_set(rtsp_client_ptr, sdp_string, sdp_length);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_sdp_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sets the SDP string to the response packet. This */
+/* function can only be called in DESCRIBE callback function. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_client_ptr Pointer to RTSP client */
+/* sdp_string Pointer to SDP string */
+/* sdp_length The length of the SDP string */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* nx_packet_data_append Append packet data */
+/* _nx_utility_uint_to_string Convert integer to string */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtsp_server_sdp_set(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *sdp_string, UINT sdp_length)
+{
+UINT status;
+CHAR temp_buffer[11];
+UINT temp_length;
+NX_PACKET *response_packet_ptr = rtsp_client_ptr -> nx_rtsp_client_response_packet;
+
+
+ /* Check if the packet is valid. */
+ if (!response_packet_ptr)
+ {
+ return(NX_RTSP_SERVER_NO_PACKET);
+ }
+
+ /* Check the request method. */
+ if ((!rtsp_client_ptr -> nx_rtsp_client_request_ptr) ||
+ (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_method != NX_RTSP_METHOD_DESCRIBE))
+ {
+ return(NX_RTSP_SERVER_INVALID_REQUEST);
+ }
+
+ /* Add "Content-Type" header. */
+ status = nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("Content-Type: "),
+ rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(NX_RTSP_SERVER_CONTENT_TYPE_SDP),
+ rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n"),
+ rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ /* Add "Content-Length" header. */
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("Content-Length: "),
+ rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string(sdp_length, 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length,
+ rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n\r\n"),
+ rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ /* Add sdp string. */
+ status += nx_packet_data_append(response_packet_ptr, sdp_string, sdp_length,
+ rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtsp_server_rtp_info_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in RTP-Info set function call. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_client_ptr Pointer to RTSP client */
+/* track_id The track ID of the media */
+/* track_id_len The length of the track ID */
+/* rtp_seq The RTP sequence number */
+/* rtp_time The RTP timestamp */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_rtp_info_set Set RTP-Info in response */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtsp_server_rtp_info_set(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *track_id, UINT track_id_len, UINT rtp_seq, UINT rtp_time)
+{
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((rtsp_client_ptr == NX_NULL) || (track_id == NX_NULL) || (track_id_len == 0) ||
+ (rtsp_client_ptr -> nx_rtsp_client_server_ptr == NX_NULL) ||
+ (rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual RTP-Info set function. */
+ status = _nx_rtsp_server_rtp_info_set(rtsp_client_ptr, track_id, track_id_len, rtp_seq, rtp_time);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_rtp_info_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sets the RTP-Info to the response packet. This */
+/* function can only be called in PLAY callback function. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_client_ptr Pointer to RTSP client */
+/* track_id The track ID of the media */
+/* track_id_len The length of the track ID */
+/* rtp_seq The RTP sequence number */
+/* rtp_time The RTP timestamp */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* nx_packet_data_append Append packet data */
+/* _nx_utility_uint_to_string Convert integer to string */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtsp_server_rtp_info_set(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *track_id, UINT track_id_len, UINT rtp_seq, UINT rtp_time)
+{
+UINT status;
+CHAR temp_buffer[11];
+UINT temp_length;
+NX_PACKET *response_packet_ptr = rtsp_client_ptr -> nx_rtsp_client_response_packet;
+
+
+ /* Check if the packet is valid. */
+ if (!response_packet_ptr)
+ {
+ return(NX_RTSP_SERVER_NO_PACKET);
+ }
+
+ /* Check the request method. */
+ if ((!rtsp_client_ptr -> nx_rtsp_client_request_ptr) ||
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_method != NX_RTSP_METHOD_PLAY)
+ {
+ return(NX_RTSP_SERVER_INVALID_REQUEST);
+ }
+
+ /* Add "RTP-Info" header. */
+ status = nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("url="),
+ rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr, rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_length,
+ rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("/"),
+ rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, track_id, track_id_len,
+ rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(";seq="),
+ rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string(rtp_seq, 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length,
+ rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(";rtptime="),
+ rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string(rtp_time, 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length,
+ rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(","),
+ rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtsp_server_range_npt_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in NPT set function call. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_client_ptr Pointer to RTSP client */
+/* npt_start The NPT start time in */
+/* milliseconds */
+/* npt_end The NPT end time in */
+/* milliseconds */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_range_npt_set Set NPT start and end time */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtsp_server_range_npt_set(NX_RTSP_CLIENT *rtsp_client_ptr, UINT npt_start, UINT npt_end)
+{
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((rtsp_client_ptr == NX_NULL) || (rtsp_client_ptr -> nx_rtsp_client_server_ptr == NX_NULL) ||
+ (rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual NPT set function. */
+ status = _nx_rtsp_server_range_npt_set(rtsp_client_ptr, npt_start, npt_end);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_range_npt_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sets the NPT start and end time in Range field. This */
+/* function can only be called in PLAY and PAUSE callback function. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_client_ptr Pointer to RTSP client */
+/* npt_start The NPT start time in */
+/* milliseconds */
+/* npt_end The NPT end time in */
+/* milliseconds */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtsp_server_range_npt_set(NX_RTSP_CLIENT *rtsp_client_ptr, UINT npt_start, UINT npt_end)
+{
+
+ /* Check the request method. */
+ if ((!rtsp_client_ptr -> nx_rtsp_client_request_ptr) ||
+ ((rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_method != NX_RTSP_METHOD_PLAY) &&
+ (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_method != NX_RTSP_METHOD_PAUSE)))
+ {
+ return(NX_RTSP_SERVER_INVALID_REQUEST);
+ }
+
+ /* Check start and end time. */
+ if (npt_end < npt_start)
+ {
+ return(NX_RTSP_SERVER_INVALID_PARAMETER);
+ }
+
+ /* Set the NPT start and end time in milliseconds. */
+ rtsp_client_ptr -> nx_rtsp_client_npt_start = npt_start;
+ rtsp_client_ptr -> nx_rtsp_client_npt_end = npt_end;
+
+ return(NX_SUCCESS);
+}
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtsp_server_error_response_send PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in error response send call. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_client_ptr Pointer to RTSP client */
+/* status_code The status code of response */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_error_response_send Send error response */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtsp_server_error_response_send(NX_RTSP_CLIENT *rtsp_client_ptr, UINT status_code)
+{
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((rtsp_client_ptr == NX_NULL) || (rtsp_client_ptr -> nx_rtsp_client_server_ptr == NX_NULL) ||
+ (rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual error response send function. */
+ status = _nx_rtsp_server_error_response_send(rtsp_client_ptr, status_code);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_error_response_send PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sends the error response packet. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_client_ptr Pointer to RTSP client */
+/* status_code The status code of response */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* nx_packet_release Release the packet */
+/* nx_packet_data_append Append packet data */
+/* _nx_utility_uint_to_string Convert integer to string */
+/* _nx_utility_string_length_check Check string length */
+/* nx_tcp_socket_send Send TCP packet */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtsp_server_error_response_send(NX_RTSP_CLIENT *rtsp_client_ptr, UINT status_code)
+{
+UINT status;
+UINT i;
+CHAR temp_buffer[11];
+UINT temp_length;
+NX_PACKET *response_packet_ptr = rtsp_client_ptr -> nx_rtsp_client_response_packet;
+NX_PACKET_POOL *pool_ptr = rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool;
+
+
+ if (!response_packet_ptr)
+ {
+ return(NX_RTSP_SERVER_NO_PACKET);
+ }
+
+ /* Loop to find the corresponding description. */
+ for (i = 0; nx_rtsp_server_response_description_table[i].nx_rtsp_response_code != NX_NULL; i++)
+ {
+ if (nx_rtsp_server_response_description_table[i].nx_rtsp_response_code == status_code)
+ {
+ break;
+ }
+ }
+
+ if (nx_rtsp_server_response_description_table[i].nx_rtsp_response_code == NX_NULL)
+ {
+ return(NX_RTSP_SERVER_INVALID_PARAMETER);
+ }
+
+#ifndef NX_DISABLE_PACKET_CHAIN
+ /* Reuse the response packet to append the error message.
+ If user has already appended data to this packet and there are packets chained,
+ remove and release the chained packets. */
+ if (response_packet_ptr -> nx_packet_next)
+ {
+ nx_packet_release(response_packet_ptr -> nx_packet_next);
+ response_packet_ptr -> nx_packet_next = NX_NULL;
+ response_packet_ptr -> nx_packet_last = NX_NULL;
+ }
+#endif /* NX_DISABLE_PACKET_CHAIN */
+
+ /* Reset the packet. */
+ response_packet_ptr -> nx_packet_append_ptr = response_packet_ptr -> nx_packet_prepend_ptr;
+ response_packet_ptr -> nx_packet_length = 0;
+
+ /* Add version. */
+ status = nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(NX_RTSP_VERSION_STRING),
+ pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, " ", 1, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ /* Add status code. */
+ temp_length = _nx_utility_uint_to_string(status_code, 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, " ", 1, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ _nx_utility_string_length_check(nx_rtsp_server_response_description_table[i].nx_rtsp_response_description, &temp_length, NX_MAX_STRING_LENGTH);
+ status += nx_packet_data_append(response_packet_ptr, nx_rtsp_server_response_description_table[i].nx_rtsp_response_description,
+ temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n"), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ /* Add "CSeq" header. */
+ status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, NX_RTSP_SERVER_STRING_WITH_SIZE("CSeq: "), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string(rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_sequence_number, 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n"), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ /* Add "Server" header. */
+ status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, NX_RTSP_SERVER_STRING_WITH_SIZE("Server: "), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_name,
+ rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_name_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n\r\n"), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ if (status == NX_SUCCESS)
+ {
+
+ /* Send the response message back. */
+ status = nx_tcp_socket_send(&rtsp_client_ptr -> nx_rtsp_client_socket, response_packet_ptr, NX_RTSP_SERVER_SEND_TIMEOUT);
+ }
+
+ /* Determine if the send was unsuccessful. */
+ if (status)
+ {
+
+ /* Release the packet. */
+ nx_packet_release(response_packet_ptr);
+ }
+
+ /* Clear the response packet pointer. */
+ rtsp_client_ptr -> nx_rtsp_client_response_packet = NX_NULL;
+
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtsp_server_keepalive_update PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in keepalive update function call. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_client_ptr Pointer to RTSP client */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_keepalive_update Update the timeout timer */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtsp_server_keepalive_update(NX_RTSP_CLIENT *rtsp_client_ptr)
+{
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((rtsp_client_ptr == NX_NULL) || (rtsp_client_ptr -> nx_rtsp_client_server_ptr == NX_NULL) ||
+ (rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual keep-alive update function. */
+ status = _nx_rtsp_server_keepalive_update(rtsp_client_ptr);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_keepalive_update PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function updates the timeout timer of the client. If RTP is */
+/* used for media transport, RTCP is used to show liveness of client. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_client_ptr Pointer to RTSP client */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtsp_server_keepalive_update(NX_RTSP_CLIENT *rtsp_client_ptr)
+{
+
+ /* Reset the client request activity timeout. */
+ if (rtsp_client_ptr -> nx_rtsp_client_request_activity_timeout)
+ {
+ rtsp_client_ptr -> nx_rtsp_client_request_activity_timeout = NX_RTSP_SERVER_ACTIVITY_TIMEOUT;
+ }
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtsp_server_describe_callback_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in DESCRIBE callback set. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* callback Callback of DESCRIBE request */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_describe_callback_set Set DESCRIBE callback */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtsp_server_describe_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
+ UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length))
+{
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((rtsp_server_ptr == NX_NULL) || (callback == NX_NULL) ||
+ (rtsp_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual DESCRIBE callback set function. */
+ status = _nx_rtsp_server_describe_callback_set(rtsp_server_ptr, callback);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_describe_callback_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function installs callback function for DESCRIBE request. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* callback Callback of DESCRIBE request */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtsp_server_describe_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
+ UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length))
+{
+
+ /* Set callback for DESCRIBE method. */
+ rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_describe_callback = callback;
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtsp_server_setup_callback_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in SETUP callback set. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* callback Callback of SETUP request */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_setup_callback_set Set SETUP callback */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtsp_server_setup_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
+ UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, NX_RTSP_TRANSPORT *transport_ptr))
+{
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((rtsp_server_ptr == NX_NULL) || (callback == NX_NULL) ||
+ (rtsp_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual SETUP callback set function. */
+ status = _nx_rtsp_server_setup_callback_set(rtsp_server_ptr, callback);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_setup_callback_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function installs callback function for SETUP request. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* callback Callback of SETUP request */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtsp_server_setup_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
+ UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, NX_RTSP_TRANSPORT *transport_ptr))
+{
+
+ /* Set callback for SETUP method. */
+ rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_setup_callback = callback;
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtsp_server_play_callback_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in PLAY callback set. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* callback Callback of PLAY request */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_play_callback_set Set PLAY callback */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtsp_server_play_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
+ UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length))
+{
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((rtsp_server_ptr == NX_NULL) || (callback == NX_NULL) ||
+ (rtsp_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual PLAY callback set function. */
+ status = _nx_rtsp_server_play_callback_set(rtsp_server_ptr, callback);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_play_callback_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function installs callback function for PLAY request. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* callback Callback of PLAY request */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtsp_server_play_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
+ UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length))
+{
+
+ /* Set callback for PLAY method. */
+ rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_play_callback = callback;
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtsp_server_teardown_callback_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in TEARDOWN callback set. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* callback Callback of TEARDOWN request */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_teardown_callback_set Set TEARDOWN callback */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtsp_server_teardown_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
+ UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length))
+{
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((rtsp_server_ptr == NX_NULL) || (callback == NX_NULL) ||
+ (rtsp_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual TEARDOWN callback set function. */
+ status = _nx_rtsp_server_teardown_callback_set(rtsp_server_ptr, callback);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_teardown_callback_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function installs callback function for TEARDOWN request. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* callback Callback of TEARDOWN request */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtsp_server_teardown_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
+ UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length))
+{
+
+ /* Set callback for TEARDOWN method. */
+ rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_teardown_callback = callback;
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtsp_server_pause_callback_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in PAUSE callback set. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* callback Callback of PAUSE request */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_pause_callback_set Set PAUSE callback */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtsp_server_pause_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
+ UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length))
+{
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((rtsp_server_ptr == NX_NULL) || (callback == NX_NULL) ||
+ (rtsp_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual PAUSE callback set function. */
+ status = _nx_rtsp_server_pause_callback_set(rtsp_server_ptr, callback);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_pause_callback_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function installs callback function for PAUSE request. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* callback Callback of PAUSE request */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtsp_server_pause_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
+ UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length))
+{
+
+ /* Set callback for PAUSE method. */
+ rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_pause_callback = callback;
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nxe_rtsp_server_set_parameter_callback_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function checks for errors in SET_PARAMETER callback set. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* callback Callback of SET_PARAMETER */
+/* request */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_set_parameter_callback_set */
+/* Set SET_PARAMETER callback */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nxe_rtsp_server_set_parameter_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
+ UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *parameter_ptr, ULONG parameter_length))
+{
+UINT status;
+
+
+ /* Check for invalid input pointers. */
+ if ((rtsp_server_ptr == NX_NULL) || (callback == NX_NULL) ||
+ (rtsp_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
+ {
+ return(NX_PTR_ERROR);
+ }
+
+ /* Call actual SET_PARAMETER callback set function. */
+ status = _nx_rtsp_server_set_parameter_callback_set(rtsp_server_ptr, callback);
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_set_parameter_callback_set PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function installs callback function for SET_PARAMETER request. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* callback Callback of SET_PARAMETER */
+/* request */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+UINT _nx_rtsp_server_set_parameter_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
+ UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *parameter_ptr, ULONG parameter_length))
+{
+
+ /* Set callback for SET_PARAMETER method. */
+ rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_set_parameter_callback = callback;
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_thread_entry PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function handles events of RTSP server thread. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_address Pointer to RTSP server */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* tx_event_flags_get Get event flags */
+/* _nx_rtsp_server_connect_process Process connect event */
+/* _nx_rtsp_server_request_process Process request event */
+/* _nx_rtsp_server_disconnect_process Process disconnect event */
+/* _nx_rtsp_server_timeout_process Process timeout event */
+/* */
+/* CALLED BY */
+/* */
+/* ThreadX */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+static VOID _nx_rtsp_server_thread_entry(ULONG rtsp_server_address)
+{
+NX_RTSP_SERVER *rtsp_server_ptr;
+UINT status;
+ULONG events;
+
+
+ /* Setup the server pointer. */
+ rtsp_server_ptr = (NX_RTSP_SERVER *)rtsp_server_address;
+
+ /* Loop to process RTSP Server requests. */
+ while (1)
+ {
+
+ /* Wait for an RTSP client activity. */
+ status = tx_event_flags_get(&(rtsp_server_ptr -> nx_rtsp_server_event_flags), NX_RTSP_SERVER_ALL_EVENTS, TX_OR_CLEAR, &events, TX_WAIT_FOREVER);
+
+ /* Check the return status. */
+ if (status)
+ {
+
+ /* If an error occurs, simply continue the loop. */
+ continue;
+ }
+
+ /* Otherwise, an event is present. Process according to the event. */
+
+ /* Check for a client connection event. */
+ if (events & NX_RTSP_SERVER_CONNECT_EVENT)
+ {
+
+ /* Call the connect process. */
+ _nx_rtsp_server_connect_process(rtsp_server_ptr);
+ }
+
+ /* Check for a client request event. */
+ if (events & NX_RTSP_SERVER_REQUEST_EVENT)
+ {
+
+ /* Call the request process. */
+ _nx_rtsp_server_request_process(rtsp_server_ptr);
+ }
+
+ /* Check for a client disconnect event. */
+ if (events & NX_RTSP_SERVER_DISCONNECT_EVENT)
+ {
+
+ /* Call the disconnect process. */
+ _nx_rtsp_server_disconnect_process(rtsp_server_ptr);
+ }
+
+ /* Check for a client activity timeout event. */
+ if (events & NX_RTSP_SERVER_TIMEOUT_EVENT)
+ {
+
+ /* Call the activity timeout process. */
+ _nx_rtsp_server_timeout_process(rtsp_server_ptr);
+ }
+ }
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_request_receive PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function receives the entire request from client including the */
+/* request header and message body. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* rtsp_client_ptr Pointer to RTSP client */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* nx_tcp_socket_receive Receive TCP packet */
+/* _nx_rtsp_server_memicmp Compare two strings */
+/* nx_packet_data_append Append packet data */
+/* nx_packet_release Release the packet */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtsp_server_request_process */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+static UINT _nx_rtsp_server_request_receive(NX_RTSP_SERVER *rtsp_server_ptr, NX_RTSP_CLIENT *rtsp_client_ptr)
+{
+NX_PACKET *head_packet_ptr = rtsp_client_ptr -> nx_rtsp_client_request_packet;
+NX_PACKET *new_packet_ptr;
+NX_PACKET *work_ptr;
+NX_PACKET *tmp_ptr;
+UCHAR *buffer_ptr;
+UINT crlf_found = 0;
+UINT content_length_found = 0;
+UINT content_length = 0;
+UINT header_length = 0;
+UINT status = NX_SUCCESS;
+
+
+ if (head_packet_ptr == NX_NULL)
+ {
+
+ /* Receive a request from RTSP client. */
+ status = nx_tcp_socket_receive(&(rtsp_client_ptr -> nx_rtsp_client_socket), &head_packet_ptr, NX_NO_WAIT);
+
+ /* Check the return status. */
+ if (status == NX_NO_PACKET)
+ {
+ return(NX_IN_PROGRESS);
+ }
+ else if (status != NX_SUCCESS)
+ {
+
+ /* Return an error condition. */
+ return(status);
+ }
+
+ rtsp_client_ptr -> nx_rtsp_client_request_packet = head_packet_ptr;
+ }
+
+ work_ptr = head_packet_ptr;
+
+ /* Build a pointer to the buffer area. */
+ buffer_ptr = work_ptr -> nx_packet_prepend_ptr;
+
+ while (status == NX_SUCCESS)
+ {
+
+ /* nx_rtsp_client_request_bytes_total is not zero means the receiving of request header is complete. */
+ if (rtsp_client_ptr -> nx_rtsp_client_request_bytes_total == 0)
+ {
+
+ /* See if there is a blank line present in the buffer. */
+ /* Search the buffer for a cr/lf pair. */
+ while ((buffer_ptr < work_ptr -> nx_packet_append_ptr) &&
+ (crlf_found < 4))
+ {
+ if (!(crlf_found & 1) && (*buffer_ptr == '\r'))
+ {
+
+ /* Found CR. */
+ crlf_found++;
+ }
+ else if ((crlf_found & 1) && (*buffer_ptr == '\n'))
+ {
+
+ /* Found LF. */
+ crlf_found++;
+ }
+ else
+ {
+
+ /* Reset the CRLF marker. */
+ crlf_found = 0;
+ }
+
+ if ((content_length_found == NX_FALSE) && ((buffer_ptr + 14) < work_ptr -> nx_packet_append_ptr) &&
+ (_nx_rtsp_server_memicmp(buffer_ptr, 15, NX_RTSP_SERVER_STRING_WITH_SIZE("Content-length:")) == NX_SUCCESS))
+ {
+
+ /* Set the found flag. */
+ content_length_found = NX_TRUE;
+ buffer_ptr += 15;
+ header_length += 15;
+
+ /* Now skip over white space. */
+ while ((buffer_ptr < work_ptr -> nx_packet_append_ptr) && (*buffer_ptr == ' '))
+ {
+ buffer_ptr++;
+ header_length++;
+ }
+
+ /* Now convert the length into a numeric value. */
+ while ((buffer_ptr < work_ptr -> nx_packet_append_ptr) && (*buffer_ptr >= '0') && (*buffer_ptr <= '9'))
+ {
+
+ /* Update the content length. */
+ content_length = content_length * 10;
+ content_length = content_length + (UINT)(*buffer_ptr) - '0';
+
+ /* Move the buffer pointer forward. */
+ buffer_ptr++;
+ header_length++;
+ }
+ }
+
+ /* Move the buffer pointer up. */
+ buffer_ptr++;
+ header_length++;
+ }
+
+ if (crlf_found == 4)
+ {
+
+ /* Store content length and total bytes need to be received. */
+ rtsp_client_ptr -> nx_rtsp_client_request_content_length = content_length;
+ rtsp_client_ptr -> nx_rtsp_client_request_bytes_total = content_length + header_length;
+
+ /* Yes, we have found the end of the HTTP request header. Continue to receive content */
+ continue;
+ }
+
+#ifndef NX_DISABLE_PACKET_CHAIN
+
+ /* Determine if the packet has already overflowed into another packet. */
+ if (work_ptr -> nx_packet_next != NX_NULL)
+ {
+
+ /* Get the next packet in the chain. */
+ work_ptr = work_ptr -> nx_packet_next;
+ buffer_ptr = work_ptr -> nx_packet_prepend_ptr;
+
+ continue;
+ }
+#endif /* NX_DISABLE_PACKET_CHAIN */
+ }
+ else
+ {
+
+ /* Check if we have received the total bytes of the request. */
+ if (head_packet_ptr -> nx_packet_length == rtsp_client_ptr -> nx_rtsp_client_request_bytes_total)
+ {
+ break;
+ }
+ else if (head_packet_ptr -> nx_packet_length > rtsp_client_ptr -> nx_rtsp_client_request_bytes_total)
+ {
+ status = NX_INVALID_PACKET;
+ break;
+ }
+ }
+
+ /* Receive another packet from the RTSP Client. */
+ status = nx_tcp_socket_receive(&(rtsp_client_ptr -> nx_rtsp_client_socket), &new_packet_ptr, NX_NO_WAIT);
+
+ /* Check the return status. */
+ if (status == NX_NO_PACKET)
+ {
+ return(NX_IN_PROGRESS);
+ }
+ else if (status != NX_SUCCESS)
+ {
+ break;
+ }
+
+ /* Successfully received another packet. Its contents now need to be placed in the head packet. */
+ tmp_ptr = new_packet_ptr;
+
+#ifndef NX_DISABLE_PACKET_CHAIN
+ while (tmp_ptr)
+#endif /* NX_DISABLE_PACKET_CHAIN */
+ {
+
+ /* Copy the contents of the current packet into the head packet. */
+ status = nx_packet_data_append(head_packet_ptr, (VOID *) tmp_ptr -> nx_packet_prepend_ptr,
+ (ULONG)(tmp_ptr -> nx_packet_append_ptr - tmp_ptr -> nx_packet_prepend_ptr),
+ rtsp_server_ptr -> nx_rtsp_server_packet_pool, NX_NO_WAIT);
+
+#ifndef NX_DISABLE_PACKET_CHAIN
+
+ /* Determine if an error occurred. */
+ if (status != NX_SUCCESS)
+ {
+ break;
+ }
+ else
+ {
+ tmp_ptr = tmp_ptr -> nx_packet_next;
+ }
+#endif /* NX_DISABLE_PACKET_CHAIN */
+ }
+
+ /* Release the new packet. */
+ nx_packet_release(new_packet_ptr);
+
+ /* If we haven't received all the request header, and haven't found the content length field. */
+ if ((rtsp_client_ptr -> nx_rtsp_client_request_bytes_total == 0) && (content_length_found == NX_FALSE))
+ {
+
+ /* Search again from the start of the packet. */
+ work_ptr = head_packet_ptr;
+
+ /* Build a pointer to the buffer area. */
+ buffer_ptr = work_ptr -> nx_packet_prepend_ptr;
+
+ /* Reset the header length. */
+ header_length = 0;
+ }
+ }
+
+ if (status)
+ {
+
+ /* Release the packet. */
+ nx_packet_release(head_packet_ptr);
+ rtsp_client_ptr -> nx_rtsp_client_request_packet = NX_NULL;
+ rtsp_client_ptr -> nx_rtsp_client_request_bytes_total = 0;
+ }
+
+ /* Return status. */
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_request_parse PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function parses incoming request packet. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_client_ptr Pointer to RTSP client */
+/* rtsp_client_request_ptr Pointer to request structure */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* memset Reset memory */
+/* _nx_rtsp_server_request_line_parse Parse request line */
+/* _nx_rtsp_server_request_header_parse Parse request header */
+/* nx_packet_allocate Allocate a packet */
+/* _nx_rtsp_server_error_response_send Send error response */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtsp_server_request_process */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+static UINT _nx_rtsp_server_request_parse(NX_RTSP_CLIENT *rtsp_client_ptr, NX_RTSP_CLIENT_REQUEST *rtsp_client_request_ptr)
+{
+UINT status;
+UCHAR *rtsp_client_request_buf;
+UCHAR *rtsp_client_request_buf_ptr;
+UCHAR *rtsp_client_request_buf_end;
+NX_PACKET *rtsp_client_request_packet = rtsp_client_ptr -> nx_rtsp_client_request_packet;
+
+
+#ifndef NX_DISABLE_PACKET_CHAIN
+
+ /* Check if the packet is chained. Chained packet isn't supported now. */
+ if (rtsp_client_request_packet -> nx_packet_next)
+ {
+ return(NX_INVALID_PACKET);
+ }
+#endif /* NX_DISABLE_PACKET_CHAIN */
+
+ /* Reset the request info. */
+ memset(rtsp_client_request_ptr, 0, sizeof(NX_RTSP_CLIENT_REQUEST));
+
+ /* Set the buffer pointer. */
+ rtsp_client_request_buf = rtsp_client_request_packet -> nx_packet_prepend_ptr;
+ rtsp_client_request_buf_end = rtsp_client_request_packet -> nx_packet_append_ptr - rtsp_client_ptr -> nx_rtsp_client_request_content_length;
+ rtsp_client_request_buf_ptr = rtsp_client_request_buf;
+
+ /* Parse the request line. */
+ status = _nx_rtsp_server_request_line_parse(rtsp_client_request_ptr, &rtsp_client_request_buf_ptr, rtsp_client_request_buf_end);
+
+ if (status == NX_SUCCESS)
+ {
+
+ /* Continue parse headers. */
+ while (rtsp_client_request_buf_ptr < rtsp_client_request_buf_end)
+ {
+
+ /* Parse the headers. */
+ status = _nx_rtsp_server_request_header_parse(rtsp_client_ptr, rtsp_client_request_ptr,
+ &rtsp_client_request_buf_ptr, rtsp_client_request_buf_end);
+
+ if (status)
+ {
+ break;
+ }
+ }
+ }
+
+ if (status)
+ {
+
+ /* Send error response packet. */
+ if (nx_packet_allocate(rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool,
+ &(rtsp_client_ptr -> nx_rtsp_client_response_packet),
+ NX_TCP_PACKET, NX_RTSP_SERVER_PACKET_TIMEOUT) == NX_SUCCESS)
+ {
+ _nx_rtsp_server_error_response_send(rtsp_client_ptr, status);
+ }
+ else
+ {
+
+ /* There is nothing we can do here. Ideally log this error event. */
+ rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_allocation_errors++;
+ }
+ }
+
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_request_line_parse PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function parses request method, URI and version. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_client_request_ptr Pointer to request structure */
+/* request_buffer Start of request buffer */
+/* request_buffer_end End to request buffer */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* memcmp Compare two strings */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtsp_server_request_parse */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+static UINT _nx_rtsp_server_request_line_parse(NX_RTSP_CLIENT_REQUEST *rtsp_client_request_ptr, UCHAR **request_buffer, UCHAR *request_buffer_end)
+{
+UCHAR *request_buffer_ptr;
+UCHAR *temp_ptr;
+UINT temp_length = 0;
+
+
+ /* Set the buffer pointer. */
+ request_buffer_ptr = *request_buffer;
+
+ /* We assume the client request is well formatted. */
+ /* Parse the request line. */
+
+ /* Trim the spaces before the method. */
+ while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr == ' '))
+ {
+ request_buffer_ptr++;
+ }
+
+ /* Return error if no more data. */
+ if (request_buffer_ptr == request_buffer_end)
+ {
+ return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
+ }
+
+ /* Set the method pointer. */
+ temp_ptr = request_buffer_ptr;
+
+ /* Find the ending point of the method. */
+ while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr != ' ') &&
+ (*request_buffer_ptr != '\r') && (*request_buffer_ptr != '\n'))
+ {
+ request_buffer_ptr++;
+ }
+
+ /* Must has space before URI. */
+ if ((request_buffer_ptr == request_buffer_end) || (*request_buffer_ptr != ' '))
+ {
+ return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
+ }
+
+ /* Calculate method length. */
+ temp_length = (UINT)(request_buffer_ptr - temp_ptr);
+
+ /* The method is case-sensitive. */
+ if ((temp_length == NX_RTSP_SERVER_STRING_SIZE("OPTIONS")) && (memcmp(temp_ptr, "OPTIONS", temp_length) == 0))
+ {
+ rtsp_client_request_ptr -> nx_rtsp_client_request_method = NX_RTSP_METHOD_OPTIONS;
+ }
+ else if ((temp_length == NX_RTSP_SERVER_STRING_SIZE("DESCRIBE")) && (memcmp(temp_ptr, "DESCRIBE", temp_length) == 0))
+ {
+ rtsp_client_request_ptr -> nx_rtsp_client_request_method = NX_RTSP_METHOD_DESCRIBE;
+ }
+ else if ((temp_length == NX_RTSP_SERVER_STRING_SIZE("SETUP")) && (memcmp(temp_ptr, "SETUP", temp_length) == 0))
+ {
+ rtsp_client_request_ptr -> nx_rtsp_client_request_method = NX_RTSP_METHOD_SETUP;
+ }
+ else if ((temp_length == NX_RTSP_SERVER_STRING_SIZE("PLAY")) && (memcmp(temp_ptr, "PLAY", temp_length) == 0))
+ {
+ rtsp_client_request_ptr -> nx_rtsp_client_request_method = NX_RTSP_METHOD_PLAY;
+ }
+ else if ((temp_length == NX_RTSP_SERVER_STRING_SIZE("PAUSE")) && (memcmp(temp_ptr, "PAUSE", temp_length) == 0))
+ {
+ rtsp_client_request_ptr -> nx_rtsp_client_request_method = NX_RTSP_METHOD_PAUSE;
+ }
+ else if ((temp_length == NX_RTSP_SERVER_STRING_SIZE("TEARDOWN")) && (memcmp(temp_ptr, "TEARDOWN", temp_length) == 0))
+ {
+ rtsp_client_request_ptr -> nx_rtsp_client_request_method = NX_RTSP_METHOD_TEARDOWN;
+ }
+ else if ((temp_length == NX_RTSP_SERVER_STRING_SIZE("SET_PARAMETER")) && (memcmp(temp_ptr, "SET_PARAMETER", temp_length) == 0))
+ {
+ rtsp_client_request_ptr -> nx_rtsp_client_request_method = NX_RTSP_METHOD_SET_PARAMETER;
+ }
+ else
+ {
+ rtsp_client_request_ptr -> nx_rtsp_client_request_method = NX_RTSP_METHOD_NOT_SUPPORT;
+
+ return(NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED);
+ }
+
+ /* Trim the spaces. */
+ while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr == ' '))
+ {
+ request_buffer_ptr++;
+ }
+
+ /* Return error if no more data. */
+ if (request_buffer_ptr == request_buffer_end)
+ {
+ return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
+ }
+
+ /* Set the URI pointer. */
+ rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr = request_buffer_ptr;
+
+ /* Find the ending point of the URI. */
+ while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr != ' ') &&
+ (*request_buffer_ptr != '\r') && (*request_buffer_ptr != '\n'))
+ {
+ request_buffer_ptr++;
+ }
+
+ /* Must has space before version. */
+ if ((request_buffer_ptr == request_buffer_end) || (*request_buffer_ptr != ' '))
+ {
+ return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
+ }
+
+ /* Calculate the URI length. */
+ rtsp_client_request_ptr -> nx_rtsp_client_request_uri_length = (UINT)(request_buffer_ptr - rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr);
+
+ /* Trim the spaces. */
+ while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr == ' '))
+ {
+ request_buffer_ptr++;
+ }
+
+ /* Return error if no more data. */
+ if (request_buffer_ptr == request_buffer_end)
+ {
+ return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
+ }
+
+ /* Set the version pointer. */
+ temp_ptr = request_buffer_ptr;
+
+ /* Find the ending point of the version. */
+ while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr != ' ') &&
+ (*request_buffer_ptr != '\r') && (*request_buffer_ptr != '\n'))
+ {
+ request_buffer_ptr++;
+ }
+
+ /* Calculate version length. */
+ temp_length = (UINT)(request_buffer_ptr - temp_ptr);
+
+ /* Check version. */
+ if ((temp_length != (sizeof(NX_RTSP_VERSION_STRING) - 1)) ||
+ memcmp(temp_ptr, NX_RTSP_VERSION_STRING, temp_length) != 0)
+ {
+ return(NX_RTSP_STATUS_CODE_RTSP_VERSION_NOT_SUPPORTED);
+ }
+
+ /* Trim the spaces. */
+ while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr == ' '))
+ {
+ request_buffer_ptr++;
+ }
+
+ /* Move to next line. */
+ /* RFC: https://www.rfc-editor.org/rfc/rfc2326#section-4
+ Lines are terminated by CRLF, but receivers should be prepared
+ to also interpret CR and LF by themselves as line terminators. */
+ if (((request_buffer_ptr + 1) < request_buffer_end) &&
+ (*request_buffer_ptr == '\r') && (*(request_buffer_ptr + 1) == '\n'))
+ {
+ request_buffer_ptr += 2;
+ }
+ else if ((request_buffer_ptr < request_buffer_end) &&
+ ((*request_buffer_ptr == '\r') || (*request_buffer_ptr == '\n')))
+ {
+ request_buffer_ptr++;
+ }
+ else
+ {
+ return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
+ }
+
+ *request_buffer = request_buffer_ptr;
+
+ /* Terminate the URI string. */
+ *(rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr + rtsp_client_request_ptr -> nx_rtsp_client_request_uri_length) = NX_NULL;
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_request_header_parse PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function parses headers in request packet. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_client_ptr Pointer to RTSP client */
+/* rtsp_client_request_ptr Pointer to request structure */
+/* request_buffer Start of request buffer */
+/* request_buffer_end End to request buffer */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_memicmp Compare two strings */
+/* _nx_utility_string_to_uint Convert string to integer */
+/* _nx_rtsp_server_strstr Search substring */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtsp_server_request_parse */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+static UINT _nx_rtsp_server_request_header_parse(NX_RTSP_CLIENT *rtsp_client_ptr, NX_RTSP_CLIENT_REQUEST *rtsp_client_request_ptr, UCHAR **request_buffer, UCHAR *request_buffer_end)
+{
+UCHAR *request_buffer_ptr;
+UCHAR *field_name_ptr;
+UCHAR *field_value_ptr;
+UINT field_name_length = 0;
+UINT field_value_length = 0;
+UINT port_length = 0;
+UINT status;
+NXD_ADDRESS *receiver_ip_address;
+
+
+ /* Set the buffer pointer. */
+ request_buffer_ptr = *request_buffer;
+
+ /* We assume the client request is well formatted. */
+ /* Parse a header line. */
+
+ /* Trim the spaces. */
+ while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr == ' '))
+ {
+ request_buffer_ptr++;
+ }
+
+ if (request_buffer_ptr == request_buffer_end)
+ {
+
+ /* Ignore empty line */
+ return(NX_SUCCESS);
+ }
+
+ /* Set the pointer of field name. */
+ field_name_ptr = request_buffer_ptr;
+
+ /* Find the ending point of the header name. */
+ while ((request_buffer_ptr < request_buffer_end) &&
+ (*request_buffer_ptr != ':') && (*request_buffer_ptr != ' ') &&
+ (*request_buffer_ptr != '\r') && (*request_buffer_ptr != '\n'))
+ {
+ request_buffer_ptr++;
+ }
+
+ /* Calculate the length of the field name. */
+ field_name_length = (UINT)(request_buffer_ptr - field_name_ptr);
+
+ if (field_name_length)
+ {
+
+ /* Trim the colon and spaces. */
+ while ((request_buffer_ptr < request_buffer_end) &&
+ ((*request_buffer_ptr == ':') || (*request_buffer_ptr == ' ')))
+ {
+ request_buffer_ptr++;
+ }
+
+ /* Set the pointer of the field value. */
+ field_value_ptr = request_buffer_ptr;
+
+ /* Find the end of the field value. */
+ while ((request_buffer_ptr < request_buffer_end) &&
+ (*request_buffer_ptr != '\r') && (*request_buffer_ptr != '\n'))
+ {
+ request_buffer_ptr++;
+ }
+
+ /* Calculate the length of the field value. */
+ field_value_length = (UINT)(request_buffer_ptr - field_value_ptr);
+
+ if (_nx_rtsp_server_memicmp(field_name_ptr, field_name_length, NX_RTSP_SERVER_STRING_WITH_SIZE("cseq")) == NX_SUCCESS)
+ {
+
+ /* Parse CSeq. */
+
+ /* Convert string to integer. */
+ status = _nx_utility_string_to_uint((CHAR *)field_value_ptr, field_value_length, &(rtsp_client_request_ptr -> nx_rtsp_client_request_sequence_number));
+ if (status)
+ {
+ return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
+ }
+ }
+ else if (_nx_rtsp_server_memicmp(field_name_ptr, field_name_length, NX_RTSP_SERVER_STRING_WITH_SIZE("range")) == NX_SUCCESS)
+ {
+
+ /* Parse Range. */
+
+ /* Set the range pointer and length. */
+ rtsp_client_request_ptr -> nx_rtsp_client_request_range_ptr = field_value_ptr;
+ rtsp_client_request_ptr -> nx_rtsp_client_request_range_length = field_value_length;
+ }
+ else if (_nx_rtsp_server_memicmp(field_name_ptr, field_name_length, NX_RTSP_SERVER_STRING_WITH_SIZE("session")) == NX_SUCCESS)
+ {
+
+ /* Parse Session. */
+
+ /* Convert string to integer. */
+ status = _nx_utility_string_to_uint((CHAR *)field_value_ptr, field_value_length, (UINT *)&(rtsp_client_request_ptr -> nx_rtsp_client_request_session_id));
+ if (status)
+ {
+ return(status);
+ }
+ }
+ else if (_nx_rtsp_server_memicmp(field_name_ptr, field_name_length, NX_RTSP_SERVER_STRING_WITH_SIZE("transport")) == NX_SUCCESS)
+ {
+
+ /* Parse Transport. */
+
+ /* RTP/AVP/TCP is not supported. https://www.rfc-editor.org/rfc/rfc2326#section-10.4. */
+ if (_nx_rtsp_server_strstr(field_value_ptr, field_value_length, NX_RTSP_SERVER_STRING_WITH_SIZE("RTP/AVP/TCP")))
+ {
+ rtsp_client_request_ptr -> nx_rtsp_client_request_transport.transport_type = NX_RTSP_TRANSPORT_TYPE_TCP;
+ return(NX_RTSP_STATUS_CODE_UNSUPPORTED_TRANSPORT);
+ }
+ else
+ {
+ rtsp_client_request_ptr -> nx_rtsp_client_request_transport.transport_type = NX_RTSP_TRANSPORT_TYPE_UDP;
+ }
+
+ receiver_ip_address = &(rtsp_client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_connect_ip);
+
+ /* Check multicast/unicast field. */
+ if (_nx_rtsp_server_strstr(field_value_ptr, field_value_length, NX_RTSP_SERVER_STRING_WITH_SIZE("unicast")))
+ {
+
+ /* For unicast mode, set the client IP address and return to user. */
+ rtsp_client_request_ptr -> nx_rtsp_client_request_transport.transport_mode = NX_RTSP_TRANSPORT_MODE_UNICAST;
+
+ if (receiver_ip_address -> nxd_ip_version == NX_IP_VERSION_V4)
+ {
+#ifndef NX_DISABLE_IPV4
+ /* Set client IP address. */
+ rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
+ rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_ip_address.nxd_ip_address.v4 = receiver_ip_address -> nxd_ip_address.v4;
+
+ /* Set default server IP address. */
+ rtsp_client_request_ptr -> nx_rtsp_client_request_transport.server_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
+ rtsp_client_request_ptr -> nx_rtsp_client_request_transport.server_ip_address.nxd_ip_address.v4 = rtsp_client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_connect_interface -> nx_interface_ip_address;
+
+ /* Record the transport ip interface in order to know where the packet is from. */
+ rtsp_client_request_ptr -> nx_rtsp_client_request_transport.interface_index = rtsp_client_ptr -> nx_rtsp_client_request_packet -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_index;
+#else
+ return(NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED);
+#endif /* NX_DISABLE_IPV4 */
+ }
+ else if (receiver_ip_address -> nxd_ip_version == NX_IP_VERSION_V6)
+ {
+#ifdef FEATURE_NX_IPV6
+ /* Set client IP address. */
+ rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
+ COPY_IPV6_ADDRESS(receiver_ip_address -> nxd_ip_address.v6, rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_ip_address.nxd_ip_address.v6);
+
+ /* Set default server IP address. */
+ rtsp_client_request_ptr -> nx_rtsp_client_request_transport.server_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
+ COPY_IPV6_ADDRESS(rtsp_client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_ipv6_addr -> nxd_ipv6_address,
+ rtsp_client_request_ptr -> nx_rtsp_client_request_transport.server_ip_address.nxd_ip_address.v6);
+
+ /* Record the transport ip interface in order to know where the packet is from. */
+ rtsp_client_request_ptr -> nx_rtsp_client_request_transport.interface_index = rtsp_client_ptr -> nx_rtsp_client_request_packet -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached -> nx_interface_index;
+#else
+ return(NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED);
+#endif /* FEATURE_NX_IPV6 */
+ }
+ else
+ {
+ return(NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED);
+ }
+
+ request_buffer_ptr = _nx_rtsp_server_strstr(field_value_ptr, field_value_length, NX_RTSP_SERVER_STRING_WITH_SIZE("client_port"));
+ port_length = NX_RTSP_SERVER_STRING_SIZE("client_port");
+ }
+ else
+ {
+
+ /* FIXME: Support that client chooses multicast address. Get destination field and convert to IP address. */
+ if (_nx_rtsp_server_strstr(field_value_ptr, field_value_length, NX_RTSP_SERVER_STRING_WITH_SIZE("destination")) != NX_NULL)
+ {
+ rtsp_client_request_ptr -> nx_rtsp_client_request_transport.transport_mode = NX_RTSP_TRANSPORT_MODE_MULTICAST_CLIENT;
+ return(NX_RTSP_STATUS_CODE_UNSUPPORTED_TRANSPORT);
+ }
+
+ /* Set multicast mode and server will choose multicast address. */
+ rtsp_client_request_ptr -> nx_rtsp_client_request_transport.transport_mode = NX_RTSP_TRANSPORT_MODE_MULTICAST_SERVER;
+ request_buffer_ptr = _nx_rtsp_server_strstr(field_value_ptr, field_value_length, NX_RTSP_SERVER_STRING_WITH_SIZE("port"));
+ port_length = NX_RTSP_SERVER_STRING_SIZE("port");
+ }
+
+ /* Get client port pair. */
+ if (request_buffer_ptr)
+ {
+
+ /* Find the port value. */
+ request_buffer_ptr = request_buffer_ptr + port_length;
+ while ((request_buffer_ptr < request_buffer_end) &&
+ ((*request_buffer_ptr == ' ') || (*request_buffer_ptr == '=')))
+ {
+ request_buffer_ptr++;
+ }
+
+ /* Get pointer of the RTP port. */
+ field_value_ptr = request_buffer_ptr;
+
+ while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr != '-') &&
+ (*request_buffer_ptr != '\r') && (*request_buffer_ptr != '\n'))
+ {
+ request_buffer_ptr++;
+ }
+
+ /* Check the format. */
+ if (*request_buffer_ptr != '-')
+ {
+ return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
+ }
+
+ /* Calculate the length of the RTP port. */
+ field_value_length = (UINT)(request_buffer_ptr - field_value_ptr);
+
+ /* Convert string to integer. */
+ status = _nx_utility_string_to_uint((CHAR *)field_value_ptr, field_value_length, (UINT *)&(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_rtp_port));
+ if (status)
+ {
+ return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
+ }
+
+ /* Get pointer of the RTCP port. */
+ request_buffer_ptr++;
+ field_value_ptr = request_buffer_ptr;
+
+ while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr != ';') &&
+ (*request_buffer_ptr != '\r') && (*request_buffer_ptr != '\n'))
+ {
+ request_buffer_ptr++;
+ }
+
+ /* Calculate the length of the RTCP port. */
+ field_value_length = (UINT)(request_buffer_ptr - field_value_ptr);
+
+ /* Convert string to integer. */
+ status = _nx_utility_string_to_uint((CHAR *)field_value_ptr, field_value_length, (UINT *)&(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_rtcp_port));
+ if (status)
+ {
+ return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
+ }
+ }
+ else
+ {
+
+ /* If no client port, move to the end of transport field. */
+ request_buffer_ptr = field_value_ptr + field_value_length;
+ }
+ }
+ }
+
+ /* Move to next line. */
+ /* RFC: https://www.rfc-editor.org/rfc/rfc2326#section-4
+ Lines are terminated by CRLF, but receivers should be prepared
+ to also interpret CR and LF by themselves as line terminators. */
+ if (((request_buffer_ptr + 1) < request_buffer_end) &&
+ (*request_buffer_ptr == '\r') && (*(request_buffer_ptr + 1) == '\n'))
+ {
+
+ /* Terminate the header line. */
+ *request_buffer_ptr = NX_NULL;
+ request_buffer_ptr += 2;
+ }
+ else if ((request_buffer_ptr < request_buffer_end) &&
+ ((*request_buffer_ptr == '\r') || (*request_buffer_ptr == '\n')))
+ {
+
+ /* Terminate the header line. */
+ *request_buffer_ptr = NX_NULL;
+ request_buffer_ptr++;
+ }
+ else
+ {
+ return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
+ }
+
+ *request_buffer = request_buffer_ptr;
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_memicmp PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function compares two pieces of memory case insensitive. */
+/* */
+/* INPUT */
+/* */
+/* src Pointer to source */
+/* src_length Length of source */
+/* dest Pointer to destination */
+/* dest_length Length of destination */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtsp_server_request_header_parse */
+/* _nx_rtsp_server_request_receive */
+/* _nx_rtsp_server_strstr */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+static UINT _nx_rtsp_server_memicmp(UCHAR *src, ULONG src_length, UCHAR *dest, ULONG dest_length)
+{
+UCHAR ch;
+
+
+ /* Compare the length. */
+ if(src_length != dest_length)
+ return(NX_RTSP_SERVER_FAILED);
+
+ while(src_length)
+ {
+
+ /* Is src lowercase? */
+ if((*src >= 'a') && (*src <= 'z'))
+ ch = (UCHAR)(*src - 'a' + 'A');
+
+ /* Is src uppercase? */
+ else if((*src >= 'A') && (*src <= 'Z'))
+ ch = (UCHAR)(*src - 'A' + 'a');
+ else
+ ch = *src;
+
+ /* Compare case insensitive. */
+ if((*src != *dest) && (ch != *dest))
+ return(NX_RTSP_SERVER_FAILED);
+
+ /* Pickup next character. */
+ src_length--;
+ src++;
+ dest++;
+ }
+
+ return(NX_SUCCESS);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_strstr PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function searches the substring and returns the pointer. */
+/* */
+/* INPUT */
+/* */
+/* src Pointer to source */
+/* src_length Length of source */
+/* dest Pointer to destination */
+/* dest_length Length of destination */
+/* */
+/* OUTPUT */
+/* */
+/* pointer Pointer to the substring */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_memicmp Compare two strings */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtsp_server_request_header_parse */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+static UCHAR *_nx_rtsp_server_strstr(UCHAR *src, ULONG src_length, UCHAR *dest, ULONG dest_length)
+{
+UINT index = 0;
+
+
+ /* Check the src and dest length. */
+ if (src_length < dest_length)
+ {
+ return(NX_NULL);
+ }
+
+ /* Loop to search the dest string. */
+ while ((index + dest_length <= src_length) &&
+ (_nx_rtsp_server_memicmp(src + index, dest_length, dest, dest_length) != NX_SUCCESS))
+ {
+ index++;
+ }
+
+ /* Return the pointer. */
+ if ((index + dest_length) <= src_length)
+ {
+ return(src + index);
+ }
+ else
+ {
+ return(NX_NULL);
+ }
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_response_create PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function creates a response packet with common lines. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* rtsp_client_ptr Pointer to RTSP client */
+/* rtsp_client_request_ptr Pointer to request structure */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* nx_packet_allocate Allocate a packet */
+/* nx_packet_data_append Append packet data */
+/* nx_packet_release Release the packet */
+/* _nx_utility_uint_to_string Convert integer to string */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtsp_server_request_process */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+static UINT _nx_rtsp_server_response_create(NX_RTSP_SERVER *rtsp_server_ptr, NX_RTSP_CLIENT *rtsp_client_ptr, NX_RTSP_CLIENT_REQUEST *rtsp_client_request_ptr)
+{
+UINT status;
+CHAR temp_buffer[11];
+UINT temp_length;
+
+
+ /* Allocate response packet. */
+ status = nx_packet_allocate(rtsp_server_ptr -> nx_rtsp_server_packet_pool, &(rtsp_client_ptr -> nx_rtsp_client_response_packet), NX_TCP_PACKET, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ if (status)
+ {
+ return(status);
+ }
+
+ /* Generate the common response lines. */
+
+ /* Set default status as 200 OK. */
+ status = nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, NX_RTSP_SERVER_STRING_WITH_SIZE(NX_RTSP_VERSION_STRING),
+ rtsp_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, NX_RTSP_SERVER_STRING_WITH_SIZE(" 200 OK\r\n"),
+ rtsp_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ /* Add "CSeq" header. */
+ status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, NX_RTSP_SERVER_STRING_WITH_SIZE("CSeq: "),
+ rtsp_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string(rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_sequence_number, 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, temp_buffer, temp_length,
+ rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n"),
+ rtsp_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ /* Add "Server" header. */
+ status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, NX_RTSP_SERVER_STRING_WITH_SIZE("Server: "),
+ rtsp_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, rtsp_server_ptr -> nx_rtsp_server_name, rtsp_server_ptr -> nx_rtsp_server_name_length,
+ rtsp_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n"),
+ rtsp_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ /* If the request method is PLAY, add RTP-Info header. */
+ if (rtsp_client_request_ptr -> nx_rtsp_client_request_method == NX_RTSP_METHOD_PLAY)
+ {
+
+ /* Add "RTP-Info" header. */
+ status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, NX_RTSP_SERVER_STRING_WITH_SIZE("RTP-Info: "),
+ rtsp_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ }
+
+ /* Check if error occurs. */
+ if (status)
+ {
+ nx_packet_release(rtsp_client_ptr -> nx_rtsp_client_response_packet);
+ rtsp_client_ptr -> nx_rtsp_client_response_packet = NX_NULL;
+ }
+
+ return(status);
+}
+
+#ifdef FEATURE_NX_IPV6
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_ipv6_address_to_string PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Haiqing Zhao, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function converts an ipv6 address from ULONG array format into */
+/* standard ipv6 address string format. */
+/* */
+/* INPUT */
+/* */
+/* ipv6_addr Pointer to ULONG array address */
+/* buffer Pointer to output string buffer*/
+/* buffer_length Max length of output buffer */
+/* size Real size of output buffer */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* memset Reset memory */
+/* memcpy Copy data memory */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtsp_server_response_send */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+static UINT _nx_rtsp_server_ipv6_address_to_string(ULONG *ipv6_addr, CHAR *buffer, UINT buffer_length, UINT *size)
+{
+UINT i, j;
+UCHAR c;
+ULONG val;
+CHAR *cur_pos = buffer;
+
+
+ /* Check if the buffer is large enough to contain the ipv6 address in string format. An example ipv6 address string
+ like "2001:0001:0002:0003:0004:0005:0006:1234" shows that 39 bytes data space is needed for the return buffer.
+ Overall, the return buffer shall be 40 bytes to include the end '\0' for the output string. */
+ if (buffer_length < 40)
+ {
+ return(NX_SIZE_ERROR);
+ }
+
+ /* Go through each 4 ULONG values in ipv6 address. */
+ for (i = 0; i < 4; i++)
+ {
+
+ /* Get the current ULONG value. */
+ val = ipv6_addr[i];
+
+ /* Go through each bit of the ULONG to convert. */
+ for (j = 0; j <= 7; j++)
+ {
+
+ /* Save the bit off the most significant end. */
+ c = (UCHAR)((val & 0xF0000000) >> 28);
+
+ /* Make it the most significant byte. */
+ val = val << 4;
+
+ /* Convert the digit to an ascii character. */
+ if (c < 10)
+ {
+ *cur_pos = (CHAR)('0' + c);
+ }
+ else /* Handle HEX digits... */
+ {
+ *cur_pos = (CHAR)('A' + (c - 10));
+ }
+
+ /* Move past the digit. */
+ cur_pos++;
+
+ /* Determine if we need to add a colon. */
+ if ((j == 3) || (j == 7))
+ {
+
+ /* Yes, append the colon and move the pointer past it. */
+ *cur_pos = ':';
+ cur_pos++;
+ }
+ }
+ }
+
+ /* Assign the last byte to make a complete string. */
+ buffer[39] = '\0';
+
+ /* Assign a constant string size 39 as the returned real output buffer size. So far, the returned real size
+ will always be 39 even if an example ipv6 address string is like "2004:0000:0000:0000:0000:0000:0000:0001"
+ since ipv6 abbreviation expression is not supported. */
+ *size = 39;
+
+ return(NX_SUCCESS);
+}
+#endif /* FEATURE_NX_IPV6 */
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_response_send PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function sends the response to the client. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* rtsp_client_ptr Pointer to RTSP client */
+/* rtsp_client_request_ptr Pointer to request structure */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* nx_packet_data_append Append packet data */
+/* _nx_utility_uint_to_string Convert integer to string */
+/* nx_packet_release Release the packet */
+/* nx_tcp_socket_send Send TCP packet */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtsp_server_request_process */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+static UINT _nx_rtsp_server_response_send(NX_RTSP_SERVER *rtsp_server_ptr, NX_RTSP_CLIENT *rtsp_client_ptr, NX_RTSP_CLIENT_REQUEST *rtsp_client_request_ptr)
+{
+UINT status = NX_SUCCESS;
+#ifdef FEATURE_NX_IPV6
+CHAR temp_buffer[40]; /* The size for buffer to store an IPv6 address represented in ASCII. */
+#else
+CHAR temp_buffer[11];
+#endif /* FEATURE_NX_IPV6 */
+UINT temp_length;
+NX_PACKET *temp_packet_ptr;
+NX_PACKET *response_packet_ptr = rtsp_client_ptr -> nx_rtsp_client_response_packet;
+NX_PACKET_POOL *pool_ptr = rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool;
+NXD_ADDRESS *source_ip_address;
+
+ if (!response_packet_ptr)
+ {
+ return(NX_RTSP_SERVER_NO_PACKET);
+ }
+
+ switch (rtsp_client_request_ptr -> nx_rtsp_client_request_method)
+ {
+ case NX_RTSP_METHOD_OPTIONS:
+ {
+
+ /* Always support "OPTIONS, SETUP, PLAY, TEARDOWN". */
+ status = nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("Public: OPTIONS, SETUP, PLAY, TEARDOWN"),
+ pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ /* Check if other methods are supported. */
+ if (rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_describe_callback != NX_NULL)
+ {
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(", DESCRIBE"),
+ pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ }
+
+ if (rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_pause_callback != NX_NULL)
+ {
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(", PAUSE"),
+ pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ }
+
+ if (rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_set_parameter_callback != NX_NULL)
+ {
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(", SET_PARAMETER"),
+ pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ }
+
+ /* Add terminators. */
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n\r\n"),
+ pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ break;
+ }
+ case NX_RTSP_METHOD_DESCRIBE:
+ {
+
+ /* The details in DESCRIBE method are fulfilled in the function _nx_rtsp_server_sdp_set
+ which is normally called in the function nx_rtsp_server_method_describe_callback.
+ So, directly break here in order to skip adding terminators in the default branch. */
+ break;
+ }
+ case NX_RTSP_METHOD_SETUP:
+ {
+
+ /* Add "Session" header. */
+ status = nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("Session: "),
+ pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string(rtsp_client_ptr -> nx_rtsp_client_session_id, 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(";timeout="),
+ pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string(NX_RTSP_SERVER_ACTIVITY_TIMEOUT, 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ /* Add "Transport" header. */
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\nTransport: RTP/AVP;"),
+ pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ /* Add unicast/multicast start words. */
+ if (rtsp_client_request_ptr -> nx_rtsp_client_request_transport.transport_mode == NX_RTSP_TRANSPORT_MODE_UNICAST)
+ {
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("unicast;source="),
+ pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ source_ip_address = &(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.server_ip_address);
+ }
+ else
+ {
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("multicast;destination="),
+ pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ source_ip_address = &(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_ip_address);
+ }
+
+ /* Add source/destination IP address. */
+ if (rtsp_client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V4)
+ {
+#ifndef NX_DISABLE_IPV4
+ temp_length = _nx_utility_uint_to_string(source_ip_address -> nxd_ip_address.v4 >> 24, 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, ".", 1, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string((source_ip_address -> nxd_ip_address.v4 >> 16) & 0xFF, 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, ".", 1, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string((source_ip_address -> nxd_ip_address.v4 >> 8) & 0xFF, 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, ".", 1, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string((source_ip_address -> nxd_ip_address.v4) & 0xFF, 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+#else
+ status = NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED;
+ break;
+#endif /* NX_DISABLE_IPV4 */
+ }
+ else if (rtsp_client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
+ {
+#ifdef FEATURE_NX_IPV6
+ _nx_rtsp_server_ipv6_address_to_string(source_ip_address -> nxd_ip_address.v6, temp_buffer, sizeof(temp_buffer), &temp_length);
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+#else
+ status = NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED;
+ break;
+#endif /* FEATURE_NX_IPV6 */
+ }
+
+ if (rtsp_client_request_ptr -> nx_rtsp_client_request_transport.transport_mode == NX_RTSP_TRANSPORT_MODE_UNICAST)
+ {
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(";client_port="), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_rtp_port,
+ 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("-"), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_rtcp_port,
+ 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(";server_port="), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.server_rtp_port,
+ 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("-"), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.server_rtcp_port,
+ 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(";ssrc="), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.rtp_ssrc,
+ 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ }
+ else
+ {
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(";port="), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_rtp_port,
+ 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("-"), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_rtcp_port,
+ 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(";ttl="), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.multicast_ttl,
+ 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ }
+
+ /* Add terminators. */
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n\r\n"),
+ pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ break;
+ }
+ case NX_RTSP_METHOD_PLAY:
+ {
+
+ /* If user has called nx_rtsp_server_rtp_info_set to set RTP-Info field,
+ there is an extra character ',' appended to the end of the packet. */
+ temp_packet_ptr = response_packet_ptr;
+
+#ifndef NX_DISABLE_PACKET_CHAIN
+ /* If the packet is chained, move to the last packet. */
+ if (response_packet_ptr -> nx_packet_last)
+ {
+ temp_packet_ptr = response_packet_ptr -> nx_packet_last;
+ }
+#endif /* NX_DISABLE_PACKET_CHAIN */
+
+ /* Remove the last character ','. */
+ if (*(temp_packet_ptr -> nx_packet_append_ptr - 1) == ',')
+ {
+ temp_packet_ptr -> nx_packet_append_ptr--;
+ temp_packet_ptr -> nx_packet_length--;
+ }
+
+ /* Add terminators. */
+ status = nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n"),
+ pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ }
+ /* fallthrough */
+ case NX_RTSP_METHOD_PAUSE:
+ {
+ if ((rtsp_client_request_ptr -> nx_rtsp_client_request_method == NX_RTSP_METHOD_PLAY) ||
+ (rtsp_client_ptr -> nx_rtsp_client_npt_start) || (rtsp_client_ptr -> nx_rtsp_client_npt_end))
+ {
+
+ /* Add "Range" header. */
+ status = nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("Range: npt="),
+ pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string((rtsp_client_ptr -> nx_rtsp_client_npt_start / 1000), 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("."), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string((rtsp_client_ptr -> nx_rtsp_client_npt_start % 1000), 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("-"), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ if (rtsp_client_ptr -> nx_rtsp_client_npt_end)
+ {
+ temp_length = _nx_utility_uint_to_string((rtsp_client_ptr -> nx_rtsp_client_npt_end / 1000), 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("."), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string((rtsp_client_ptr -> nx_rtsp_client_npt_end % 1000), 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ }
+
+ /* Add terminators. */
+ status = nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n"),
+ pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ }
+
+ /* Add "Session" header. */
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("Session: "),
+ pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string(rtsp_client_ptr -> nx_rtsp_client_session_id, 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(";timeout="),
+ pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+ temp_length = _nx_utility_uint_to_string(NX_RTSP_SERVER_ACTIVITY_TIMEOUT, 10, temp_buffer, sizeof(temp_buffer));
+ status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ /* Add terminators. */
+ status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n\r\n"),
+ pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ break;
+ }
+ default:
+ {
+
+ /* Add terminators. */
+ status = nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n"),
+ pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
+
+ break;
+ }
+ }
+
+ if (status == NX_SUCCESS)
+ {
+
+ /* Send the response message back. */
+ status = nx_tcp_socket_send(&rtsp_client_ptr -> nx_rtsp_client_socket, response_packet_ptr, NX_RTSP_SERVER_SEND_TIMEOUT);
+ }
+
+ /* Determine if the send was unsuccessful. */
+ if (status)
+ {
+
+ /* Release the packet. */
+ nx_packet_release(response_packet_ptr);
+ }
+
+ /* Clear the response packet pointer. */
+ rtsp_client_ptr -> nx_rtsp_client_response_packet = NX_NULL;
+
+ return(status);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_request_process PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes RTSP requests. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_request_receive Receive client request */
+/* _nx_rtsp_server_request_parse Parse client request */
+/* _nx_rtsp_server_response_create Create common response */
+/* _nx_rtsp_server_error_response_send Send error response */
+/* _nx_rtsp_server_response_send Send common response */
+/* nx_packet_release Release the packet */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtsp_server_thread_entry */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+static VOID _nx_rtsp_server_request_process(NX_RTSP_SERVER *rtsp_server_ptr)
+{
+UINT i;
+UINT status;
+NX_RTSP_CLIENT *rtsp_client_ptr;
+NX_RTSP_SERVER_METHOD_CALLBACKS method_callbacks = rtsp_server_ptr -> nx_rtsp_server_method_callbacks;
+
+
+ /* Now look for a socket that has receive data. */
+ for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
+ {
+
+ /* Setup pointer to client structure. */
+ rtsp_client_ptr = &(rtsp_server_ptr -> nx_rtsp_server_client_list[i]);
+
+ /* Now see if this socket has data. */
+ if (rtsp_client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_receive_queue_count)
+ {
+
+ /* Attempt to read a packet from this socket. */
+ status = _nx_rtsp_server_request_receive(rtsp_server_ptr, rtsp_client_ptr);
+
+ /* Check for no data present. */
+ if (status != NX_SUCCESS)
+ {
+
+ /* Just continue the loop and look at the next socket. */
+ continue;
+ }
+
+ /* Reset the client request activity timeout. */
+ rtsp_client_ptr -> nx_rtsp_client_request_activity_timeout = NX_RTSP_SERVER_ACTIVITY_TIMEOUT;
+
+ /* Set the pointer to the current Client request. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr = &(rtsp_client_ptr -> nx_rtsp_client_request);
+
+ /* Parse the client request. */
+ status = _nx_rtsp_server_request_parse(rtsp_client_ptr, rtsp_client_ptr -> nx_rtsp_client_request_ptr);
+
+ /* Check for error status. */
+ if (status != NX_SUCCESS)
+ {
+
+ /* Release the request packet. */
+ nx_packet_release(rtsp_client_ptr -> nx_rtsp_client_request_packet);
+ rtsp_client_ptr -> nx_rtsp_client_request_packet = NX_NULL;
+ rtsp_client_ptr -> nx_rtsp_client_request_bytes_total = 0;
+
+ /* Clear the pointer of Client request. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr = NX_NULL;
+
+ /* Just continue the loop and look at the next socket. */
+ continue;
+ }
+
+ /* Create the response packet. */
+ status = _nx_rtsp_server_response_create(rtsp_server_ptr, rtsp_client_ptr, rtsp_client_ptr -> nx_rtsp_client_request_ptr);
+
+ /* Packet allocation failure. */
+ if (status != NX_SUCCESS)
+ {
+
+ /* There is nothing we can do here. Ideally log this error event. */
+ rtsp_server_ptr -> nx_rtsp_server_allocation_errors++;
+
+ /* Release the request packet. */
+ nx_packet_release(rtsp_client_ptr -> nx_rtsp_client_request_packet);
+ rtsp_client_ptr -> nx_rtsp_client_request_packet = NX_NULL;
+ rtsp_client_ptr -> nx_rtsp_client_request_bytes_total = 0;
+
+ /* Clear the pointer of Client request. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr = NX_NULL;
+
+ /* At this point, just continue the loop and look at the next socket. */
+ continue;
+ }
+
+ /* Set default response status code to 200 OK. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_OK;
+
+ switch (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_method)
+ {
+ case NX_RTSP_METHOD_OPTIONS:
+ {
+
+ /* OPTIONS is always allowed and supported. */
+ break;
+ }
+ case NX_RTSP_METHOD_DESCRIBE:
+ {
+ if (method_callbacks.nx_rtsp_server_method_describe_callback == NX_NULL)
+ {
+
+ /* Method not installed, so we return "method not supported". */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED;
+
+ break;
+ }
+
+ /* Invoke the actual callback routine. */
+ status = method_callbacks.nx_rtsp_server_method_describe_callback
+ (rtsp_client_ptr,
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr,
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_length);
+
+ if (status != NX_SUCCESS)
+ {
+
+ /* Internal error occurs. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_INTERNAL_SERVER_ERROR;
+ }
+
+ break;
+ }
+ case NX_RTSP_METHOD_SETUP:
+ {
+
+ /* The callbacks for SETUP, PLAY and TEARDOWN are required to be set and
+ we have checked this in _nx_rtsp_server_start() function. */
+
+ /* If session ID is present, we need to verify session ID. */
+ if (rtsp_client_ptr -> nx_rtsp_client_session_id &&
+ (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_session_id != rtsp_client_ptr -> nx_rtsp_client_session_id))
+ {
+
+ /* Session not found. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
+ break;
+ }
+
+ if (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr == NX_NULL)
+ {
+
+ /* No media specified in the request. Invalid case. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
+ break;
+ }
+ else if ((rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_transport.transport_mode == NX_RTSP_TRANSPORT_MODE_UNICAST) &&
+ ((rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_rtp_port == 0) ||
+ (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_rtcp_port == 0)))
+ {
+
+ /* Invalid client port. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_UNSUPPORTED_TRANSPORT;
+ break;
+ }
+
+ status = method_callbacks.nx_rtsp_server_method_setup_callback
+ (rtsp_client_ptr,
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr,
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_length,
+ &(rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_transport));
+
+ /* If callback returns "SUCCESS". */
+ if (status == NX_SUCCESS)
+ {
+ if (rtsp_client_ptr -> nx_rtsp_client_state == NX_RTSP_STATE_INIT)
+ {
+
+ /* Set client state to ready. */
+ rtsp_client_ptr -> nx_rtsp_client_state = NX_RTSP_STATE_READY;
+ }
+
+ if (rtsp_client_ptr -> nx_rtsp_client_session_id == 0)
+ {
+
+ /* Remember the session ID for future validation. */
+ rtsp_client_ptr -> nx_rtsp_client_session_id = (ULONG)NX_RAND();
+ }
+ }
+ else
+ {
+
+ /* Internal error occurs. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_INTERNAL_SERVER_ERROR;
+ }
+
+ break;
+ }
+ case NX_RTSP_METHOD_PLAY:
+ {
+
+ /* The callbacks for SETUP, PLAY and TEARDOWN are required to be set and
+ we have checked this in _nx_rtsp_server_start() function. */
+
+ if (!(rtsp_client_ptr -> nx_rtsp_client_session_id) ||
+ (rtsp_client_ptr -> nx_rtsp_client_session_id != rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_session_id))
+ {
+
+ /* Session not found. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
+
+ break;
+ }
+
+ if (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr == NX_NULL)
+ {
+
+ /* No media specified in the request. Invalid case. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
+ break;
+ }
+
+ /* Reset the npt start and end time. */
+ rtsp_client_ptr -> nx_rtsp_client_npt_start = 0;
+ rtsp_client_ptr -> nx_rtsp_client_npt_end = 0;
+
+ status = method_callbacks.nx_rtsp_server_method_play_callback
+ (rtsp_client_ptr,
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr,
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_length,
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_range_ptr,
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_range_length);
+
+ /* If callback returns "SUCCESS". */
+ if (status == NX_SUCCESS)
+ {
+
+ /* Set client state to playing. */
+ rtsp_client_ptr -> nx_rtsp_client_state = NX_RTSP_STATE_PLAYING;
+ }
+ else
+ {
+
+ /* Internal error occurs. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_INTERNAL_SERVER_ERROR;
+ }
+
+ break;
+ }
+ case NX_RTSP_METHOD_PAUSE:
+ {
+ if (method_callbacks.nx_rtsp_server_method_pause_callback == NX_NULL)
+ {
+
+ /* Method not installed, so we return "method not supported". */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED;
+
+ break;
+ }
+
+ /* Validate Session ID. */
+ if (!(rtsp_client_ptr -> nx_rtsp_client_session_id) ||
+ (rtsp_client_ptr -> nx_rtsp_client_session_id != rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_session_id))
+ {
+
+ /* Session not found. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
+
+ break;
+ }
+
+ if (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr == NX_NULL)
+ {
+
+ /* No media specified in the request. Invalid case. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
+ break;
+ }
+
+ /* Reset the npt start and end time. */
+ rtsp_client_ptr -> nx_rtsp_client_npt_start = 0;
+ rtsp_client_ptr -> nx_rtsp_client_npt_end = 0;
+
+ status = method_callbacks.nx_rtsp_server_method_pause_callback
+ (rtsp_client_ptr,
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr,
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_length,
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_range_ptr,
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_range_length);
+
+ /* If callback returns "SUCCESS". */
+ if (status == NX_SUCCESS)
+ {
+
+ /* Set client state to ready. */
+ rtsp_client_ptr -> nx_rtsp_client_state = NX_RTSP_STATE_READY;
+ }
+ else
+ {
+
+ /* Internal error occurs. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_INTERNAL_SERVER_ERROR;
+ }
+
+ break;
+ }
+ case NX_RTSP_METHOD_TEARDOWN:
+ {
+
+ /* The callbacks for SETUP, PLAY and TEARDOWN are required to be set and
+ we have checked this in _nx_rtsp_server_start() function. */
+
+ /* Validate session ID. */
+ if (!(rtsp_client_ptr -> nx_rtsp_client_session_id) ||
+ (rtsp_client_ptr -> nx_rtsp_client_session_id != rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_session_id))
+ {
+
+ /* Session not found. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
+
+ break;
+ }
+
+ if (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr == NX_NULL)
+ {
+
+ /* No media specified in the request. Invalid case. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
+ break;
+ }
+
+ status = method_callbacks.nx_rtsp_server_method_teardown_callback
+ (rtsp_client_ptr,
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr,
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_length);
+
+
+ /* If got positive response from media handler. */
+ if (status == NX_SUCCESS)
+ {
+
+ /* Set client state to init. */
+ rtsp_client_ptr -> nx_rtsp_client_state = NX_RTSP_STATE_INIT;
+
+ /* Clear the session ID. */
+ rtsp_client_ptr -> nx_rtsp_client_session_id = 0;
+ }
+ else
+ {
+
+ /* Internal error occurs. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_INTERNAL_SERVER_ERROR;
+ }
+
+ break;
+ }
+ case NX_RTSP_METHOD_SET_PARAMETER:
+ {
+ if (method_callbacks.nx_rtsp_server_method_set_parameter_callback == NULL)
+ {
+
+ /* Method not installed, so we return "method not supported". */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED;
+
+ break;
+ }
+
+ /* Validate session ID. */
+ if (!(rtsp_client_ptr -> nx_rtsp_client_session_id) ||
+ (rtsp_client_ptr -> nx_rtsp_client_session_id != rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_session_id))
+ {
+
+ /* Session not found. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
+
+ break;
+ }
+
+ if (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr == NX_NULL)
+ {
+
+ /* No media specified in the request. Invalid case. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
+ break;
+ }
+
+ status = method_callbacks.nx_rtsp_server_method_set_parameter_callback
+ (rtsp_client_ptr,
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr,
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_length,
+ (rtsp_client_ptr -> nx_rtsp_client_request_packet -> nx_packet_append_ptr - rtsp_client_ptr -> nx_rtsp_client_request_content_length),
+ rtsp_client_ptr -> nx_rtsp_client_request_content_length);
+
+ /* If callback returns "SUCCESS". */
+ if (status)
+ {
+
+ /* Internal error occurs. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_INTERNAL_SERVER_ERROR;
+ }
+
+ break;
+ }
+ default:
+ {
+
+ /* Method not installed, so we return "NOT IMPLEMENTED". */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED;
+
+ break;
+ }
+ }
+
+ /* Send the response. */
+ if (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code >= 300)
+ {
+
+ /* Handle error response. */
+ _nx_rtsp_server_error_response_send(rtsp_client_ptr, rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code);
+ }
+ else
+ {
+ _nx_rtsp_server_response_send(rtsp_server_ptr, rtsp_client_ptr, rtsp_client_ptr -> nx_rtsp_client_request_ptr);
+ }
+
+ /* Release the request packet. */
+ nx_packet_release(rtsp_client_ptr -> nx_rtsp_client_request_packet);
+ rtsp_client_ptr -> nx_rtsp_client_request_packet = NX_NULL;
+ rtsp_client_ptr -> nx_rtsp_client_request_bytes_total = 0;
+
+ /* Clear the pointer of Client request. */
+ rtsp_client_ptr -> nx_rtsp_client_request_ptr = NX_NULL;
+ }
+ }
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_connect_process PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes connections for multiple sessions. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* nx_tcp_server_socket_accept Accept incoming TCP request */
+/* nx_tcp_server_socket_unaccept Clear accepted socket */
+/* nx_tcp_server_socket_relisten Re-listen on free socket */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtsp_server_thread_entry */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+static VOID _nx_rtsp_server_connect_process(NX_RTSP_SERVER *rtsp_server_ptr)
+{
+UINT i;
+UINT status;
+NX_RTSP_CLIENT *client_ptr;
+
+
+ /* One of the control ports is in the processing of connection.
+ Search the connections to see which one. */
+ for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
+ {
+
+ /* Setup pointer to client structure. */
+ client_ptr = &(rtsp_server_ptr -> nx_rtsp_server_client_list[i]);
+
+ /* Now see if this socket was the one that is in being connected. */
+ if ((client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_state > NX_TCP_CLOSED) &&
+ (client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_state < NX_TCP_ESTABLISHED) &&
+ (client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_connect_port))
+ {
+
+ /* Yes, we have found the socket being connected. */
+
+ /* Attempt to accept on this socket. */
+ status = nx_tcp_server_socket_accept(&(client_ptr -> nx_rtsp_client_socket), NX_RTSP_SERVER_ACCEPT_TIMEOUT);
+
+ /* Determine if it is successful. */
+ if (status)
+ {
+
+ /* Not successful, simply unaccept on this socket. */
+ nx_tcp_server_socket_unaccept(&(client_ptr -> nx_rtsp_client_socket));
+ }
+ else
+ {
+
+ /* Reset the client request activity timeout. */
+ client_ptr -> nx_rtsp_client_request_activity_timeout = NX_RTSP_SERVER_ACTIVITY_TIMEOUT;
+
+ /* Set the client as valid. */
+ client_ptr -> nx_rtsp_client_valid = NX_TRUE;
+
+ /* Store the RTSP server pointer. */
+ client_ptr -> nx_rtsp_client_server_ptr = rtsp_server_ptr;
+
+ /* Update the connected client count. */
+ rtsp_server_ptr -> nx_rtsp_server_connected_client_count++;
+ }
+
+ /* In any case break out of the loop when we find a connection - there can only be one
+ at a time! */
+ break;
+ }
+ }
+
+ /* Now look for a client that is valid to relisten on. */
+ for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
+ {
+
+ /* Setup pointer to client request structure. */
+ client_ptr = &(rtsp_server_ptr -> nx_rtsp_server_client_list[i]);
+
+ /* Now see if this socket is closed. */
+ if ((client_ptr -> nx_rtsp_client_valid == NX_FALSE) &&
+ (client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_state == NX_TCP_CLOSED))
+ {
+
+ /* Relisten on this socket. */
+ status = nx_tcp_server_socket_relisten(rtsp_server_ptr -> nx_rtsp_server_ip_ptr, rtsp_server_ptr -> nx_rtsp_server_port,
+ &(client_ptr -> nx_rtsp_client_socket));
+
+ /* Check for bad status. */
+ if ((status != NX_SUCCESS) && (status != NX_CONNECTION_PENDING))
+ {
+
+ /* Increment the error count and keep trying. */
+ rtsp_server_ptr -> nx_rtsp_server_relisten_errors++;
+ continue;
+ }
+
+ /* Break out of loop. */
+ break;
+ }
+ }
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_disconnect_process PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes disconnect for multiple sessions. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_disconnect Disconnect from client */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtsp_server_thread_entry */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+static VOID _nx_rtsp_server_disconnect_process(NX_RTSP_SERVER *rtsp_server_ptr)
+{
+UINT i;
+NX_RTSP_CLIENT *rtsp_client_ptr;
+
+
+ /* Examine all the client structures. */
+ for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
+ {
+
+ /* Setup pointer to client structure. */
+ rtsp_client_ptr = &(rtsp_server_ptr -> nx_rtsp_server_client_list[i]);
+
+ /* Determine if this socket is in a disconnect state. */
+ if (rtsp_client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_state > NX_TCP_ESTABLISHED)
+ {
+
+ /* Yes, this socket needs to be torn down. */
+
+ /* Increment the number of disconnection requests. */
+ rtsp_server_ptr -> nx_rtsp_server_disconnection_requests++;
+
+ /* Disconnect the socket. */
+ _nx_rtsp_server_disconnect(rtsp_server_ptr, rtsp_client_ptr);
+ }
+ }
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_timeout_process PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes timeout event. */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _nx_rtsp_server_disconnect Disconnect from client */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtsp_server_thread_entry */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+static VOID _nx_rtsp_server_timeout_process(NX_RTSP_SERVER *rtsp_server_ptr)
+{
+UINT i;
+NX_RTSP_CLIENT *rtsp_client_ptr;
+
+
+ /* Examine all the client structures. */
+ for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
+ {
+
+ /* Setup pointer to client structure. */
+ rtsp_client_ptr = &(rtsp_server_ptr -> nx_rtsp_server_client_list[i]);
+
+ /* Skip the socket that is not used. */
+ if (rtsp_client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_state <= NX_TCP_LISTEN_STATE)
+ {
+ continue;
+ }
+
+ /* Skip the inactive client. */
+ if (rtsp_client_ptr -> nx_rtsp_client_request_activity_timeout == 0)
+ {
+ continue;
+ }
+
+ /* Decrease the timer count. */
+ rtsp_client_ptr -> nx_rtsp_client_request_activity_timeout--;
+
+ /* Check if the client is timeout. */
+ if (rtsp_client_ptr -> nx_rtsp_client_request_activity_timeout == 0)
+ {
+
+ /* Disconnect the socket. */
+ _nx_rtsp_server_disconnect(rtsp_server_ptr, rtsp_client_ptr);
+ }
+ }
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_request_present PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function handles all RTSP client commands received on */
+/* the control socket. */
+/* */
+/* */
+/* INPUT */
+/* */
+/* request_socket_ptr Socket event occurred */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* tx_event_flags_set Set events for server thread */
+/* */
+/* CALLED BY */
+/* */
+/* NetX NetX receive packet callback */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+static VOID _nx_rtsp_server_request_present(NX_TCP_SOCKET *request_socket_ptr)
+{
+
+NX_RTSP_SERVER *server_ptr;
+
+
+ /* Pickup server pointer. This is setup in the reserved field of the TCP socket. */
+ server_ptr = request_socket_ptr -> nx_tcp_socket_reserved_ptr;
+
+ /* Set the request event flag. */
+ tx_event_flags_set(&(server_ptr -> nx_rtsp_server_event_flags), NX_RTSP_SERVER_REQUEST_EVENT, TX_OR);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_connect_present PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function handles all RTSP client connections received on */
+/* the control socket. */
+/* */
+/* */
+/* INPUT */
+/* */
+/* request_socket_ptr Socket event occurred */
+/* port Port the connection occurred */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* tx_event_flags_set Set events for server thread */
+/* */
+/* CALLED BY */
+/* */
+/* NetX NetX connect callback */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+static VOID _nx_rtsp_server_connect_present(NX_TCP_SOCKET *request_socket_ptr, UINT port)
+{
+NX_RTSP_SERVER *server_ptr;
+
+
+ NX_PARAMETER_NOT_USED(port);
+
+ /* Pickup server pointer. This is setup in the reserved field of the TCP socket. */
+ server_ptr = request_socket_ptr -> nx_tcp_socket_reserved_ptr;
+
+ /* Set the connect event flag. */
+ tx_event_flags_set(&(server_ptr -> nx_rtsp_server_event_flags), NX_RTSP_SERVER_CONNECT_EVENT, TX_OR);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_disconnect_present PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function notifies the RTSP server thread of client disconnects */
+/* of the control socket. */
+/* */
+/* */
+/* INPUT */
+/* */
+/* request_socket_ptr Socket event occurred */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* tx_event_flags_set Set events for server thread */
+/* */
+/* CALLED BY */
+/* */
+/* NetX NetX connect callback */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+static VOID _nx_rtsp_server_disconnect_present(NX_TCP_SOCKET *request_socket_ptr)
+{
+NX_RTSP_SERVER *server_ptr;
+
+
+ /* Pickup server pointer. This is setup in the reserved field of the TCP socket. */
+ server_ptr = request_socket_ptr -> nx_tcp_socket_reserved_ptr;
+
+ /* Set the disconnect event flag. */
+ tx_event_flags_set(&(server_ptr -> nx_rtsp_server_event_flags), NX_RTSP_SERVER_DISCONNECT_EVENT, TX_OR);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_timeout PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This internal function is invoked whenever the internal timeout */
+/* timer expires, and is passed into tx_timer_create as the callback. */
+/* */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_address Pointer to RTSP server */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* tx_event_flags_set Set events for server thread */
+/* */
+/* CALLED BY */
+/* */
+/* ThreadX */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+static VOID _nx_rtsp_server_timeout(ULONG rtsp_server_address)
+{
+NX_RTSP_SERVER *rtsp_server_ptr = (NX_RTSP_SERVER *)rtsp_server_address;
+
+
+ /* Set the timeout event flag. */
+ tx_event_flags_set(&(rtsp_server_ptr -> nx_rtsp_server_event_flags), NX_RTSP_SERVER_TIMEOUT_EVENT, TX_OR);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_rtsp_server_disconnect PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function disconnects a client which is disconnected or timeout.*/
+/* */
+/* */
+/* INPUT */
+/* */
+/* rtsp_server_ptr Pointer to RTSP server */
+/* rtsp_client_ptr Pointer to RTSP client */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* nx_tcp_socket_disconnect Disconnect TCP socket */
+/* nx_tcp_server_socket_unaccept Clear accepted socket */
+/* nx_packet_release Release the packet */
+/* nx_tcp_server_socket_relisten Re-listen on free socket */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_rtsp_server_disconnect_process */
+/* _nx_rtsp_server_timeout_process */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+static VOID _nx_rtsp_server_disconnect(NX_RTSP_SERVER *rtsp_server_ptr, NX_RTSP_CLIENT *rtsp_client_ptr)
+{
+
+ /* Disable the client request activity timeout. */
+ rtsp_client_ptr -> nx_rtsp_client_request_activity_timeout = 0;
+
+ /* Now disconnect the socket. */
+ nx_tcp_socket_disconnect(&(rtsp_client_ptr -> nx_rtsp_client_socket), NX_NO_WAIT);
+
+ /* Unaccept the server socket. */
+ nx_tcp_server_socket_unaccept(&(rtsp_client_ptr -> nx_rtsp_client_socket));
+
+ /* Check to see if a packet is queued up. */
+ if (rtsp_client_ptr -> nx_rtsp_client_request_packet)
+ {
+
+ /* Yes, release it! */
+ nx_packet_release(rtsp_client_ptr -> nx_rtsp_client_request_packet);
+ rtsp_client_ptr -> nx_rtsp_client_request_packet = NX_NULL;
+ rtsp_client_ptr -> nx_rtsp_client_request_bytes_total = 0;
+ }
+
+ /* Check to see if a packet is queued up. */
+ if (rtsp_client_ptr -> nx_rtsp_client_response_packet)
+ {
+
+ /* Yes, release it! */
+ nx_packet_release(rtsp_client_ptr -> nx_rtsp_client_response_packet);
+ rtsp_client_ptr -> nx_rtsp_client_response_packet = NX_NULL;
+ }
+
+ /* Invoke the disconnect callback. */
+ if ((rtsp_server_ptr -> nx_rtsp_server_disconnect_callback) &&
+ (rtsp_client_ptr -> nx_rtsp_client_state > NX_RTSP_STATE_INIT))
+ {
+ rtsp_server_ptr -> nx_rtsp_server_disconnect_callback(rtsp_client_ptr);
+ }
+
+ /* Relisten on this socket. */
+ nx_tcp_server_socket_relisten(rtsp_server_ptr -> nx_rtsp_server_ip_ptr, rtsp_server_ptr -> nx_rtsp_server_port,
+ &(rtsp_client_ptr -> nx_rtsp_client_socket));
+
+ /* Clear the session ID. */
+ rtsp_client_ptr -> nx_rtsp_client_session_id = 0;
+
+ /* Reset client valid status. */
+ rtsp_client_ptr -> nx_rtsp_client_valid = NX_FALSE;
+
+ /* Reset client state. */
+ rtsp_client_ptr -> nx_rtsp_client_state = NX_RTSP_STATE_INIT;
+
+ /* Update the connected client count. */
+ rtsp_server_ptr -> nx_rtsp_server_connected_client_count--;
+}
+
diff --git a/addons/rtsp/nx_rtsp_server.h b/addons/rtsp/nx_rtsp_server.h
new file mode 100644
index 00000000..2f62aaeb
--- /dev/null
+++ b/addons/rtsp/nx_rtsp_server.h
@@ -0,0 +1,535 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** Real Time Streaming Protocol (RTSP) */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* APPLICATION INTERFACE DEFINITION RELEASE */
+/* */
+/* nx_rtsp_server.h PORTABLE C */
+/* 6.3.0 */
+/* AUTHOR */
+/* */
+/* Wenhui Xie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the NetX RTSP Server component, including all */
+/* data types and external references. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
+/* */
+/**************************************************************************/
+
+#ifndef NX_RTSP_SERVER_H
+#define NX_RTSP_SERVER_H
+
+#include "tx_api.h"
+#include "nx_api.h"
+
+/* Determine if a C++ compiler is being used. If so, ensure that standard
+ C is used to process the API information. */
+
+#ifdef __cplusplus
+/* Yes, C++ compiler is present. Use standard C. */
+extern "C" {
+
+#endif
+
+/* Define the RTSP Server ID. */
+#define NX_RTSP_SERVER_ID 0x52545350UL
+
+/* Define the RTSP protocol version of the RTSP Server. */
+#define NX_RTSP_VERSION_STRING "RTSP/1.0"
+
+/* Define the RTSP SDP content type. */
+#define NX_RTSP_SERVER_CONTENT_TYPE_SDP "application/sdp"
+
+/* Define the RTSP status code. */
+#define NX_RTSP_STATUS_CODE_OK 200
+#define NX_RTSP_STATUS_CODE_CREATED 201
+#define NX_RTSP_STATUS_CODE_LOW_ON_STORAGE_SPACE 250
+#define NX_RTSP_STATUS_CODE_MULTIPLE_CHOICES 300
+#define NX_RTSP_STATUS_CODE_MOVED_PERMANENTLY 301
+#define NX_RTSP_STATUS_CODE_MOVED_TEMPORARILY 302
+#define NX_RTSP_STATUS_CODE_SEE_OTHER 303
+#define NX_RTSP_STATUS_CODE_NOT_MODIFIED 304
+#define NX_RTSP_STATUS_CODE_USE_PROXY 305
+#define NX_RTSP_STATUS_CODE_GOING_AWAY 350
+#define NX_RTSP_STATUS_CODE_LOAD_BALANCING 351
+#define NX_RTSP_STATUS_CODE_BAD_REQUEST 400
+#define NX_RTSP_STATUS_CODE_UNAUTHORIZED 401
+#define NX_RTSP_STATUS_CODE_PAYMENT_REQUIRED 402
+#define NX_RTSP_STATUS_CODE_FORBIDDEN 403
+#define NX_RTSP_STATUS_CODE_NOT_FOUND 404
+#define NX_RTSP_STATUS_CODE_METHOD_NOT_ALLOWED 405
+#define NX_RTSP_STATUS_CODE_NOT_ACCEPTABLE 406
+#define NX_RTSP_STATUS_CODE_PROXY_AUTHENTICATION_REQUIRED 407
+#define NX_RTSP_STATUS_CODE_REQUEST_TIMEOUT 408
+#define NX_RTSP_STATUS_CODE_GONE 410
+#define NX_RTSP_STATUS_CODE_LENGTH_REQUIRED 411
+#define NX_RTSP_STATUS_CODE_PRECONDITION_FAILED 412
+#define NX_RTSP_STATUS_CODE_REQUEST_ENTITY_TOO_LARGE 413
+#define NX_RTSP_STATUS_CODE_REQUESTURI_TOO_LARGE 414
+#define NX_RTSP_STATUS_CODE_UNSUPPORTED_MEDIA_TYPE 415
+#define NX_RTSP_STATUS_CODE_PARAMETER_NOT_UNDERSTOOD 451
+#define NX_RTSP_STATUS_CODE_RESERVED 452
+#define NX_RTSP_STATUS_CODE_NOT_ENOUGH_BANDWIDTH 453
+#define NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND 454
+#define NX_RTSP_STATUS_CODE_METHOD_NOT_VALID_IN_THIS_STATE 455
+#define NX_RTSP_STATUS_CODE_HEADER_FIELD_NOT_VALID_FOR_RESOURCE 456
+#define NX_RTSP_STATUS_CODE_INVALID_RANGE 457
+#define NX_RTSP_STATUS_CODE_PARAMETER_IS_READONLY 458
+#define NX_RTSP_STATUS_CODE_AGGREGATE_OPERATION_NOT_ALLOWED 459
+#define NX_RTSP_STATUS_CODE_ONLY_AGGREGATE_OPERATION_ALLOWED 460
+#define NX_RTSP_STATUS_CODE_UNSUPPORTED_TRANSPORT 461
+#define NX_RTSP_STATUS_CODE_DESTINATION_UNREACHABLE 462
+#define NX_RTSP_STATUS_CODE_INTERNAL_SERVER_ERROR 500
+#define NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED 501
+#define NX_RTSP_STATUS_CODE_BAD_GATEWAY 502
+#define NX_RTSP_STATUS_CODE_SERVICE_UNAVAILABLE 503
+#define NX_RTSP_STATUS_CODE_GATEWAY_TIMEOUT 504
+#define NX_RTSP_STATUS_CODE_RTSP_VERSION_NOT_SUPPORTED 505
+#define NX_RTSP_STATUS_CODE_OPTION_NOT_SUPPORTED 551
+
+/* Define the RTSP Server error code. */
+#define NX_RTSP_SERVER_ALREADY_STARTED 0x7000
+#define NX_RTSP_SERVER_NOT_STARTED 0x7001
+#define NX_RTSP_SERVER_INTERNAL_ERROR 0x7002
+#define NX_RTSP_SERVER_NO_PACKET 0x7003
+#define NX_RTSP_SERVER_NOT_IMPLEMENTED 0x7004
+#define NX_RTSP_SERVER_MISSING_REQUIRED_CALLBACKS 0x7005
+#define NX_RTSP_SERVER_INVALID_REQUEST 0x7006
+#define NX_RTSP_SERVER_INVALID_PARAMETER 0x7007
+#define NX_RTSP_SERVER_UNSUPPORTED 0x7008
+#define NX_RTSP_SERVER_FAILED 0x7009
+
+/* Define the max number of concurrent Clients the Server supports. */
+#ifndef NX_RTSP_SERVER_MAX_CLIENTS
+#define NX_RTSP_SERVER_MAX_CLIENTS 2
+#endif /* NX_RTSP_SERVER_MAX_CLIENTS */
+
+/* Define the RTSP Server time slice. */
+#ifndef NX_RTSP_SERVER_TIME_SLICE
+#define NX_RTSP_SERVER_TIME_SLICE TX_NO_TIME_SLICE
+#endif /* NX_RTSP_SERVER_TIME_SLICE */
+
+/* Define the timeout for the packet allocation and data appending. */
+#ifndef NX_RTSP_SERVER_PACKET_TIMEOUT
+#define NX_RTSP_SERVER_PACKET_TIMEOUT (1 * NX_IP_PERIODIC_RATE)
+#endif /* NX_RTSP_SERVER_PACKET_TIMEOUT */
+
+/* Define the timeout for the RTSP Server socket accepting. */
+#ifndef NX_RTSP_SERVER_ACCEPT_TIMEOUT
+#define NX_RTSP_SERVER_ACCEPT_TIMEOUT (10 * NX_IP_PERIODIC_RATE)
+#endif /* NX_RTSP_SERVER_ACCEPT_TIMEOUT */
+
+/* Define the timeout for the packet sending. */
+#ifndef NX_RTSP_SERVER_SEND_TIMEOUT
+#define NX_RTSP_SERVER_SEND_TIMEOUT (1 * NX_IP_PERIODIC_RATE)
+#endif /* NX_RTSP_SERVER_SEND_TIMEOUT */
+
+/* Define the timeout in seconds for Client activity. */
+#ifndef NX_RTSP_SERVER_ACTIVITY_TIMEOUT
+#define NX_RTSP_SERVER_ACTIVITY_TIMEOUT 60
+#endif /* NX_RTSP_SERVER_ACTIVITY_TIMEOUT */
+
+/* Define the type of service. */
+#ifndef NX_RTSP_SERVER_TYPE_OF_SERVICE
+#define NX_RTSP_SERVER_TYPE_OF_SERVICE NX_IP_NORMAL
+#endif /* NX_RTSP_SERVER_TYPE_OF_SERVICE */
+
+/* Define the fragment option. */
+#ifndef NX_RTSP_SERVER_FRAGMENT_OPTION
+#define NX_RTSP_SERVER_FRAGMENT_OPTION NX_FRAGMENT_OKAY
+#endif /* NX_RTSP_SERVER_FRAGMENT_OPTION */
+
+/* Define the TTL. */
+#ifndef NX_RTSP_SERVER_TIME_TO_LIVE
+#define NX_RTSP_SERVER_TIME_TO_LIVE NX_IP_TIME_TO_LIVE
+#endif /* NX_RTSP_SERVER_TIME_TO_LIVE */
+
+/* Define the window size. */
+#ifndef NX_RTSP_SERVER_WINDOW_SIZE
+#define NX_RTSP_SERVER_WINDOW_SIZE 8192
+#endif /* NX_RTSP_SERVER_WINDOW_SIZE */
+
+/* Define the RTSP Server events. */
+#define NX_RTSP_SERVER_ALL_EVENTS 0xFFFFFFFF
+#define NX_RTSP_SERVER_CONNECT_EVENT 0x00000001
+#define NX_RTSP_SERVER_DISCONNECT_EVENT 0x00000002
+#define NX_RTSP_SERVER_REQUEST_EVENT 0x00000004
+#define NX_RTSP_SERVER_TIMEOUT_EVENT 0x00000008
+
+/* Define the RTSP state. */
+#define NX_RTSP_STATE_INIT 1
+#define NX_RTSP_STATE_READY 2
+#define NX_RTSP_STATE_PLAYING 3
+
+/* Define the transport type. */
+#define NX_RTSP_TRANSPORT_TYPE_UDP 0x00
+#define NX_RTSP_TRANSPORT_TYPE_TCP 0x01
+
+/* There are several modes of transport, see https://www.rfc-editor.org/rfc/rfc2326#section-1.6
+ 1. unicast.
+ 2. multicast, Server chooses address.
+ 3. multicast, Client chooses address. */
+#define NX_RTSP_TRANSPORT_MODE_UNICAST 0x00
+#define NX_RTSP_TRANSPORT_MODE_MULTICAST_SERVER 0x01
+#define NX_RTSP_TRANSPORT_MODE_MULTICAST_CLIENT 0x02
+
+/* Define Server capabilities. */
+#define NX_RTSP_METHOD_OPTIONS 0x00
+#define NX_RTSP_METHOD_DESCRIBE 0x01
+#define NX_RTSP_METHOD_SETUP 0x02
+#define NX_RTSP_METHOD_PLAY 0x03
+#define NX_RTSP_METHOD_PAUSE 0x04
+#define NX_RTSP_METHOD_TEARDOWN 0x05
+#define NX_RTSP_METHOD_SET_PARAMETER 0x06
+#define NX_RTSP_METHOD_NOT_SUPPORT 0xFF
+
+/* Define the transport structure. */
+typedef struct NX_RTSP_TRANSPORT_STRUCT
+{
+ UCHAR transport_type; /* UDP or TCP. */
+
+ UCHAR transport_mode; /* Unicast or multicast(Server or Client chooses address). */
+
+ USHORT multicast_ttl; /* TTL for multicast. */
+
+ ULONG rtp_ssrc; /* RTP SSRC. */
+
+ USHORT client_rtp_port; /* Client RTP port. */
+
+ USHORT client_rtcp_port; /* Client RTCP port. */
+
+ USHORT server_rtp_port; /* Server RTP port. */
+
+ USHORT server_rtcp_port; /* Server RTCP port. */
+
+ NXD_ADDRESS client_ip_address; /* Client IP address. */
+
+ NXD_ADDRESS server_ip_address; /* Server IP address. */
+
+ UINT interface_index; /* IP interface index. */
+} NX_RTSP_TRANSPORT;
+
+/* Define the response status code and description. */
+typedef struct NX_RTSP_RESPONSE_STRCUT
+{
+ UINT nx_rtsp_response_code; /* The value of the response status code. */
+
+ CHAR *nx_rtsp_response_description; /* The description of the response status code. */
+} NX_RTSP_RESPONSE;
+
+/* Define the Client request structure. */
+typedef struct NX_RTSP_CLIENT_REQUEST_STRUCT
+{
+ UINT nx_rtsp_client_request_method; /* OPTION/SETUP/DESCRIBE/PLAY/PAUSE/TEARDOWN/SET_PARAMETER. */
+
+ UINT nx_rtsp_client_request_sequence_number; /* Current Client sequence number. */
+
+ UCHAR *nx_rtsp_client_request_uri_ptr; /* Request URI name. */
+ UINT nx_rtsp_client_request_uri_length; /* Request URI length. */
+
+ UCHAR *nx_rtsp_client_request_range_ptr; /* Range field, needed for holding the PLAY and PAUSE method. */
+ UINT nx_rtsp_client_request_range_length; /* Range field length. */
+
+ ULONG nx_rtsp_client_request_session_id; /* Session id for request method. */
+
+ UINT nx_rtsp_client_request_response_code; /* Response status code. */
+
+ NX_RTSP_TRANSPORT nx_rtsp_client_request_transport; /* Transport structure. */
+} NX_RTSP_CLIENT_REQUEST;
+
+/* Define the Client data structure. */
+typedef struct NX_RTSP_CLIENT_STRUCT
+{
+ UCHAR nx_rtsp_client_valid; /* This entry is valid or not. */
+
+ UCHAR nx_rtsp_client_state; /* The state a Client is in: INIT/READY/PLAYING. See page 77 RFC 2326. */
+
+ UCHAR nx_rtsp_client_reserved[2]; /* Reserved. */
+
+ NX_TCP_SOCKET nx_rtsp_client_socket; /* The socket for incoming request. */
+
+ ULONG nx_rtsp_client_request_activity_timeout; /* Timeout for Client activity. */
+
+ ULONG nx_rtsp_client_session_id; /* Session ID, assigned by RTSP, in host byte order. */
+
+ struct NX_RTSP_SERVER_STRUCT *nx_rtsp_client_server_ptr; /* Pointer to the RTSP Server. */
+
+ NX_RTSP_CLIENT_REQUEST *nx_rtsp_client_request_ptr; /* Pointer to the current Client request. */
+
+ NX_RTSP_CLIENT_REQUEST nx_rtsp_client_request; /* The stored client request. */
+
+ NX_PACKET *nx_rtsp_client_request_packet; /* The request packet received from Client. */
+
+ UINT nx_rtsp_client_request_bytes_total; /* The total bytes of the request. */
+
+ UINT nx_rtsp_client_request_content_length; /* The content length of the request. */
+
+ NX_PACKET *nx_rtsp_client_response_packet; /* The response packet will be send to Client. */
+
+ UINT nx_rtsp_client_npt_start; /* The start time in milliseconds of the NPT. */
+ UINT nx_rtsp_client_npt_end; /* The end time in milliseconds of the NPT. */
+} NX_RTSP_CLIENT;
+
+/* Define the method callbacks structure. */
+typedef struct NX_RTSP_SERVER_METHOD_CALLBACKS_STRUCT
+{
+ UINT (*nx_rtsp_server_method_describe_callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length);
+
+ UINT (*nx_rtsp_server_method_setup_callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, NX_RTSP_TRANSPORT *transport_ptr);
+
+ UINT (*nx_rtsp_server_method_play_callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length);
+
+ UINT (*nx_rtsp_server_method_teardown_callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length);
+
+ UINT (*nx_rtsp_server_method_pause_callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length);
+
+ UINT (*nx_rtsp_server_method_set_parameter_callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *parameter_ptr, ULONG parameter_length);
+} NX_RTSP_SERVER_METHOD_CALLBACKS;
+
+/* Define the Server structure. */
+typedef struct NX_RTSP_SERVER_STRUCT
+{
+ ULONG nx_rtsp_server_id; /* The ID of RTSP Server. */
+
+ CHAR *nx_rtsp_server_name; /* The name of RTSP Server. */
+
+ UINT nx_rtsp_server_name_length; /* The length of RTSP Server's name. */
+
+ TX_THREAD nx_rtsp_server_thread; /* RTSP Server thread. */
+
+ TX_TIMER nx_rtsp_server_timer; /* Timer for Client activity. */
+
+ TX_EVENT_FLAGS_GROUP nx_rtsp_server_event_flags; /* Event flags. */
+
+ NX_IP *nx_rtsp_server_ip_ptr; /* Pointer to the IP instance. */
+
+ USHORT nx_rtsp_server_port; /* RTSP Server port. */
+
+ UCHAR nx_rtsp_server_started; /* The RTSP Server is started or not. */
+
+ UCHAR nx_rtsp_server_reserved; /* Reserved. */
+
+ NX_PACKET_POOL *nx_rtsp_server_packet_pool; /* Packet Pool for packet allocation. */
+
+ /* Infos recorded in RTSP Server procedures. */
+ ULONG nx_rtsp_server_allocation_errors;
+ ULONG nx_rtsp_server_relisten_errors;
+ ULONG nx_rtsp_server_disconnection_requests;
+ UINT nx_rtsp_server_connected_client_count;
+
+ /* Data structure for all the Clients connected to the RTSP Server. */
+ NX_RTSP_CLIENT nx_rtsp_server_client_list[NX_RTSP_SERVER_MAX_CLIENTS];
+
+ /* The callbacks for the received methods and disconnection. */
+ UINT (*nx_rtsp_server_disconnect_callback)(NX_RTSP_CLIENT *rtsp_client_ptr);
+ NX_RTSP_SERVER_METHOD_CALLBACKS nx_rtsp_server_method_callbacks;
+} NX_RTSP_SERVER;
+
+#ifndef NX_RTSP_SERVER_SOURCE_CODE
+
+/* Application caller is present, perform API mapping. */
+
+/* Determine if error checking is desired. If so, map API functions
+ to the appropriate error checking front-ends. Otherwise, map API
+ functions to the core functions that actually perform the work.
+ Note: error checking is enabled by default. */
+#ifdef NX_DISABLE_ERROR_CHECKING
+
+/* Services without error checking. */
+#define nx_rtsp_server_create _nx_rtsp_server_create
+#define nx_rtsp_server_delete _nx_rtsp_server_delete
+#define nx_rtsp_server_start _nx_rtsp_server_start
+#define nx_rtsp_server_stop _nx_rtsp_server_stop
+
+#define nx_rtsp_server_describe_callback_set _nx_rtsp_server_describe_callback_set
+#define nx_rtsp_server_setup_callback_set _nx_rtsp_server_setup_callback_set
+#define nx_rtsp_server_play_callback_set _nx_rtsp_server_play_callback_set
+#define nx_rtsp_server_pause_callback_set _nx_rtsp_server_pause_callback_set
+#define nx_rtsp_server_teardown_callback_set _nx_rtsp_server_teardown_callback_set
+#define nx_rtsp_server_set_parameter_callback_set _nx_rtsp_server_set_parameter_callback_set
+
+#define nx_rtsp_server_sdp_set _nx_rtsp_server_sdp_set
+#define nx_rtsp_server_rtp_info_set _nx_rtsp_server_rtp_info_set
+#define nx_rtsp_server_range_npt_set _nx_rtsp_server_range_npt_set
+
+#define nx_rtsp_server_keepalive_update _nx_rtsp_server_keepalive_update
+#define nx_rtsp_server_error_response_send _nx_rtsp_server_error_response_send
+
+#else
+
+/* Services with error checking. */
+#define nx_rtsp_server_create _nxe_rtsp_server_create
+#define nx_rtsp_server_delete _nxe_rtsp_server_delete
+#define nx_rtsp_server_start _nxe_rtsp_server_start
+#define nx_rtsp_server_stop _nxe_rtsp_server_stop
+
+#define nx_rtsp_server_describe_callback_set _nxe_rtsp_server_describe_callback_set
+#define nx_rtsp_server_setup_callback_set _nxe_rtsp_server_setup_callback_set
+#define nx_rtsp_server_play_callback_set _nxe_rtsp_server_play_callback_set
+#define nx_rtsp_server_pause_callback_set _nxe_rtsp_server_pause_callback_set
+#define nx_rtsp_server_teardown_callback_set _nxe_rtsp_server_teardown_callback_set
+#define nx_rtsp_server_set_parameter_callback_set _nxe_rtsp_server_set_parameter_callback_set
+
+#define nx_rtsp_server_sdp_set _nxe_rtsp_server_sdp_set
+#define nx_rtsp_server_rtp_info_set _nxe_rtsp_server_rtp_info_set
+#define nx_rtsp_server_range_npt_set _nxe_rtsp_server_range_npt_set
+
+#define nx_rtsp_server_keepalive_update _nxe_rtsp_server_keepalive_update
+#define nx_rtsp_server_error_response_send _nxe_rtsp_server_error_response_send
+
+#endif /* NX_DISABLE_ERROR_CHECKING */
+
+/* Define the prototypes accessible to the application software. */
+
+UINT nx_rtsp_server_describe_callback_set(NX_RTSP_SERVER * rtsp_server,
+ UINT (*)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length));
+
+UINT nx_rtsp_server_setup_callback_set(NX_RTSP_SERVER * rtsp_server,
+ UINT (*)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, NX_RTSP_TRANSPORT *transport_ptr));
+
+UINT nx_rtsp_server_play_callback_set(NX_RTSP_SERVER * rtsp_server,
+ UINT (*)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length));
+
+UINT nx_rtsp_server_teardown_callback_set(NX_RTSP_SERVER * rtsp_server,
+ UINT (*)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length));
+
+
+UINT nx_rtsp_server_pause_callback_set(NX_RTSP_SERVER * rtsp_server,
+ UINT (*)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length));
+
+UINT nx_rtsp_server_set_parameter_callback_set(NX_RTSP_SERVER * rtsp_server,
+ UINT (*)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *parameter_ptr, ULONG parameter_length));
+
+UINT nx_rtsp_server_create(NX_RTSP_SERVER *rtsp_server_ptr, CHAR *server_name, UINT server_name_length,
+ NX_IP *ip_ptr, NX_PACKET_POOL *rtsp_packet_pool, VOID *stack_ptr, ULONG stack_size, UINT priority, UINT server_port,
+ UINT (*disconnect_callback)(NX_RTSP_CLIENT *rtsp_client_ptr));
+
+UINT nx_rtsp_server_delete(NX_RTSP_SERVER *rtsp_server);
+
+UINT nx_rtsp_server_start(NX_RTSP_SERVER *rtsp_server);
+
+UINT nx_rtsp_server_stop(NX_RTSP_SERVER *rtsp_server);
+
+/* Called in DESCRIBE callback function to set SDP string. */
+UINT nx_rtsp_server_sdp_set(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *sdp_string, UINT sdp_length);
+
+/* Called in PLAY callback function to set RTP-Info field, including the RTP sequence number and RTP timestamp. */
+UINT nx_rtsp_server_rtp_info_set(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *track_id, UINT track_id_len, UINT rtp_seq, UINT rtp_time);
+
+/* Called in PLAY and PAUSE callback functions to set the NPT start and end time in Range field. */
+UINT nx_rtsp_server_range_npt_set(NX_RTSP_CLIENT *rtsp_client_ptr, UINT npt_start, UINT npt_end);
+
+/* If received RTCP reports, call this API to update the keepalive timeout. https://www.rfc-editor.org/rfc/rfc2326#appendix-A.2. */
+UINT nx_rtsp_server_keepalive_update(NX_RTSP_CLIENT *rtsp_client_ptr);
+
+UINT nx_rtsp_server_error_response_send(NX_RTSP_CLIENT *rtsp_client_ptr, UINT status_code);
+
+#else
+
+/* Define the prototypes accessible to the application software. */
+
+UINT _nx_rtsp_server_describe_callback_set(NX_RTSP_SERVER * rtsp_server,
+ UINT (*)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length));
+UINT _nxe_rtsp_server_describe_callback_set(NX_RTSP_SERVER * rtsp_server,
+ UINT (*)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length));
+
+UINT _nx_rtsp_server_setup_callback_set(NX_RTSP_SERVER * rtsp_server,
+ UINT (*)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, NX_RTSP_TRANSPORT *transport_ptr));
+UINT _nxe_rtsp_server_setup_callback_set(NX_RTSP_SERVER * rtsp_server,
+ UINT (*)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, NX_RTSP_TRANSPORT *transport_ptr));
+
+UINT _nx_rtsp_server_play_callback_set(NX_RTSP_SERVER * rtsp_server,
+ UINT (*)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length));
+UINT _nxe_rtsp_server_play_callback_set(NX_RTSP_SERVER * rtsp_server,
+ UINT (*)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length));
+
+UINT _nx_rtsp_server_teardown_callback_set(NX_RTSP_SERVER * rtsp_server,
+ UINT (*)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length));
+UINT _nxe_rtsp_server_teardown_callback_set(NX_RTSP_SERVER * rtsp_server,
+ UINT (*)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length));
+
+UINT _nx_rtsp_server_pause_callback_set(NX_RTSP_SERVER * rtsp_server,
+ UINT (*)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length));
+UINT _nxe_rtsp_server_pause_callback_set(NX_RTSP_SERVER * rtsp_server,
+ UINT (*)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length));
+
+
+UINT _nx_rtsp_server_set_parameter_callback_set(NX_RTSP_SERVER * rtsp_server,
+ UINT (*)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *parameter_ptr, ULONG parameter_length));
+UINT _nxe_rtsp_server_set_parameter_callback_set(NX_RTSP_SERVER * rtsp_server,
+ UINT (*)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *parameter_ptr, ULONG parameter_length));
+
+UINT _nx_rtsp_server_create(NX_RTSP_SERVER *rtsp_server_ptr, CHAR *server_name, UINT server_name_length,
+ NX_IP *ip_ptr, NX_PACKET_POOL *rtsp_packet_pool, VOID *stack_ptr, ULONG stack_size, UINT priority, UINT server_port,
+ UINT (*disconnect_callback)(NX_RTSP_CLIENT *rtsp_client_ptr));
+UINT _nxe_rtsp_server_create(NX_RTSP_SERVER *rtsp_server_ptr, CHAR *server_name, UINT server_name_length,
+ NX_IP *ip_ptr, NX_PACKET_POOL *rtsp_packet_pool, VOID *stack_ptr, ULONG stack_size, UINT priority, UINT server_port,
+ UINT (*disconnect_callback)(NX_RTSP_CLIENT *rtsp_client_ptr));
+
+UINT _nx_rtsp_server_delete(NX_RTSP_SERVER *rtsp_server);
+UINT _nxe_rtsp_server_delete(NX_RTSP_SERVER *rtsp_server);
+
+UINT _nx_rtsp_server_start(NX_RTSP_SERVER *rtsp_server);
+UINT _nxe_rtsp_server_start(NX_RTSP_SERVER *rtsp_server);
+
+UINT _nx_rtsp_server_stop(NX_RTSP_SERVER *rtsp_server);
+UINT _nxe_rtsp_server_stop(NX_RTSP_SERVER *rtsp_server);
+
+/* Called in DESCRIBE callback function to set SDP string. */
+UINT _nx_rtsp_server_sdp_set(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *sdp_string, UINT sdp_length);
+UINT _nxe_rtsp_server_sdp_set(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *sdp_string, UINT sdp_length);
+
+/* Called in PLAY callback function to set RTP-Info field, including the RTP sequence number and RTP timestamp. */
+UINT _nx_rtsp_server_rtp_info_set(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *track_id, UINT track_id_len, UINT rtp_seq, UINT rtp_time);
+UINT _nxe_rtsp_server_rtp_info_set(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *track_id, UINT track_id_len, UINT rtp_seq, UINT rtp_time);
+
+/* Called in PLAY and PAUSE callback functions to set the NPT start and end time in Range field. */
+UINT _nx_rtsp_server_range_npt_set(NX_RTSP_CLIENT *rtsp_client_ptr, UINT npt_start, UINT npt_end);
+UINT _nxe_rtsp_server_range_npt_set(NX_RTSP_CLIENT *rtsp_client_ptr, UINT npt_start, UINT npt_end);
+
+/* If received RTCP reports, call this API to update the keepalive timeout. https://www.rfc-editor.org/rfc/rfc2326#appendix-A.2. */
+UINT _nx_rtsp_server_keepalive_update(NX_RTSP_CLIENT *rtsp_client_ptr);
+UINT _nxe_rtsp_server_keepalive_update(NX_RTSP_CLIENT *rtsp_client_ptr);
+
+UINT _nx_rtsp_server_error_response_send(NX_RTSP_CLIENT *rtsp_client_ptr, UINT status_code);
+UINT _nxe_rtsp_server_error_response_send(NX_RTSP_CLIENT *rtsp_client_ptr, UINT status_code);
+
+#endif /* NX_RTSP_SERVER_SOURCE_CODE */
+
+
+/* Determine if a C++ compiler is being used. If so, complete the standard
+ C conditional started above. */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NX_RTSP_SERVER_H */
+
diff --git a/addons/smtp/nxd_smtp_client.c b/addons/smtp/nxd_smtp_client.c
index 2c010c07..a73b5ff8 100644
--- a/addons/smtp/nxd_smtp_client.c
+++ b/addons/smtp/nxd_smtp_client.c
@@ -3404,7 +3404,7 @@ UINT first_digit_server_reply;
/* FUNCTION RELEASE */
/* */
/* _nx_smtp_utility_read_server_code PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -3447,6 +3447,9 @@ UINT first_digit_server_reply;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), */
+/* avoided invalid release, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_smtp_utility_read_server_code(NX_SMTP_CLIENT *client_ptr, ULONG timeout, UINT receive_all_lines)
@@ -3518,6 +3521,7 @@ UINT buffer_length;
/* No, it wasn't. */
nx_packet_release(packet_ptr);
+ client_ptr -> nx_smtp_server_packet = NX_NULL;
/* Set session state to QUIT. */
client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_QUIT;
diff --git a/addons/snmp/nxd_snmp.c b/addons/snmp/nxd_snmp.c
index c9453b36..9de3e81c 100644
--- a/addons/snmp/nxd_snmp.c
+++ b/addons/snmp/nxd_snmp.c
@@ -3464,8 +3464,7 @@ UINT _nx_snmp_agent_stop(NX_SNMP_AGENT *agent_ptr)
/* nx_packet_release Release original SNMP packet */
/* _nx_snmp_utility_sequence_get Get sequence number in packet */
/* _nx_snmp_utility_version_get Get SNMP version number */
-/* _nx_snmp_version_1_process Process SNMP v1 request */
-/* _nx_snmp_version_2_process Process SNMP v2 request */
+/* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/
/* _nx_snmp_version_3_process Process SNMP v3 request */
/* nx_udp_socket_receive Receive SNMP request */
/* nx_udp_source_extract Extract source IP and port */
@@ -3637,7 +3636,7 @@ NX_PACKET *new_packet_ptr;
agent_ptr -> nx_snmp_agent_current_version = version;
/* Process SNMP Version 1 request. */
- _nx_snmp_version_1_process(agent_ptr, packet_ptr);
+ _nx_snmp_version_1_and_2_process(agent_ptr, packet_ptr);
}
#else
@@ -3674,7 +3673,7 @@ NX_PACKET *new_packet_ptr;
/* Process SNMP Version 2 request. */
- _nx_snmp_version_2_process(agent_ptr, packet_ptr);
+ _nx_snmp_version_1_and_2_process(agent_ptr, packet_ptr);
}
#else
@@ -13665,8 +13664,7 @@ ULONG *value_ptr;
/* */
/* CALLED BY */
/* */
-/* _nx_snmp_version_1_process SNMP v1 request processing */
-/* _nx_snmp_version_2_process SNMP v2 request processing */
+/* _nx_snmp_version_1_and_2_process SNMP v1, v2 request processing*/
/* */
/* RELEASE HISTORY */
/* */
@@ -13836,8 +13834,7 @@ UINT total;
/* */
/* _nx_snmp_agent_trap_send Send SNMP v1 trap */
/* _nx_snmp_agent_trapv2_send Send SNMP v2 trap */
-/* _nx_snmp_version_1_process Process SNMP v1 request */
-/* _nx_snmp_version_2_process Process SNMP v2 request */
+/* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/
/* */
/* RELEASE HISTORY */
/* */
@@ -13951,8 +13948,7 @@ UINT length;
/* */
/* CALLED BY */
/* */
-/* _nx_snmp_version_1_process Process SNMP v1 request */
-/* _nx_snmp_version_2_process Process SNMP v2 request */
+/* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/
/* _nx_snmp_version_3_process Process SNMP v3 request */
/* */
/* RELEASE HISTORY */
@@ -14045,8 +14041,7 @@ UINT _nx_snmp_utility_error_info_get(UCHAR *buffer_ptr, UINT *error_code, UINT
/* _nx_snmp_agent_trapv2_send Send SNMP v2 trap */
/* _nx_snmp_agent_trapv3_send Send SNMP v3 trap */
/* _nx_snmp_version_error_response Send error response to Manager*/
-/* _nx_snmp_version_1_process Process SNMP v1 request */
-/* _nx_snmp_version_2_process Process SNMP v2 request */
+/* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/
/* _nx_snmp_version_3_report_send Send SNMP v3 report */
/* _nx_snmp_version_3_process Process SNMP v3 request */
/* */
@@ -14122,8 +14117,7 @@ UINT _nx_snmp_utility_error_info_set(UCHAR *buffer_ptr, UINT error_code, UINT e
/* CALLED BY */
/* */
/* _nx_snmp_utility_object_data_get Get object data */
-/* _nx_snmp_version_1_process Process SNMP v1 request */
-/* _nx_snmp_version_2_process Process SNMP v2 request */
+/* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/
/* _nx_snmp_version_3_process Process SNMP v3 request */
/* */
/* RELEASE HISTORY */
@@ -14475,7 +14469,7 @@ UINT string_length;
/* FUNCTION RELEASE */
/* */
/* _nx_snmp_utility_object_id_set PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -14507,8 +14501,7 @@ UINT string_length;
/* _nx_snmp_agent_trapv2_send SNMP v2 trap send */
/* _nx_snmp_agent_trapv3_send SNMP v3 trap send */
/* _nx_snmp_utility_object_data_set Object data set */
-/* _nx_snmp_version_1_process Process SNMP v1 request */
-/* _nx_snmp_version_2_process Process SNMP v2 request */
+/* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/
/* _nx_snmp_version_3_process Process SNMP v3 request */
/* */
/* RELEASE HISTORY */
@@ -14518,6 +14511,9 @@ UINT string_length;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 10-31-2023 Bo Chen Modified comment(s), improved */
+/* buffer length verification, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_snmp_utility_object_id_set(UCHAR *buffer_ptr, UCHAR *object_string, UCHAR *buffer_end)
@@ -14607,6 +14603,10 @@ UINT object_string_length;
value = value + 80;
}
+ /* Check for the end of the buffer. */
+ if (buffer_ptr >= buffer_end)
+ return(0);
+
/* Set the first byte, which is the combination of the first two bytes. */
*buffer_ptr++ = (UCHAR) value;
@@ -15171,8 +15171,7 @@ UCHAR encoding_started;
/* */
/* CALLED BY */
/* */
-/* _nx_snmp_version_1_process Process SNMP v1 request */
-/* _nx_snmp_version_2_process Process SNMP v2 request */
+/* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/
/* _nx_snmp_version_3_process Process SNMP v3 request */
/* */
/* RELEASE HISTORY */
@@ -15419,8 +15418,7 @@ UINT status;
/* _nx_snmp_agent_trap_send Send SNMP v1 Trap */
/* _nx_snmp_agent_trapv2_send Send SNMP v2 Trap */
/* _nx_snmp_agent_trapv3_send Send SNMP v3 Trap */
-/* _nx_snmp_version_1_process Process SNMP v1 request */
-/* _nx_snmp_version_2_process Process SNMP v2 request */
+/* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/
/* _nx_snmp_version_3_process Process SNMP v3 request */
/* */
/* RELEASE HISTORY */
@@ -16071,8 +16069,7 @@ UINT header_size;
/* CALLED BY */
/* */
/* _nx_snmp_agent_thread_entry SNMP Agent's thread entry */
-/* _nx_snmp_version_1_process Process SNMP v1 request */
-/* _nx_snmp_version_2_process Process SNMP v2 request */
+/* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/
/* _nx_snmp_version_3_process Process SNMP v3 request */
/* */
/* RELEASE HISTORY */
@@ -16204,8 +16201,7 @@ UCHAR byte;
/* _nx_snmp_agent_trap_send Send SNMP v1 trap */
/* _nx_snmp_agent_trapv2_send Send SNMP v2 trap */
/* _nx_snmp_agent_trapv3_send Send SNMP v3 trap */
-/* _nx_snmp_version_1_process Process SNMP v1 request */
-/* _nx_snmp_version_2_process Process SNMP v2 request */
+/* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/
/* _nx_snmp_version_3_report_send Send SNMP v3 report */
/* _nx_snmp_version_3_process Process SNMP v3 request */
/* */
@@ -16339,8 +16335,7 @@ UINT _nx_snmp_utility_sequence_set_1byte(UCHAR *buffer_ptr, UINT sequence_value
/* */
/* CALLED BY */
/* */
-/* _nx_snmp_version_1_process Process SNMP v1 request */
-/* _nx_snmp_version_2_process Process SNMP v2 request */
+/* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/
/* _nx_snmp_version_3_process Process SNMP v3 request */
/* */
/* RELEASE HISTORY */
@@ -16453,8 +16448,7 @@ UCHAR byte;
/* */
/* _nx_snmp_agent_trapv2_send Send SNMP v2 trap */
/* _nx_snmp_agent_trapv3_send Send SNMP v3 trap */
-/* _nx_snmp_version_1_process Process SNMP v1 request */
-/* _nx_snmp_version_2_process Process SNMP v2 request */
+/* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/
/* _nx_snmp_version_3_report_send Send SNMP v3 report */
/* _nx_snmp_version_3_report_send Send SNMP v3 report */
/* _nx_snmp_version_3_process Process SNMP v3 request */
@@ -16593,8 +16587,7 @@ UINT length;
/* */
/* CALLED BY */
/* */
-/* _nx_snmp_version_1_process Process SNMP v1 request */
-/* _nx_snmp_version_2_process Process SNMP v2 request */
+/* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/
/* _nx_snmp_version_3_process Process SNMP v3 request */
/* */
/* RELEASE HISTORY */
@@ -16733,8 +16726,7 @@ UCHAR byte;
/* _nx_snmp_agent_trap_send Send SNMP v1 trap */
/* _nx_snmp_agent_trapv2_send Send SNMP v2 trap */
/* _nx_snmp_agent_trapv3_send Send SNMP v3 trap */
-/* _nx_snmp_version_1_process Process SNMP v1 request */
-/* _nx_snmp_version_2_process Process SNMP v2 request */
+/* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/
/* _nx_snmp_version_3_report_send Send SNMP v3 report */
/* _nx_snmp_version_3_process Process SNMP v3 request */
/* */
@@ -16801,8 +16793,7 @@ UINT _nx_snmp_utility_request_type_set_1byte(UCHAR *buffer_ptr, UINT request_ty
/* */
/* CALLED BY */
/* */
-/* _nx_snmp_version_1_process Process SNMP v1 request */
-/* _nx_snmp_version_2_process Process SNMP v2 request */
+/* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/
/* _nx_snmp_version_3_process Process SNMP v3 request */
/* */
/* RELEASE HISTORY */
@@ -16872,8 +16863,7 @@ UINT _nx_snmp_utility_request_type_set_multibyte(UCHAR *buffer_ptr, UINT reques
/* CALLED BY */
/* */
/* _nx_snmp_agent_thread_entry SNMP Agent's thread entry */
-/* _nx_snmp_version_1_process Process SNMP v1 request */
-/* _nx_snmp_version_2_process Process SNMP v2 request */
+/* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/
/* _nx_snmp_version_3_process Process SNMP v3 request */
/* */
/* RELEASE HISTORY */
@@ -16961,8 +16951,7 @@ UINT _nx_snmp_utility_version_get(UCHAR *buffer_ptr, UINT *snmp_version, INT bu
/* _nx_snmp_agent_trap_send Send SNMP v1 trap */
/* _nx_snmp_agent_trapv2_send Send SNMP v2 trap */
/* _nx_snmp_agent_trapv3_send Send SNMP v3 trap */
-/* _nx_snmp_version_1_process Process SNMP v1 request */
-/* _nx_snmp_version_2_process Process SNMP v2 request */
+/* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/
/* _nx_snmp_version_3_report_send Send SNMP v3 report */
/* _nx_snmp_version_3_process Process SNMP v3 request */
/* */
@@ -17035,8 +17024,7 @@ UINT _nx_snmp_utility_version_set(UCHAR *buffer_ptr, UINT snmp_version, UCHAR *
/* */
/* CALLED BY */
/* */
-/* _nx_snmp_version_1_process SNMP v1 message processing */
-/* _nx_snmp_version_2_process SNMP v2 message processing */
+/* _nx_snmp_version_1_and_2_process Process SNMP v1 and v2 request*/
/* _nx_snmp_version_3_process SNMP v3 message processing */
/* */
/* RELEASE HISTORY */
@@ -17167,13 +17155,13 @@ ULONG temp;
return;
}
-#ifndef NX_SNMP_DISABLE_V1
+#if !defined(NX_SNMP_DISABLE_V1) && !defined(NX_SNMP_DISABLE_V2)
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
-/* _nx_snmp_version_1_process PORTABLE C */
-/* 6.1 */
+/* _nx_snmp_version_1_and_2_process PORTABLE C */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -17224,22 +17212,21 @@ ULONG temp;
/* */
/* DATE NAME DESCRIPTION */
/* */
-/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
-/* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
-/* variable len verification, */
-/* resulting in version 6.1 */
+/* 10-31-2023 Bo Chen Initial Version 6.3.0 */
/* */
/**************************************************************************/
-VOID _nx_snmp_version_1_process(NX_SNMP_AGENT *agent_ptr, NX_PACKET *packet_ptr)
+VOID _nx_snmp_version_1_and_2_process(NX_SNMP_AGENT *agent_ptr, NX_PACKET *packet_ptr)
{
UINT sequence_length, version, request_type, request_length;
-UINT error_code, error_index;
+UINT non_repeaters, max_repetitions, next_object;
+#ifndef NX_SNMP_DISABLE_V2
+UINT current_repetitions;
+#endif /* NX_SNMP_DISABLE_V2 */
UINT variable_list_length, variable_length;
ULONG request_id;
UINT status, length, objects;
UCHAR *buffer_ptr;
-UCHAR *variable_start_ptr = NX_NULL;
UCHAR *error_ptr, *request_type_ptr;
UINT response_length;
UINT total_variable_length = 0;
@@ -17404,9 +17391,9 @@ INT buffer_length;
/* Save a pointer to the error string. */
error_ptr = buffer_ptr;
-
- /* Pickup the SNMP Error information. */
- length = _nx_snmp_utility_error_info_get(buffer_ptr, &error_code, &error_index, buffer_length);
+ /* Pickup the SNMP Error information. This is actually used to derive the GETBULK
+ information in SNMP V2 and above. */
+ length = _nx_snmp_utility_error_info_get(buffer_ptr, &non_repeaters, &max_repetitions, buffer_length);
/* Check for a valid packet. */
if (length == 0)
@@ -17438,9 +17425,11 @@ INT buffer_length;
}
#endif /* NX_DISABLE_PACKET_CHAIN */
+ /* Check to see if there is a username processing routine. */
if (agent_ptr -> nx_snmp_agent_username_process)
{
+ /* Yes, there is a callback routine to process the community/username. */
status = agent_ptr -> nx_snmp_agent_username_process(agent_ptr, agent_ptr -> nx_snmp_agent_current_community_string);
/* Determine if the callback routine generated an error. */
@@ -17450,1031 +17439,29 @@ INT buffer_length;
/* Increment the number of community/username errors. */
agent_ptr -> nx_snmp_agent_username_errors++;
-#ifdef NX_SNMP_V1_AUTHORIZATION_ERROR_RESPONSE
- /* Call the error handling response routine. */
- _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_NOSUCHNAME, 0);
-#else
- /* Authorization error response is not supported by version 1. */
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-#endif
-
- /* Done, return to caller. */
- return;
- }
- }
-
- /* Move the buffer pointer up. */
- buffer_ptr = buffer_ptr + length;
-
- /* The buffer pointer is moved by the length. Update buffer size */
- buffer_length -= (INT)length;
-
- /* Pickup the SNMP Variable list length. */
- length = _nx_snmp_utility_sequence_get(buffer_ptr, &variable_list_length, buffer_length);
-
- /* Check for a valid packet. */
- if (length == 0)
- {
-
- /* Increment the invalid packet error counter. */
- agent_ptr -> nx_snmp_agent_invalid_packets++;
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- /* Return to caller. */
- return;
- }
-
- /* Move the buffer pointer up. */
- buffer_ptr = buffer_ptr + length;
-
- /* The buffer pointer is moved by the length. Update buffer size */
- buffer_length -= (INT)length;
-
- /* At this point we have parsed the incoming SNMP request up to the first
- variable. */
-
- /* Now prepare response message so we can process the variables one by one. */
-
- /* Determine which packet type we allocate based on the destination address type. */
- if (agent_ptr -> nx_snmp_agent_current_manager_ip.nxd_ip_version == NX_IP_VERSION_V4)
- {
- packet_type = NX_IPv4_UDP_PACKET;
- }
- else if (agent_ptr -> nx_snmp_agent_current_manager_ip.nxd_ip_version == NX_IP_VERSION_V6)
- {
-
-#ifndef FEATURE_NX_IPV6
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- return;
-#else
- packet_type = NX_IPv6_UDP_PACKET;
-#endif /* FEATURE_NX_IPV6 */
- }
- else
- {
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- return;
- }
-
- /* Allocate the packet for the SNMP response. */
- status = nx_packet_allocate(agent_ptr -> nx_snmp_agent_packet_pool_ptr, &response_packet_ptr, packet_type, NX_SNMP_AGENT_TIMEOUT);
-
- /* Determine if a response packet was allocated. */
- if (status)
- {
-
- /* Increment the packet allocation error counter. */
- agent_ptr -> nx_snmp_agent_allocation_errors++;
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- /* Return to caller. */
- return;
- }
-
- memset(response_packet_ptr -> nx_packet_prepend_ptr, 0,
- (UINT)(response_packet_ptr -> nx_packet_data_end - response_packet_ptr -> nx_packet_prepend_ptr));
-
- /* Initialize the counters required for the length fields of the response packet. */
- response_sequence_length = 0;
- response_type_length = 0;
- response_variable_list_length = 0;
-
- /* Setup a pointer to the response packet's buffer area. */
- response_buffer_ptr = response_packet_ptr -> nx_packet_prepend_ptr;
-
- /* This is also the response sequence pointer. Remember it since we are going to have to
- update it later with the actual length of the response. */
- response_sequence_ptr = response_buffer_ptr;
-
- /* First, write the sequence in the response packet. A zero is written for now. This will be
- updated later. */
- response_length = _nx_snmp_utility_sequence_set(response_buffer_ptr, 0, response_packet_ptr -> nx_packet_data_end);
-
- /* Check for a valid operation. */
- if (response_length == 0)
- {
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- /* Release the response packet too. */
- nx_packet_release(response_packet_ptr);
-
- /* Return to caller. */
- return;
- }
-
- /* Move the response buffer pointer up. */
- response_buffer_ptr = response_buffer_ptr + response_length;
-
- /* Now set the SNMP version in the response. */
- response_length = _nx_snmp_utility_version_set(response_buffer_ptr, NX_SNMP_VERSION_1, response_packet_ptr -> nx_packet_data_end);
-
- /* Check for a valid operation. */
- if (response_length == 0)
- {
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- /* Release the response packet too. */
- nx_packet_release(response_packet_ptr);
-
- /* Return to caller. */
- return;
- }
-
- /* Move the response buffer pointer up. */
- response_buffer_ptr = response_buffer_ptr + response_length;
-
- /* Adjust the response sequence length. */
- response_sequence_length = response_sequence_length + response_length;
-
- /* Set the SNMP community in the response message. */
- response_length = _nx_snmp_utility_community_set(response_buffer_ptr, agent_ptr -> nx_snmp_agent_current_community_string, response_packet_ptr -> nx_packet_data_end);
-
- /* Check for a valid operation. */
- if (response_length == 0)
- {
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- /* Release the response packet too. */
- nx_packet_release(response_packet_ptr);
-
- /* Return to caller. */
- return;
- }
-
- /* Move the response buffer pointer up. */
- response_buffer_ptr = response_buffer_ptr + response_length;
-
- /* Adjust the response sequence length. */
- response_sequence_length = response_sequence_length + response_length;
-
- /* Remember the request type pointer, since it will need to be updated later. */
- response_type_ptr = response_buffer_ptr;
-
- /* Now set the request type in the response message. */
- response_length = _nx_snmp_utility_request_type_set_multibyte(response_buffer_ptr, NX_SNMP_ANS1_GET_RESPONSE, 0, response_packet_ptr -> nx_packet_data_end);
-
- /* Check for a valid operation. */
- if (response_length == 0)
- {
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- /* Release the response packet too. */
- nx_packet_release(response_packet_ptr);
-
- /* Return to caller. */
- return;
- }
-
- /* Move the response buffer pointer up. */
- response_buffer_ptr = response_buffer_ptr + response_length;
-
- /* Adjust the response sequence length. */
- response_sequence_length = response_sequence_length + response_length;
-
- /* Now set the request ID in the response message. */
- response_length = _nx_snmp_utility_request_id_set(response_buffer_ptr, request_id, response_packet_ptr -> nx_packet_data_end);
-
- /* Check for a valid operation. */
- if (response_length == 0)
- {
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- /* Release the response packet too. */
- nx_packet_release(response_packet_ptr);
-
- /* Return to caller. */
- return;
- }
-
- /* Move the response buffer pointer up. */
- response_buffer_ptr = response_buffer_ptr + response_length;
-
- /* Adjust the response sequence length. */
- response_sequence_length = response_sequence_length + response_length;
-
- /* Adjust the response request type length. */
- response_type_length = response_type_length + response_length;
-
- /* Set the response error information. Assume everything is okay at this point. */
- response_length = _nx_snmp_utility_error_info_set(response_buffer_ptr, 0, 0, response_packet_ptr -> nx_packet_data_end);
-
- /* Check for a valid operation. */
- if (response_length == 0)
- {
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- /* Release the response packet too. */
- nx_packet_release(response_packet_ptr);
-
- /* Return to caller. */
- return;
- }
-
- /* Move the response buffer pointer up. */
- response_buffer_ptr = response_buffer_ptr + response_length;
-
- /* Adjust the response sequence length. */
- response_sequence_length = response_sequence_length + response_length;
-
- /* Adjust the response request type length. */
- response_type_length = response_type_length + response_length;
-
- /* Remember the start of the response's variable list field. */
- response_variable_list_ptr = response_buffer_ptr;
-
- /* Setup the variable list response. For now, the length will be zero. We
- will overwrite this with the actual length later. */
- response_length = _nx_snmp_utility_sequence_set(response_buffer_ptr, 0, response_packet_ptr -> nx_packet_data_end);
-
- /* Check for a valid operation. */
- if (response_length == 0)
- {
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- /* Release the response packet too. */
- nx_packet_release(response_packet_ptr);
-
- /* Return to caller. */
- return;
- }
-
- /* Move the response buffer pointer up. */
- response_buffer_ptr = response_buffer_ptr + response_length;
-
- /* Adjust the response sequence length. */
- response_sequence_length = response_sequence_length + response_length;
-
- /* Adjust the response request type length. */
- response_type_length = response_type_length + response_length;
-
- /* At this point the response buffer is setup to exactly the same position the
- SNMP Manager's input buffer is - right before the first variable. We can
- now walk through the variable list to process each request and place the
- result in the response buffer. */
- objects = 0;
- do
- {
-
- /* Remember the start of the variable. */
- variable_start_ptr = buffer_ptr;
-
- /* Pickup the first SNMP Variable length. */
- length = _nx_snmp_utility_sequence_get(buffer_ptr, &variable_length, buffer_length);
-
- /* Calculate the total variable size. */
- total_variable_length = variable_length + length;
-
- /* Determine if this variable will fit in the remaining length of the
- variable list, buffer length, and if there is integer overflow. */
- if ((length == 0) || (total_variable_length > variable_list_length) ||
- (total_variable_length < variable_length) || (total_variable_length > (UINT)buffer_length))
- {
-
- /* Increment the invalid packet error counter. */
- agent_ptr -> nx_snmp_agent_invalid_packets++;
-
- /* Release the response packet. */
- nx_packet_release(response_packet_ptr);
-
- /* Send an SNMP version error response. */
- _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_SUCCESS, objects+1);
-
- /* Return to caller. */
- return;
- }
-
- /* Move the buffer pointer up. */
- buffer_ptr = buffer_ptr + length;
-
- /* Update the size of the remaining buffer. */
- buffer_length -= (INT)length;
-
- /* Now pickup the object ID. */
- length = _nx_snmp_utility_object_id_get(buffer_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, buffer_length);
-
- /* Determine if the object retrieval was successful. */
- if (length == 0)
- {
-
- /* Increment the invalid packet error counter. */
- agent_ptr -> nx_snmp_agent_invalid_packets++;
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- /* Release the response packet. */
- nx_packet_release(response_packet_ptr);
-
- /* Return to caller. */
- return;
- }
-
- /* Move the buffer pointer up. */
- buffer_ptr = buffer_ptr + length;
-
- /* Update the size of the remaining buffer. */
- buffer_length -= (INT)length;
-
- /* Default the value to NULL. */
- agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type = 0;
-
- /* Determine if a value is present. */
- if (length != variable_length)
- {
-
- /* Pickup the value associated with this variable. */
- length = _nx_snmp_utility_object_data_get(buffer_ptr, &(agent_ptr -> nx_snmp_agent_current_object_data), buffer_length);
-
- /* Determine if the object value was successful. */
- if (length == 0)
+ /* Check the version. */
+ if (version == NX_SNMP_VERSION_1)
{
- /* Increment the invalid packet error counter. */
- agent_ptr -> nx_snmp_agent_invalid_packets++;
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Send an SNMP version error response. */
- _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_BADVALUE, objects+1);
-
+#ifdef NX_SNMP_V1_AUTHORIZATION_ERROR_RESPONSE
+ /* Call the error handling response routine. */
+ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_NOSUCHNAME, 0);
+#else
+ /* Authorization error response is not supported by version 1. */
/* Release the packet. */
nx_packet_release(packet_ptr);
-
- /* Release the response packet. */
- nx_packet_release(response_packet_ptr);
-
- /* Return to caller. */
- return;
+#endif
}
- }
-
- /* At this point, we are ready to call the appropriate application request handling routine.
- It is responsible for extracting or placing information in the object data structure. */
- if (request_type == NX_SNMP_ANS1_GET_REQUEST)
- {
-
- /* Increment the total number of get variables. */
- agent_ptr -> nx_snmp_agent_total_get_variables++;
-
- /* Call the application's GET routine. */
- status = (agent_ptr -> nx_snmp_agent_get_process)(agent_ptr, agent_ptr -> nx_snmp_agent_current_octet_string,
- &(agent_ptr -> nx_snmp_agent_current_object_data));
- }
- else if (request_type == NX_SNMP_ANS1_GET_NEXT_REQUEST)
- {
-
- /* Increment the total number of get variables. */
- agent_ptr -> nx_snmp_agent_total_get_variables++;
-
- /* Call the application's GETNEXT routine. */
- status = (agent_ptr -> nx_snmp_agent_getnext_process)(agent_ptr, agent_ptr -> nx_snmp_agent_current_octet_string,
- &(agent_ptr -> nx_snmp_agent_current_object_data));
- }
- else if (request_type == NX_SNMP_ANS1_SET_REQUEST)
- {
-
- /* Increment the total number of set variables. */
- agent_ptr -> nx_snmp_agent_total_set_variables++;
-
- /* Call the application's SET routine. */
- status = (agent_ptr -> nx_snmp_agent_set_process)(agent_ptr, agent_ptr -> nx_snmp_agent_current_octet_string,
- &(agent_ptr -> nx_snmp_agent_current_object_data));
- }
- else
- {
-
- /* Release the response packet. */
- nx_packet_release(response_packet_ptr);
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Done, return to caller. */
- return;
- }
-
- /* Check for an error status from the agent's request processing callback routine. */
- if (status)
- {
-
- /* Release the response packet. */
- nx_packet_release(response_packet_ptr);
-
- /* Per RFC2576 4.3 */
- switch(status)
+ else
{
- case NX_SNMP_SUCCESS:
- case NX_SNMP_ERROR_TOOBIG:
- /* Call the error handling response routine. */
- _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, status, objects+1);
- break;
- case NX_SNMP_ERROR_BADVALUE:
- case NX_SNMP_ERROR_WRONGVALUE:
- case NX_SNMP_ERROR_WRONGENCODING:
- case NX_SNMP_ERROR_WRONGTYPE:
- case NX_SNMP_ERROR_WRONGLENGTH:
- case NX_SNMP_ERROR_INCONSISTENTVALUE:
- /* Call the error handling response routine. */
- _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_BADVALUE, objects+1);
- break;
- case NX_SNMP_ERROR_NOSUCHNAME:
- case NX_SNMP_ERROR_NOACCESS:
- case NX_SNMP_ERROR_NOTWRITABLE:
- case NX_SNMP_ERROR_NOCREATION:
- case NX_SNMP_ERROR_INCONSISTENTNAME:
- case NX_SNMP_ERROR_AUTHORIZATION:
- /* Call the error handling response routine. */
- _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_NOSUCHNAME, objects+1);
- break;
- case NX_SNMP_ERROR_GENERAL:
- case NX_SNMP_ERROR_RESOURCEUNAVAILABLE:
- case NX_SNMP_ERROR_COMMITFAILED:
- case NX_SNMP_ERROR_UNDOFAILED:
+
/* Call the error handling response routine. */
- _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_GENERAL, objects+1);
- break;
- default:
- /* Release the packet. */
- nx_packet_release(packet_ptr);
+ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_AUTHORIZATION, 0);
}
/* Done, return to caller. */
return;
}
-
- /* Determine if the returning object is valid. */
- if ((agent_ptr -> nx_snmp_agent_current_octet_string[0] != '1') || (agent_ptr -> nx_snmp_agent_current_octet_string[1] != '.') || (agent_ptr -> nx_snmp_agent_current_octet_string[2] != '3') || (agent_ptr -> nx_snmp_agent_current_octet_string[3] != '.'))
- {
-
- /* Release the response packet. */
- nx_packet_release(response_packet_ptr);
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Done, return to caller. */
- return;
- }
-
- /* Now ensure the returning object type is supported in V1. */
- if ((agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_INTEGER) &&
- (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_OCTET_STRING) &&
- (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_NULL) &&
- (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_TIME_TICS) &&
- (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_GAUGE) &&
- (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_COUNTER) &&
- (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_COUNTER64) &&
- (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_IP_ADDRESS) &&
-#ifdef FEATURE_NX_IPV6
- (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_IPV6_ADDRESS) &&
-#endif
- (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_NSAP_ADDRESS) &&
- (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_OBJECT_ID))
- {
-
- /* Release the packet. */
- nx_packet_release(response_packet_ptr);
-
- /* Call the error handling response routine. */
- _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_NOSUCHNAME, objects + 1);
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Done, return to caller. */
- return;
- }
-
- /* Everything is okay, place the object and object data into the response buffer. */
-
- /* Remember the start of the variable response sequence. */
- response_variable_ptr = response_buffer_ptr;
-
- /* Clear the response variable size. */
- response_variable_length = 0;
-
- /* Determine if there is enough room in the destination for the variable sequence. */
- if ((response_buffer_ptr + 4) >= response_packet_ptr -> nx_packet_data_end)
- {
-
- /* Release the response packet. */
- nx_packet_release(response_packet_ptr);
-
- /* Call the error handling response routine. */
- _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_TOOBIG, objects+1);
-
- /* Done, return to caller. */
- return;
- }
-
- /* Setup the variable response sequence. For now, the length will be zero. We
- will overwrite this with the actual length later. */
- response_length = _nx_snmp_utility_sequence_set(response_buffer_ptr, 0, response_packet_ptr -> nx_packet_data_end);
-
- /* Check for a valid operation. */
- if (response_length == 0)
- {
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- /* Release the response packet too. */
- nx_packet_release(response_packet_ptr);
-
- /* Return to caller. */
- return;
- }
-
- /* Move the response buffer pointer up. */
- response_buffer_ptr = response_buffer_ptr + response_length;
-
- /* Adjust the response sequence length. */
- response_sequence_length = response_sequence_length + response_length;
-
- /* Adjust the response request type length. */
- response_type_length = response_type_length + response_length;
-
- /* Adjust the response variable list size. */
- response_variable_list_length = response_variable_list_length + response_length;
-
- /* Place the object into the response buffer. */
- response_length = _nx_snmp_utility_object_id_set(response_buffer_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, response_packet_ptr -> nx_packet_data_end);
-
- /* Check for a valid operation. */
- if (response_length == 0)
- {
-
- /* Release the response packet. */
- nx_packet_release(response_packet_ptr);
-
- /* Call the error handling response routine. */
- _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_TOOBIG, objects+1);
-
- /* Done, return to caller. */
- return;
- }
-
- /* Move the response buffer pointer up. */
- response_buffer_ptr = response_buffer_ptr + response_length;
-
- /* Adjust the response sequence length. */
- response_sequence_length = response_sequence_length + response_length;
-
- /* Adjust the response request type length. */
- response_type_length = response_type_length + response_length;
-
- /* Adjust the response variable list size. */
- response_variable_list_length = response_variable_list_length + response_length;
-
- /* Adjust the response variable size. */
- response_variable_length = response_variable_length + response_length;
-
- /* Insert the object's data into the response buffer. */
- response_length = _nx_snmp_utility_object_data_set(response_buffer_ptr, &(agent_ptr -> nx_snmp_agent_current_object_data), response_packet_ptr -> nx_packet_data_end);
-
- /* Check for a valid operation. */
- if (response_length == 0)
- {
-
- /* Release the response packet. */
- nx_packet_release(response_packet_ptr);
-
- /* Call the error handling response routine. */
- _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_TOOBIG, objects+1);
-
- /* Done, return to caller. */
- return;
- }
-
- /* Move the response buffer pointer up. */
- response_buffer_ptr = response_buffer_ptr + response_length;
-
- /* Adjust the response sequence length. */
- response_sequence_length = response_sequence_length + response_length;
-
- /* Adjust the response request type length. */
- response_type_length = response_type_length + response_length;
-
- /* Adjust the response variable list size. */
- response_variable_list_length = response_variable_list_length + response_length;
-
- /* Adjust the response variable size. */
- response_variable_length = response_variable_length + response_length;
-
- /* Now update the response variable sequence with the actual variable length. */
- _nx_snmp_utility_sequence_set(response_variable_ptr, response_variable_length, response_packet_ptr -> nx_packet_data_end);
-
- /* Adjust the pointer to the next variable. */
- buffer_ptr = variable_start_ptr + total_variable_length;
-
- /* Decrement the size of the variable list. */
- variable_list_length = variable_list_length - total_variable_length;
-
- /* Increment the object counter. */
- objects++;
-
- } while (variable_list_length);
-
- /* At this point, several response fields need to be updated with actual lengths. */
- _nx_snmp_utility_sequence_set(response_sequence_ptr, response_sequence_length, response_packet_ptr -> nx_packet_data_end);
- _nx_snmp_utility_sequence_set(response_variable_list_ptr, response_variable_list_length, response_packet_ptr -> nx_packet_data_end);
- _nx_snmp_utility_request_type_set_multibyte(response_type_ptr, NX_SNMP_ANS1_GET_RESPONSE, response_type_length, response_packet_ptr -> nx_packet_data_end);
-
- /* Now the response packet's pointers must be setup so it can be sent. */
- response_packet_ptr -> nx_packet_length = (ULONG)(response_buffer_ptr - response_packet_ptr -> nx_packet_prepend_ptr);
- response_packet_ptr -> nx_packet_append_ptr = response_buffer_ptr;
-
- /* Release the original request packet. */
- nx_packet_release(packet_ptr);
-
- /* Update various statistics. */
- agent_ptr -> nx_snmp_agent_total_bytes_received += packet_ptr -> nx_packet_length;
- agent_ptr -> nx_snmp_agent_total_bytes_sent += response_packet_ptr -> nx_packet_length;
- if (request_type == NX_SNMP_ANS1_GET_REQUEST)
- agent_ptr -> nx_snmp_agent_get_requests++;
- else if (request_type == NX_SNMP_ANS1_GET_NEXT_REQUEST)
- agent_ptr -> nx_snmp_agent_getnext_requests++;
- else if (request_type == NX_SNMP_ANS1_GET_BULK_REQUEST)
- agent_ptr -> nx_snmp_agent_getbulk_requests++;
- else if (request_type == NX_SNMP_ANS1_SET_REQUEST)
- agent_ptr -> nx_snmp_agent_set_requests++;
-
- /* Increment the sent packet counter. */
- agent_ptr -> nx_snmp_agent_packets_sent++;
-
- /* Increment the get responses sent counter. */
- agent_ptr -> nx_snmp_agent_getresponse_sent++;
-
- /* Send the response packet back to the requesting SNMP manager. */
- status = nxd_udp_socket_send(&(agent_ptr -> nx_snmp_agent_socket), response_packet_ptr,
- &(agent_ptr -> nx_snmp_agent_current_manager_ip),
- agent_ptr -> nx_snmp_agent_current_manager_port);
-
- /* Check for successful call. */
- if (status)
- {
-
- /* Release the packet. */
- nx_packet_release(response_packet_ptr);
- }
-}
-#endif /* NX_SNMP_DISABLE_V1 */
-
-
-#ifndef NX_SNMP_DISABLE_V2
-/**************************************************************************/
-/* */
-/* FUNCTION RELEASE */
-/* */
-/* _nx_snmp_version_2_process PORTABLE C */
-/* 6.1 */
-/* AUTHOR */
-/* */
-/* Yuxin Zhou, Microsoft Corporation */
-/* */
-/* DESCRIPTION */
-/* */
-/* This function processes the SNMP v2 request from the manager. */
-/* */
-/* INPUT */
-/* */
-/* agent_ptr Pointer to SNMP agent */
-/* packet_ptr Pointer to packet containing */
-/* the SNMP request */
-/* */
-/* OUTPUT */
-/* */
-/* None */
-/* */
-/* CALLS */
-/* */
-/* nx_packet_allocate Allocate response packet */
-/* nx_packet_release Release the packet */
-/* nx_udp_socket_send Send the UDP packet */
-/* _nx_snmp_utility_community_get Get the community name */
-/* _nx_snmp_utility_community_set Set the community name */
-/* _nx_snmp_utility_error_info_get Get the error information */
-/* _nx_snmp_utility_error_info_set Set the error information */
-/* _nx_snmp_utility_object_data_get Get the object data */
-/* _nx_snmp_utility_object_data_set Set the object data */
-/* _nx_snmp_utility_object_id_get Get the object ID */
-/* _nx_snmp_utility_object_id_set Set the object ID */
-/* _nx_snmp_utility_request_id_get Get the request ID */
-/* _nx_snmp_utility_request_id_set Set the request ID */
-/* _nx_snmp_utility_request_type_get Get the request type */
-/* _nx_snmp_utility_request_type_set_multibyte */
-/* Set trap request type */
-/* _nx_snmp_utility_sequence_get Get the ANS.1 sequence */
-/* _nx_snmp_utility_sequence_set Set the ANS.1 sequence */
-/* _nx_snmp_utility_version_get Get the SNMP version */
-/* _nx_snmp_utility_version_set Set the SNMP version */
-/* _nx_snmp_version_error_response Send SNMP Manager error */
-/* */
-/* CALLED BY */
-/* */
-/* _nx_snmp_agent_thread_entry SNMP Agent thread */
-/* */
-/* RELEASE HISTORY */
-/* */
-/* DATE NAME DESCRIPTION */
-/* */
-/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
-/* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
-/* variable len verification, */
-/* resulting in version 6.1 */
-/* */
-/**************************************************************************/
-VOID _nx_snmp_version_2_process(NX_SNMP_AGENT *agent_ptr, NX_PACKET *packet_ptr)
-{
-
-UINT sequence_length, version, request_type, request_length;
-UINT non_repeaters, max_repetitions, current_repetitions, next_object;
-UINT variable_list_length, variable_length;
-ULONG request_id;
-UINT status, length, objects;
-UCHAR *buffer_ptr;
-UCHAR *variable_start_ptr = NX_NULL;
-UCHAR *error_ptr, *request_type_ptr;
-UINT response_length;
-UINT total_variable_length = 0;
-NX_PACKET *response_packet_ptr;
-UCHAR *response_buffer_ptr;
-UINT response_sequence_length, response_type_length;
-UINT response_variable_list_length, response_variable_length;
-UCHAR *response_sequence_ptr, *response_type_ptr;
-UCHAR *response_variable_list_ptr, *response_variable_ptr;
-UINT packet_type;
-INT buffer_length;
-
- buffer_length = (INT)(packet_ptr -> nx_packet_length);
-
- /* Setup a pointer to the buffer. */
- buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
-
- /* Pickup the SEQUENCE field. */
- length = _nx_snmp_utility_sequence_get(buffer_ptr, &sequence_length, buffer_length);
-
- /* Check for a valid packet. */
- if (length == 0)
- {
-
- /* Increment the invalid packet error counter. */
- agent_ptr -> nx_snmp_agent_invalid_packets++;
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- /* Return to caller. */
- return;
- }
-
- /* Move the buffer pointer up. */
- buffer_ptr = buffer_ptr + length;
-
- /* The buffer pointer is moved by the length. Update buffer size */
- buffer_length -= (INT)length;
-
- /* Pickup the SNMP VERSION field. */
- length = _nx_snmp_utility_version_get(buffer_ptr, &version, buffer_length);
-
- /* Check for a valid packet. */
- if (length == 0)
- {
-
- /* Increment the invalid packet error counter. */
- agent_ptr -> nx_snmp_agent_invalid_packets++;
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- /* Return to caller. */
- return;
- }
-
- /* Move the buffer pointer up. */
- buffer_ptr = buffer_ptr + length;
-
- /* The buffer pointer is moved by the length. Update buffer size */
- buffer_length -= (INT)length;
-
- /* Pickup the SNMP Community String field. */
- length = _nx_snmp_utility_community_get(buffer_ptr,
- agent_ptr -> nx_snmp_agent_current_community_string,
- buffer_length);
-
- /* Check for a valid packet. */
- if (length == 0)
- {
-
- /* Increment the invalid packet error counter. */
- agent_ptr -> nx_snmp_agent_invalid_packets++;
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- /* Return to caller. */
- return;
- }
-
- /* Move the buffer pointer up. */
- buffer_ptr = buffer_ptr + length;
-
- /* The buffer pointer is moved by the length. Update buffer size */
- buffer_length -= (INT)length;
-
- /* Save the request type pointer. */
- request_type_ptr = buffer_ptr;
-
- /* Pick up the SNMP Request type. */
- length = _nx_snmp_utility_request_type_get(buffer_ptr, &request_type, &request_length, buffer_length);
-
- /* Check for a valid packet. */
- if (length == 0)
- {
-
- /* Increment the invalid packet error counter. */
- agent_ptr -> nx_snmp_agent_invalid_packets++;
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- /* Return to caller. */
- return;
- }
-
- /* Move the buffer pointer up. */
- buffer_ptr = buffer_ptr + length;
-
- /* The buffer pointer is moved by the length. Update buffer size */
- buffer_length -= (INT)length;
-
- agent_ptr -> nx_snmp_agent_request_get_type = NX_FALSE;
- if ((request_type == NX_SNMP_GET_REQUEST) ||
- (request_type == NX_SNMP_GET_NEXT_REQUEST) ||
- (request_type == NX_SNMP_GET_BULK_REQUEST))
- {
- agent_ptr -> nx_snmp_agent_request_get_type = NX_TRUE;
- }
-
- /* Pickup the SNMP Request ID. */
- length = _nx_snmp_utility_request_id_get(buffer_ptr, &request_id, buffer_length);
-
- /* Check for a valid packet. */
- if (length == 0)
- {
-
- /* Increment the invalid packet error counter. */
- agent_ptr -> nx_snmp_agent_invalid_packets++;
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- /* Return to caller. */
- return;
- }
-
- /* Move the buffer pointer up. */
- buffer_ptr = buffer_ptr + length;
-
- /* The buffer pointer is moved by the length. Update buffer size */
- buffer_length -= (INT)length;
-
- /* Save a pointer to the error string. */
- error_ptr = buffer_ptr;
-
- /* Pickup the SNMP Error information. This is actually used to derive the GETBULK
- information in SNMP V2 and above. */
- length = _nx_snmp_utility_error_info_get(buffer_ptr, &non_repeaters, &max_repetitions, buffer_length);
-
- /* Check for a valid packet. */
- if (length == 0)
- {
-
- /* Increment the invalid packet error counter. */
- agent_ptr -> nx_snmp_agent_invalid_packets++;
-
- /* Increment the internal error counter. */
- agent_ptr -> nx_snmp_agent_internal_errors++;
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
- /* Return to caller. */
- return;
- }
-
-#ifndef NX_DISABLE_PACKET_CHAIN
-
- /* Determine if the received packet size is too big. */
- if (packet_ptr -> nx_packet_next)
- {
-
- /* Call the error handling response routine. */
- _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_TOOBIG, 0);
-
- /* Done, return to caller. */
- return;
- }
-#endif /* NX_DISABLE_PACKET_CHAIN */
-
-
-
- /* Check to see if there is a username processing routine. */
- if (agent_ptr -> nx_snmp_agent_username_process)
- {
-
- /* Yes, there is a callback routine to process the community/username. */
- status = (agent_ptr -> nx_snmp_agent_username_process)(agent_ptr, agent_ptr -> nx_snmp_agent_current_community_string);
-
- /* Determine if the callback routine generated an error. */
- if (status != NX_SUCCESS)
- {
-
- /* Increment the number of community/username errors. */
- agent_ptr -> nx_snmp_agent_username_errors++;
-
- /* Call the error handling response routine. */
- _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_AUTHORIZATION, 0);
-
- /* Done, return to caller. */
- return;
- }
}
/* Move the buffer pointer up. */
@@ -18530,7 +17517,6 @@ INT buffer_length;
#else
packet_type = NX_IPv6_UDP_PACKET;
#endif /* FEATURE_NX_IPV6 */
-
}
else
{
@@ -18773,9 +17759,11 @@ INT buffer_length;
SNMP Manager's input buffer is - right before the first variable. We can
now walk through the variable list to process each request and place the
result in the response buffer. */
- objects = 0;
- next_object = NX_TRUE;
+ objects = 0;
+ next_object = NX_TRUE;
+#ifndef NX_SNMP_DISABLE_V2
current_repetitions = max_repetitions;
+#endif /* NX_SNMP_DISABLE_V2 */
do
{
@@ -18783,9 +17771,6 @@ INT buffer_length;
if (next_object)
{
- /* Remember the start of the variable. */
- variable_start_ptr = buffer_ptr;
-
/* Pickup the first SNMP Variable length. */
length = _nx_snmp_utility_sequence_get(buffer_ptr, &variable_length, buffer_length);
@@ -18805,7 +17790,7 @@ INT buffer_length;
nx_packet_release(response_packet_ptr);
/* Call the error handling response routine. This will release the packet */
- _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_SUCCESS, objects+1);
+ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_SUCCESS, objects + 1);
/* Return to caller. */
return;
@@ -18814,13 +17799,11 @@ INT buffer_length;
/* Move the buffer pointer up. */
buffer_ptr = buffer_ptr + length;
- /* The buffer pointer is moved by the length. Update buffer size */
+ /* Update the size of the remaining buffer. */
buffer_length -= (INT)length;
/* Now pickup the object ID. */
- length = _nx_snmp_utility_object_id_get(buffer_ptr,
- agent_ptr -> nx_snmp_agent_current_octet_string,
- buffer_length);
+ length = _nx_snmp_utility_object_id_get(buffer_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, buffer_length);
/* Determine if the object retrieval was successful. */
if (length == 0)
@@ -18845,7 +17828,7 @@ INT buffer_length;
/* Move the buffer pointer up. */
buffer_ptr = buffer_ptr + length;
- /* The buffer pointer is moved by the length. Update buffer size */
+ /* Update the size of the remaining buffer. */
buffer_length -= (INT)length;
/* Default the value to NULL. */
@@ -18868,11 +17851,8 @@ INT buffer_length;
/* Increment the internal error counter. */
agent_ptr -> nx_snmp_agent_internal_errors++;
- /* Send an SNMP version error response. */
- _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_BADVALUE, objects+1);
-
- /* Release the packet. */
- nx_packet_release(packet_ptr);
+ /* Send an SNMP version error response. The packet will be released in the function. */
+ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_BADVALUE, objects + 1);
/* Release the response packet. */
nx_packet_release(response_packet_ptr);
@@ -18880,6 +17860,15 @@ INT buffer_length;
/* Return to caller. */
return;
}
+ else
+ {
+
+ /* Move the buffer pointer up. */
+ buffer_ptr = buffer_ptr + length;
+
+ /* Update the size of the remaining buffer. */
+ buffer_length -= (INT)length;
+ }
}
}
@@ -18892,7 +17881,8 @@ INT buffer_length;
agent_ptr -> nx_snmp_agent_total_get_variables++;
/* Call the application's GET routine. */
- status = (agent_ptr -> nx_snmp_agent_get_process)(agent_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, &(agent_ptr -> nx_snmp_agent_current_object_data));
+ status = (agent_ptr -> nx_snmp_agent_get_process)(agent_ptr, agent_ptr -> nx_snmp_agent_current_octet_string,
+ &(agent_ptr -> nx_snmp_agent_current_object_data));
}
else if (request_type == NX_SNMP_ANS1_GET_NEXT_REQUEST)
{
@@ -18901,9 +17891,22 @@ INT buffer_length;
agent_ptr -> nx_snmp_agent_total_get_variables++;
/* Call the application's GETNEXT routine. */
- status = (agent_ptr -> nx_snmp_agent_getnext_process)(agent_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, &(agent_ptr -> nx_snmp_agent_current_object_data));
+ status = (agent_ptr -> nx_snmp_agent_getnext_process)(agent_ptr, agent_ptr -> nx_snmp_agent_current_octet_string,
+ &(agent_ptr -> nx_snmp_agent_current_object_data));
}
- else if (request_type == NX_SNMP_ANS1_GET_BULK_REQUEST)
+ else if (request_type == NX_SNMP_ANS1_SET_REQUEST)
+ {
+
+ /* Increment the total number of set variables. */
+ agent_ptr -> nx_snmp_agent_total_set_variables++;
+
+ /* Call the application's SET routine. */
+ status = (agent_ptr -> nx_snmp_agent_set_process)(agent_ptr, agent_ptr -> nx_snmp_agent_current_octet_string,
+ &(agent_ptr -> nx_snmp_agent_current_object_data));
+ }
+
+#ifndef NX_SNMP_DISABLE_V2
+ else if ((request_type == NX_SNMP_ANS1_GET_BULK_REQUEST) && (version != NX_SNMP_VERSION_1))
{
/* Increment the total number of get variables. */
@@ -18944,22 +17947,14 @@ INT buffer_length;
}
}
}
- else if (request_type == NX_SNMP_ANS1_SET_REQUEST)
- {
-
- /* Increment the total number of set variables. */
- agent_ptr -> nx_snmp_agent_total_set_variables++;
-
- /* Call the application's SET routine. */
- status = (agent_ptr -> nx_snmp_agent_set_process)(agent_ptr, agent_ptr -> nx_snmp_agent_current_octet_string, &(agent_ptr -> nx_snmp_agent_current_object_data));
- }
+#endif /* NX_SNMP_DISABLE_V2 */
else
{
/* Release the response packet. */
nx_packet_release(response_packet_ptr);
- /* Release the packet. */
+ /* Release the packet. */
nx_packet_release(packet_ptr);
/* Increment the internal error counter. */
@@ -18976,8 +17971,56 @@ INT buffer_length;
/* Release the response packet. */
nx_packet_release(response_packet_ptr);
- /* Call the error handling response routine. This will release the packet */
- _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, status, objects);
+#ifndef NX_SNMP_DISABLE_V1
+ /* Check the version. */
+ if (version == NX_SNMP_VERSION_1)
+ {
+
+ /* Per RFC2576 4.3 */
+ switch(status)
+ {
+ case NX_SNMP_SUCCESS:
+ case NX_SNMP_ERROR_TOOBIG:
+ /* Call the error handling response routine. */
+ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, status, objects + 1);
+ break;
+ case NX_SNMP_ERROR_BADVALUE:
+ case NX_SNMP_ERROR_WRONGVALUE:
+ case NX_SNMP_ERROR_WRONGENCODING:
+ case NX_SNMP_ERROR_WRONGTYPE:
+ case NX_SNMP_ERROR_WRONGLENGTH:
+ case NX_SNMP_ERROR_INCONSISTENTVALUE:
+ /* Call the error handling response routine. */
+ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_BADVALUE, objects + 1);
+ break;
+ case NX_SNMP_ERROR_NOSUCHNAME:
+ case NX_SNMP_ERROR_NOACCESS:
+ case NX_SNMP_ERROR_NOTWRITABLE:
+ case NX_SNMP_ERROR_NOCREATION:
+ case NX_SNMP_ERROR_INCONSISTENTNAME:
+ case NX_SNMP_ERROR_AUTHORIZATION:
+ /* Call the error handling response routine. */
+ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_NOSUCHNAME, objects + 1);
+ break;
+ case NX_SNMP_ERROR_GENERAL:
+ case NX_SNMP_ERROR_RESOURCEUNAVAILABLE:
+ case NX_SNMP_ERROR_COMMITFAILED:
+ case NX_SNMP_ERROR_UNDOFAILED:
+ /* Call the error handling response routine. */
+ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_GENERAL, objects + 1);
+ break;
+ default:
+ /* Release the packet. */
+ nx_packet_release(packet_ptr);
+ }
+ }
+ else
+#endif /* NX_SNMP_DISABLE_V1 */
+ {
+
+ /* Call the error handling response routine. This will release the packet */
+ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, status, objects + 1);
+ }
/* Done, return to caller. */
return;
@@ -19013,10 +18056,14 @@ INT buffer_length;
(agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_IPV6_ADDRESS) &&
#endif
(agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_NSAP_ADDRESS) &&
- (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_OBJECT_ID) &&
+ (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_OBJECT_ID)
+#ifndef NX_SNMP_DISABLE_V2
+ &&
(agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_NO_SUCH_OBJECT) &&
(agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_NO_SUCH_INSTANCE) &&
- (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_END_OF_MIB_VIEW))
+ (agent_ptr -> nx_snmp_agent_current_object_data.nx_snmp_object_data_type != NX_SNMP_ANS1_END_OF_MIB_VIEW)
+#endif /* NX_SNMP_DISABLE_V2 */
+ )
{
/* Release the response packet. */
@@ -19047,8 +18094,8 @@ INT buffer_length;
/* Release the response packet. */
nx_packet_release(response_packet_ptr);
- /* Call the error handling response routine. This will release the packet */
- _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_TOOBIG, objects);
+ /* Call the error handling response routine. This will release the packet. */
+ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_TOOBIG, objects + 1);
/* Done, return to caller. */
return;
@@ -19097,8 +18144,8 @@ INT buffer_length;
/* Release the response packet. */
nx_packet_release(response_packet_ptr);
- /* Call the error handling response routine. This will release the packet */
- _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_TOOBIG, objects);
+ /* Call the error handling response routine. This will release the packet. */
+ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_TOOBIG, objects + 1);
/* Done, return to caller. */
return;
@@ -19129,8 +18176,8 @@ INT buffer_length;
/* Release the response packet. */
nx_packet_release(response_packet_ptr);
- /* Call the error handling response routine. This will release the packet */
- _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_TOOBIG, objects);
+ /* Call the error handling response routine. This will release the packet. */
+ _nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_TOOBIG, objects + 1);
/* Done, return to caller. */
return;
@@ -19158,16 +18205,12 @@ INT buffer_length;
if (next_object)
{
- /* Adjust the pointer to the next variable. */
- buffer_ptr = variable_start_ptr + total_variable_length;
-
/* Decrement the size of the variable list. */
variable_list_length = variable_list_length - total_variable_length;
/* Increment the object counter. */
objects++;
}
-
} while ((variable_list_length) || (next_object == NX_FALSE));
/* At this point, several response fields need to be updated with actual lengths. */
@@ -19213,7 +18256,7 @@ INT buffer_length;
nx_packet_release(response_packet_ptr);
}
}
-#endif
+#endif /* !NX_SNMP_DISABLE_V1 && !NX_SNMP_DISABLE_V2 */
#ifndef NX_SNMP_DISABLE_V3
@@ -19222,7 +18265,7 @@ INT buffer_length;
/* FUNCTION RELEASE */
/* */
/* _nx_snmp_version_3_process PORTABLE C */
-/* 6.1.6 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -19291,6 +18334,10 @@ INT buffer_length;
/* improved boundary check, */
/* checked NULL pointer, */
/* resulting in version 6.1.6 */
+/* 10-31-2023 Bo Chen Modified comment(s), improved */
+/* buffer length verification, */
+/* fixed packet double release,*/
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
VOID _nx_snmp_version_3_process(NX_SNMP_AGENT *agent_ptr, NX_PACKET *packet_ptr)
@@ -19303,7 +18350,6 @@ UINT variable_list_length, variable_length;
ULONG request_id;
UINT status, length, objects;
UCHAR *buffer_ptr;
-UCHAR *variable_start_ptr = NX_NULL;
UCHAR *error_ptr, *request_type_ptr, *temp_ptr;
UINT response_length;
UINT total_variable_length = 0;
@@ -19549,6 +18595,9 @@ INT buffer_length;
/* Position the buffer pointer past the octet string. */
buffer_ptr = buffer_ptr + 2;
+ /* The buffer pointer is moved. Update buffer size */
+ buffer_length -= 2;
+
/* Pickup the sequence for the security data. */
length = _nx_snmp_utility_sequence_get(buffer_ptr, &security_sequence_length, buffer_length);
@@ -20823,7 +19872,7 @@ INT buffer_length;
/* Save the location if we need to return an error message. */
pdu_buffer_ptr = buffer_ptr;
- status = _nx_snmp_agent_decrypt_pdu(agent_ptr, &buffer_ptr, response_buffer_ptr, &response_encryption_size_ptr, &response_length, buffer_length);
+ status = _nx_snmp_agent_decrypt_pdu(agent_ptr, &buffer_ptr, response_buffer_ptr, &response_encryption_size_ptr, &response_length, &buffer_length);
if (status != NX_SUCCESS)
{
@@ -20840,39 +19889,92 @@ INT buffer_length;
return;
}
+ /* Check the packet length. */
+ if (buffer_length < 4)
+ {
+
+ /* Increment the invalid packet error counter. */
+ agent_ptr -> nx_snmp_agent_invalid_packets++;
+
+ /* Increment the internal error counter. */
+ agent_ptr -> nx_snmp_agent_internal_errors++;
+
+ /* Release the packet. */
+ nx_packet_release(packet_ptr);
+
+ /* Release the response packet too. */
+ nx_packet_release(response_packet_ptr);
+
+ return;
+ }
+
+ UINT temp = 0;
+
/* This is typically coded as 0x30 0x29 [or whatever length] 0x04 0x82 or [length] without
the multi byte coding. This will also handle 0x81 "multi byte" coding. */
if (buffer_ptr[3] & NX_SNMP_ANS1_MULTI_BYTES)
{
/* Get the type of length of the string */
- UINT temp = (UINT)(buffer_ptr[3] & 0x7F);
-
- if (temp == 2)
+ temp = (UINT)(buffer_ptr[3] & 0x7F);
+
+ /* Check the packet length. */
+ if (((temp != 1) && (temp !=2)) || ((UINT)buffer_length < (4 + temp)))
{
- pdu_length = (UINT) (*(buffer_ptr+ 4) << 8) | ((UINT) *(buffer_ptr+5));
- pdu_buffer_ptr = buffer_ptr;
+ /* Increment the invalid packet error counter. */
+ agent_ptr -> nx_snmp_agent_invalid_packets++;
+
+ /* Increment the internal error counter. */
+ agent_ptr -> nx_snmp_agent_internal_errors++;
+
+ /* Release the packet. */
+ nx_packet_release(packet_ptr);
+
+ /* Release the response packet too. */
+ nx_packet_release(response_packet_ptr);
+
+ return;
}
-
- else if (temp == 1)
+
+ if (temp == 2)
{
- pdu_length = *(buffer_ptr + 4);
- pdu_buffer_ptr = buffer_ptr;
+ pdu_length = (UINT) (*(buffer_ptr+ 4) << 8) | ((UINT) *(buffer_ptr+5));
}
else
{
-
- /* String is either null or too big, return a zero length to indicate an error. */
- return;
+ /* temp == 1. */
+ pdu_length = *(buffer_ptr + 4);
}
+
}
else /* Assume one byte */
{
pdu_length = *(buffer_ptr + 3);
- pdu_buffer_ptr = buffer_ptr;
}
+ /* Check the pdu length. */
+ if (pdu_length > (UINT)(buffer_length - 4 - (INT)temp))
+ {
+
+ /* Increment the invalid packet error counter. */
+ agent_ptr -> nx_snmp_agent_invalid_packets++;
+
+ /* Increment the internal error counter. */
+ agent_ptr -> nx_snmp_agent_internal_errors++;
+
+ /* Release the packet. */
+ nx_packet_release(packet_ptr);
+
+ /* Release the response packet too. */
+ nx_packet_release(response_packet_ptr);
+
+ return;
+ }
+
+ /* Set pdu_buffer_ptr. */
+ pdu_buffer_ptr = buffer_ptr;
+
response_length = 4;
}
@@ -21460,9 +20562,6 @@ INT buffer_length;
if (next_object)
{
- /* Remember the start of the variable. */
- variable_start_ptr = buffer_ptr;
-
/* Pickup the first SNMP Variable length. */
length = _nx_snmp_utility_sequence_get(buffer_ptr, &variable_length, buffer_length);
@@ -21541,18 +20640,24 @@ INT buffer_length;
/* Increment the internal error counter. */
agent_ptr -> nx_snmp_agent_internal_errors++;
- /* Send an SNMP version error response. */
+ /* Send an SNMP version error response. The packet will be released in the function. */
_nx_snmp_version_error_response(agent_ptr, packet_ptr, request_type_ptr, error_ptr, NX_SNMP_ERROR_BADVALUE, objects+1);
- /* Release the packet. */
- nx_packet_release(packet_ptr);
-
/* Release the response packet. */
nx_packet_release(response_packet_ptr);
/* Return to caller. */
return;
}
+ else
+ {
+
+ /* Move the buffer pointer up. */
+ buffer_ptr = buffer_ptr + length;
+
+ /* Update the size of the remaining buffer. */
+ buffer_length -= (INT)length;
+ }
}
}
@@ -21856,9 +20961,6 @@ INT buffer_length;
if (next_object)
{
- /* Adjust the pointer to the next variable. */
- buffer_ptr = variable_start_ptr + total_variable_length;
-
/* Decrement the size of the variable list. */
variable_list_length = variable_list_length - total_variable_length;
@@ -21982,7 +21084,7 @@ INT buffer_length;
/* FUNCTION RELEASE */
/* */
/* _nx_snmp_version_3_report_send PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -22030,6 +21132,9 @@ INT buffer_length;
/* 09-30-2020 Yuxin Zhou Modified comment(s), and */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
+/* 10-31-2023 Bo Chen Modified comment(s), improved */
+/* buffer length verification, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
VOID _nx_snmp_version_3_report_send(NX_SNMP_AGENT *agent_ptr, UCHAR *buffer_ptr, UINT report_respond, INT buffer_length)
@@ -22139,7 +21244,7 @@ UCHAR report_security_level;
{
/* We do. Decrypt the data. We need to get the PDU data, request id and other data. */
- status = _nx_snmp_agent_decrypt_pdu(agent_ptr, &buffer_ptr, NX_NULL, &report_encryption_size_ptr, &report_length, buffer_length);
+ status = _nx_snmp_agent_decrypt_pdu(agent_ptr, &buffer_ptr, NX_NULL, &report_encryption_size_ptr, &report_length, &buffer_length);
if (status != NX_SUCCESS)
{
@@ -23451,7 +22556,7 @@ UCHAR key2[NX_SNMP_DIGEST_WORKING_SIZE];
/* FUNCTION RELEASE */
/* */
/* _nx_snmp_agent_encrypt_pdu PORTABLE C */
-/* 6.1.6 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -23498,6 +22603,9 @@ UCHAR key2[NX_SNMP_DIGEST_WORKING_SIZE];
/* 04-02-2021 Yuxin Zhou Modified comment(s), improved */
/* verification of encryption, */
/* resulting in version 6.1.6 */
+/* 10-31-2023 Bo Chen Modified comment(s), improved */
+/* buffer length verification, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
@@ -23524,9 +22632,15 @@ UINT adjusted_pdu_length;
*response_pdu_length = *response_pdu_length + padding;
*response_sequence_length = *response_sequence_length + padding;
+ /* Check the buffer. */
+ if ((UINT)(response_sequence_buffer_end - (*response_buffer_ptr)) < padding)
+ {
+ return(NX_SNMP_INVALID_PDU_ENCRYPTION);
+ }
+
/* Use a work pointer to initialize the padding buffer. */
temp_ptr = *response_buffer_ptr;
-
+
/* Clear the end of the response message... just to be nice! */
for (i = 0; i < padding; i++)
{
@@ -23670,7 +22784,7 @@ UINT adjusted_pdu_length;
/* FUNCTION RELEASE */
/* */
/* _nx_snmp_agent_decrypt_pdu PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -23715,24 +22829,31 @@ UINT adjusted_pdu_length;
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 10-31-2023 Bo Chen Modified comment(s), improved */
+/* buffer length verification, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_snmp_agent_decrypt_pdu(NX_SNMP_AGENT *agent_ptr, UCHAR **buffer_ptr, UCHAR *response_buffer_ptr,
- UCHAR **response_encryption_size_ptr, UINT *response_length, INT buffer_length)
+ UCHAR **response_encryption_size_ptr, UINT *response_length, INT *buffer_length)
{
UINT i, j, encrypted_size;
UCHAR key1[NX_SNMP_DIGEST_WORKING_SIZE];
UCHAR key2[NX_SNMP_DIGEST_WORKING_SIZE];
-UCHAR *temp_ptr;
*response_length = 0;
- temp_ptr = *buffer_ptr;
+
+ /* Check the buffer length for tag and length. */
+ if (*buffer_length < 2)
+ {
+ return(NX_SNMP_INVALID_PDU_ENCRYPTION);
+ }
/* Decrypt the source PDU and setup the response to have an encryption header. */
- if (temp_ptr[0] != NX_SNMP_ANS1_OCTET_STRING)
+ if ((*buffer_ptr)[0] != NX_SNMP_ANS1_OCTET_STRING)
{
#ifdef NX_SNMPV3_PRINT_DEBUG_MESSAGE
@@ -23743,27 +22864,41 @@ UCHAR *temp_ptr;
}
/* Pickup the encrypted PDU size. */
- if (temp_ptr[1] & NX_SNMP_ANS1_MULTI_BYTES)
+ if ((*buffer_ptr)[1] & NX_SNMP_ANS1_MULTI_BYTES)
{
- UINT temp = temp_ptr[1] & 0x7F;
+ UINT temp = (*buffer_ptr)[1] & 0x7F;
if (temp == 2)
{
-
+
+ /* Check the buffer length. */
+ if (*buffer_length < 4)
+ {
+ return(NX_SNMP_INVALID_PDU_ENCRYPTION);
+ }
+
/* Two byte octet string. */
- encrypted_size = (((UINT) temp_ptr[2]) << 8) | ((UINT) temp_ptr[3]);
+ encrypted_size = (((UINT) (*buffer_ptr)[2]) << 8) | ((UINT) (*buffer_ptr)[3]);
/* Move the buffer pointer up to the actual encrypted PDU contents. */
- temp_ptr = temp_ptr + 4;
+ (*buffer_ptr) += 4;
+ *buffer_length -= 4;
}
else if (temp == 1)
{
+ /* Check the buffer length. */
+ if (*buffer_length < 3)
+ {
+ return(NX_SNMP_INVALID_PDU_ENCRYPTION);
+ }
+
/* One byte octet string e.g. 0x04 0x81 0xXY */
- encrypted_size = (UINT) temp_ptr[2];
+ encrypted_size = (UINT) (*buffer_ptr)[2];
/* Move the buffer pointer up to the actual encrypted PDU contents. */
- temp_ptr = temp_ptr + 3;
+ (*buffer_ptr) += 3;
+ (*buffer_length) -= 3;
}
else
@@ -23776,15 +22911,15 @@ UCHAR *temp_ptr;
{
/* One byte octet string. */
- encrypted_size = (UINT) temp_ptr[1];
+ encrypted_size = (UINT) (*buffer_ptr)[1];
/* Move the buffer pointer up to the actual encrypted PDU contents. */
- temp_ptr = temp_ptr + 2;
-
+ (*buffer_ptr) += 2;
+ (*buffer_length) -= 2;
}
/* Check for invalid buffer size. */
- if ((INT)encrypted_size > buffer_length)
+ if ((INT)encrypted_size > *buffer_length)
{
/* Invalid buffer size. */
@@ -23813,7 +22948,7 @@ UCHAR *temp_ptr;
_nx_des_key_set(&(agent_ptr -> nx_snmp_agent_v3_des_data), (agent_ptr -> nx_snmp_agent_v3_privacy_key) -> nx_snmp_security_key);
/* Decrypt the first 8 bytes. */
- _nx_des_decrypt(&(agent_ptr -> nx_snmp_agent_v3_des_data), temp_ptr, key1);
+ _nx_des_decrypt(&(agent_ptr -> nx_snmp_agent_v3_des_data), (*buffer_ptr), key1);
/* XOR with the IV. */
for (i = 0; i < 8; i++)
@@ -23829,17 +22964,17 @@ UCHAR *temp_ptr;
{
/* Decrypt the next 8-byte block. */
- _nx_des_decrypt(&(agent_ptr -> nx_snmp_agent_v3_des_data), &temp_ptr[j], key2);
+ _nx_des_decrypt(&(agent_ptr -> nx_snmp_agent_v3_des_data), &(*buffer_ptr)[j], key2);
/* XOR with the previous encrypted 8-byte block. */
for (i = 0; i < 8; i++)
{
/* XOR result with previous block. */
- key2[i] = key2[i] ^ temp_ptr[(j-8)+i];
+ key2[i] = key2[i] ^ (*buffer_ptr)[(j-8)+i];
/* Copy a byte of the decrypted block over the source. */
- temp_ptr[(j-8)+i] = key1[i];
+ (*buffer_ptr)[(j-8)+i] = key1[i];
/* Save this byte of the new decrypted block. */
key1[i] = key2[i];
@@ -23854,11 +22989,9 @@ UCHAR *temp_ptr;
{
/* Copy a byte of the decrypted block over the source. */
- temp_ptr[(j-8)+i] = key1[i];
+ (*buffer_ptr)[(j-8)+i] = key1[i];
}
- *buffer_ptr = temp_ptr;
-
/* If the caller is going to encrypt its response it will send a non null response buffer pointer. */
if (response_buffer_ptr != NX_NULL)
{
diff --git a/addons/snmp/nxd_snmp.h b/addons/snmp/nxd_snmp.h
index 5777da0e..3b30be22 100644
--- a/addons/snmp/nxd_snmp.h
+++ b/addons/snmp/nxd_snmp.h
@@ -26,7 +26,7 @@
/* APPLICATION INTERFACE DEFINITION RELEASE */
/* */
/* nxd_snmp.h PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* 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 */
+/* 10-31-2023 Bo Chen Modified comment(s), and */
+/* combined the functions of */
+/* processing snmp v1 and v2, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
@@ -867,14 +871,13 @@ UINT _nx_snmp_utility_version_get(UCHAR *buffer_ptr, UINT *snmp_version, INT
UINT _nx_snmp_utility_version_set(UCHAR *buffer_ptr, UINT snmp_version, UCHAR *buffer_end);
UINT _nx_snmp_utility_tlv_block_parse(UCHAR *buffer, INT buffer_length, USHORT *tlv_type, USHORT *tlv_tag_class, ULONG *tlv_length, UCHAR **tlv_data, ULONG *header_length);
VOID _nx_snmp_version_error_response(NX_SNMP_AGENT *agent_ptr, NX_PACKET *packet_ptr, UCHAR *request_type_ptr, UCHAR *error_string_ptr, UINT status, UINT objects);
-VOID _nx_snmp_version_1_process(NX_SNMP_AGENT *agent_ptr, NX_PACKET *packet_ptr);
-VOID _nx_snmp_version_2_process(NX_SNMP_AGENT *agent_ptr, NX_PACKET *packet_ptr);
+VOID _nx_snmp_version_1_and_2_process(NX_SNMP_AGENT *agent_ptr, NX_PACKET *packet_ptr);
VOID _nx_snmp_version_3_report_send(NX_SNMP_AGENT *agent_ptr, UCHAR *buffer_ptr, UINT discovery_response, INT buffer_length);
VOID _nx_snmp_version_3_process(NX_SNMP_AGENT *agent_ptr, NX_PACKET *packet_ptr);
UINT _nx_snmp_agent_encrypt_pdu(NX_SNMP_AGENT *agent_ptr, UINT *response_pdu_length, UINT *response_sequence_length, UCHAR *response_encryption_size_ptr,
UCHAR **response_sequence_ptr, UCHAR *response_sequence_buffer_end, UCHAR **response_buffer_ptr,UCHAR *response_privacy_ptr);
UINT _nx_snmp_agent_add_auth_parameter(NX_SNMP_AGENT *agent_ptr, NX_PACKET *response_packet_ptr, UCHAR *response_authentication_ptr);
-UINT _nx_snmp_agent_decrypt_pdu(NX_SNMP_AGENT *agent_ptr, UCHAR **buffer_ptr, UCHAR *response_buffer_ptr, UCHAR **response_encryption_size_ptr, UINT *response_length, INT buffer_length);
+UINT _nx_snmp_agent_decrypt_pdu(NX_SNMP_AGENT *agent_ptr, UCHAR **buffer_ptr, UCHAR *response_buffer_ptr, UCHAR **response_encryption_size_ptr, UINT *response_length, INT *buffer_length);
VOID _nx_snmp_agent_security_response_status(NX_SNMP_AGENT *agent_ptr, UINT *authenticate, UINT *encryption, UINT *send_reply);
diff --git a/addons/sntp/nxd_sntp_client.c b/addons/sntp/nxd_sntp_client.c
index 0563e2ce..01af4e2e 100644
--- a/addons/sntp/nxd_sntp_client.c
+++ b/addons/sntp/nxd_sntp_client.c
@@ -2449,7 +2449,7 @@ NX_SNTP_TIME local_time;
/* FUNCTION RELEASE */
/* */
/* _nx_sntp_client_receive_time_update PORTABLE C */
-/* 6.1.12 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -2500,6 +2500,9 @@ NX_SNTP_TIME local_time;
/* 07-29-2022 Yuxin Zhou Modified comment(s), and */
/* corrected the port check, */
/* resulting in version 6.1.12 */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), and */
+/* fixed packet chain issue, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_sntp_client_receive_time_update(NX_SNTP_CLIENT *client_ptr, ULONG timeout)
@@ -2728,6 +2731,18 @@ NXD_ADDRESS source_ip_address, destination_ip_address;
continue;
}
+#ifndef NX_DISABLE_PACKET_CHAIN
+ /* Ignore packet chain. */
+ if (receive_packet -> nx_packet_next)
+ {
+
+ /* No further need for the receive packet. Release back to the client pool. */
+ nx_packet_release(receive_packet);
+
+ continue;
+ }
+#endif /* NX_DISABLE_PACKET_CHAIN */
+
memset(&(client_ptr -> nx_sntp_current_server_time_message), 0, sizeof(NX_SNTP_TIME_MESSAGE));
/* Extract time message data from packet data into time message. */
diff --git a/common/inc/nx_api.h b/common/inc/nx_api.h
index dba70712..12d88a57 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.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -100,9 +100,9 @@
/* 03-08-2023 Tiejun Zhou Modified comment(s), and */
/* updated product constants, */
/* resulting in version 6.2.1 */
-/* xx-xx-xxxx Tiejun Zhou Modified comment(s), */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), */
/* supported random IP id, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
@@ -518,8 +518,8 @@ VOID _nx_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, ULONG
/* Define basic constants for the NetX TCP/IP Stack. */
#define AZURE_RTOS_NETXDUO
#define NETXDUO_MAJOR_VERSION 6
-#define NETXDUO_MINOR_VERSION 2
-#define NETXDUO_PATCH_VERSION 1
+#define NETXDUO_MINOR_VERSION 3
+#define NETXDUO_PATCH_VERSION 0
/* Define the following symbols for backward compatibility */
#define EL_PRODUCT_NETXDUO
diff --git a/common/inc/nx_icmpv6.h b/common/inc/nx_icmpv6.h
index 15b2e196..0e517d7e 100644
--- a/common/inc/nx_icmpv6.h
+++ b/common/inc/nx_icmpv6.h
@@ -26,7 +26,7 @@
/* COMPONENT DEFINITION RELEASE */
/* */
/* nx_icmpv6.h PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* 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 */
+/* 10-31-2023 Bo Chen Modified comment(s), improved */
+/* packet length verification, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
@@ -255,24 +258,13 @@ typedef struct NX_ICMPV6_OPTION_PREFIX_STRUCT
typedef struct NX_ICMPV6_OPTION_MTU_STRUCT
{
- /* prefix type. */
- /*lint -esym(768,NX_ICMPV6_OPTION_MTU_STRUCT::nx_icmpv6_option_mtu_type) suppress member not referenced. It is used before type casting from NX_ICMPV6_OPTION. */
- UCHAR nx_icmpv6_option_mtu_type;
-
- /* option length. */
- /*lint -esym(768,NX_ICMPV6_OPTION_MTU_STRUCT::nx_icmpv6_option_mtu_length) suppress member not referenced. It is used before type casting from NX_ICMPV6_OPTION. */
- UCHAR nx_icmpv6_option_mtu_length;
-
- /* Unused */
- /*lint -esym(768,NX_ICMPV6_OPTION_MTU_STRUCT::nx_icmpv6_option_mtu_reserved) suppress member not referenced. It is reserved for future use. */
- USHORT nx_icmpv6_option_mtu_reserved;
+ /* General ICMPv6 header. */
+ /*lint -esym(768,NX_ICMPV6_OPTION_MTU_STRUCT::nx_icmpv6_option_mtu_icmpv6_header) suppress member not referenced. It is used before type casting from NX_ICMPV6_HEADER. */
+ NX_ICMPV6_HEADER nx_icmpv6_option_mtu_icmpv6_header;
/* MTU length. */
ULONG nx_icmpv6_option_mtu_path_mtu;
- /* Pointer to the probe message (not the ICMPv6 header)
- which for path MTU discovery. */
- UCHAR *nx_icmpv6_option_mtu_message;
} NX_ICMPV6_OPTION_MTU;
/* Define the Router solicitation message type. */
diff --git a/common/inc/nx_user_sample.h b/common/inc/nx_user_sample.h
index 2bc43017..7593d9fa 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.x */
+/* 6.3.0 */
/* */
/* AUTHOR */
/* */
@@ -52,9 +52,9 @@
/* resulting in version 6.1.8 */
/* 04-25-2022 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1.11 */
-/* xx-xx-xxxx Tiejun Zhou Modified comment(s), */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), */
/* supported random IP id, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
diff --git a/common/src/nx_icmpv6_packet_process.c b/common/src/nx_icmpv6_packet_process.c
index 9d5c3f04..a55d84d0 100644
--- a/common/src/nx_icmpv6_packet_process.c
+++ b/common/src/nx_icmpv6_packet_process.c
@@ -46,7 +46,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_icmpv6_packet_process PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -96,6 +96,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 10-31-2023 Bo Chen Modified comment(s), improved */
+/* packet length verification, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
VOID _nx_icmpv6_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
@@ -112,6 +115,19 @@ NX_IPV6_HEADER *ipv6_header;
/* Add debug information. */
NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
+ /* Check packet length is at least sizeof(NX_ICMPV6_HEADER). */
+ if ((UINT)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) < sizeof(NX_ICMPV6_HEADER))
+ {
+#ifndef NX_DISABLE_ICMP_INFO
+
+ /* Increment the ICMP invalid packet error. */
+ ip_ptr -> nx_ip_icmp_invalid_packets++;
+#endif
+
+ _nx_packet_release(packet_ptr);
+ return;
+ }
+
/* Points to the ICMP message header. */
/*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
header_ptr = (NX_ICMPV6_HEADER *)packet_ptr -> nx_packet_prepend_ptr;
diff --git a/common/src/nx_icmpv6_process_na.c b/common/src/nx_icmpv6_process_na.c
index acfd9452..f8e4f26a 100644
--- a/common/src/nx_icmpv6_process_na.c
+++ b/common/src/nx_icmpv6_process_na.c
@@ -43,7 +43,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_icmpv6_process_na PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -88,15 +88,16 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 10-31-2023 Bo Chen Modified comment(s), improved */
+/* packet length verification, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
VOID _nx_icmpv6_process_na(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
{
ND_CACHE_ENTRY *nd_entry = NX_NULL;
-
-/*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
-NX_ICMPV6_ND *nd_ptr = (NX_ICMPV6_ND *)(packet_ptr -> nx_packet_prepend_ptr);
+NX_ICMPV6_ND *nd_ptr;
NX_ICMPV6_OPTION *option_ptr = NX_NULL;
INT error = 0;
INT lla_same = 0;
@@ -109,6 +110,29 @@ UINT i;
/* Add debug information. */
NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
+#ifndef NX_DISABLE_RX_SIZE_CHECKING
+ /* Check packet length is at least sizeof(NX_ICMPV6_ND). */
+ if ((packet_ptr -> nx_packet_length < sizeof(NX_ICMPV6_ND))
+#ifndef NX_DISABLE_PACKET_CHAIN
+ || (packet_ptr -> nx_packet_next) /* Ignore chained packet. */
+#endif /* NX_DISABLE_PACKET_CHAIN */
+ )
+ {
+#ifndef NX_DISABLE_ICMP_INFO
+
+ /* Increment the ICMP invalid packet error. */
+ ip_ptr -> nx_ip_icmp_invalid_packets++;
+#endif /* NX_DISABLE_ICMP_INFO */
+
+ /* Release the packet and we are done. */
+ _nx_packet_release(packet_ptr);
+ return;
+ }
+#endif /* NX_DISABLE_RX_SIZE_CHECKING */
+
+ /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
+ nd_ptr = (NX_ICMPV6_ND *)(packet_ptr -> nx_packet_prepend_ptr);
+
/* Take care of endian-ness. */
NX_IPV6_ADDRESS_CHANGE_ENDIAN(nd_ptr -> nx_icmpv6_nd_targetAddress);
NX_CHANGE_ULONG_ENDIAN(nd_ptr -> nx_icmpv6_nd_flag);
diff --git a/common/src/nx_icmpv6_process_ns.c b/common/src/nx_icmpv6_process_ns.c
index 9cdc06f1..ca023b4e 100644
--- a/common/src/nx_icmpv6_process_ns.c
+++ b/common/src/nx_icmpv6_process_ns.c
@@ -44,7 +44,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_icmpv6_process_ns PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -89,6 +89,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 10-31-2023 Bo Chen Modified comment(s), improved */
+/* packet length verification, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
VOID _nx_icmpv6_process_ns(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
@@ -125,6 +128,26 @@ ULONG dest_address[4];
/*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
ipv6_header = (NX_IPV6_HEADER *)packet_ptr -> nx_packet_ip_header;
+#ifndef NX_DISABLE_RX_SIZE_CHECKING
+ /* Check packet length is at least sizeof(NX_ICMPV6_ND). */
+ if ((packet_ptr -> nx_packet_length < sizeof(NX_ICMPV6_ND))
+#ifndef NX_DISABLE_PACKET_CHAIN
+ || (packet_ptr -> nx_packet_next) /* Ignore chained packet. */
+#endif /* NX_DISABLE_PACKET_CHAIN */
+ )
+ {
+#ifndef NX_DISABLE_ICMP_INFO
+
+ /* Increment the ICMP invalid packet error. */
+ ip_ptr -> nx_ip_icmp_invalid_packets++;
+#endif /* NX_DISABLE_ICMP_INFO */
+
+ /* Release the packet and we are done. */
+ _nx_packet_release(packet_ptr);
+ return;
+ }
+#endif /* NX_DISABLE_RX_SIZE_CHECKING */
+
/* Get a pointer to the Neighbor Discovery message. */
/*lint -e{929} suppress cast of pointer to pointer, since it is necessary */
nd_ptr = (NX_ICMPV6_ND *)header_ptr;
diff --git a/common/src/nx_icmpv6_process_packet_too_big.c b/common/src/nx_icmpv6_process_packet_too_big.c
index 54e62c3a..fb30b859 100644
--- a/common/src/nx_icmpv6_process_packet_too_big.c
+++ b/common/src/nx_icmpv6_process_packet_too_big.c
@@ -45,7 +45,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_icmpv6_process_packet_too_big PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -87,6 +87,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 10-31-2023 Bo Chen Modified comment(s), improved */
+/* packet length verification, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_icmpv6_process_packet_too_big(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
@@ -105,7 +108,11 @@ NX_INTERFACE *if_ptr;
NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
#ifndef NX_DISABLE_RX_SIZE_CHECKING
- if (packet_ptr -> nx_packet_length < sizeof(NX_ICMPV6_OPTION_MTU))
+ if ((packet_ptr -> nx_packet_length < (sizeof(NX_ICMPV6_OPTION_MTU) + sizeof(NX_IPV6_HEADER)))
+#ifndef NX_DISABLE_PACKET_CHAIN
+ || (packet_ptr -> nx_packet_next) /* Ignore chained packet. */
+#endif /* NX_DISABLE_PACKET_CHAIN */
+ )
{
#ifndef NX_DISABLE_ICMP_INFO
@@ -129,7 +136,7 @@ NX_INTERFACE *if_ptr;
/* Parse the original sender data. */
/*lint -e{929} -e{826} -e{740} suppress cast of pointer to pointer, since it is necessary */
- original_ip_header_ptr = (NX_IPV6_HEADER *)(&(icmpv6_mtu_option_ptr -> nx_icmpv6_option_mtu_message));
+ original_ip_header_ptr = (NX_IPV6_HEADER *)(packet_ptr -> nx_packet_prepend_ptr + sizeof(NX_ICMPV6_OPTION_MTU));
/* Extract the original sender from the IP header. */
packet_ptr -> nx_packet_prepend_ptr -= sizeof(NX_IPV6_HEADER);
diff --git a/common/src/nx_icmpv6_process_ra.c b/common/src/nx_icmpv6_process_ra.c
index 423576a1..6ae4de9b 100644
--- a/common/src/nx_icmpv6_process_ra.c
+++ b/common/src/nx_icmpv6_process_ra.c
@@ -37,7 +37,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_icmpv6_process_ra PORTABLE C */
-/* 6.1.11 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -83,6 +83,9 @@
/* added internal ip address */
/* change notification, */
/* resulting in version 6.1.11 */
+/* 10-31-2023 Bo Chen Modified comment(s), improved */
+/* packet length verification, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
VOID _nx_icmpv6_process_ra(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
@@ -112,6 +115,26 @@ UINT interface_index;
/* Add debug information. */
NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
+ /* Check packet length is at least sizeof(NX_ICMPV6_RA). */
+#ifndef NX_DISABLE_RX_SIZE_CHECKING
+ if ((packet_ptr -> nx_packet_length < sizeof(NX_ICMPV6_RA))
+#ifndef NX_DISABLE_PACKET_CHAIN
+ || (packet_ptr -> nx_packet_next) /* Ignore chained packet. */
+#endif /* NX_DISABLE_PACKET_CHAIN */
+ )
+ {
+#ifndef NX_DISABLE_ICMP_INFO
+
+ /* Increment the ICMP invalid message count. */
+ ip_ptr -> nx_ip_icmp_invalid_packets++;
+#endif
+
+ /* Invalid ICMP message, just release it. */
+ _nx_packet_release(packet_ptr);
+ return;
+ }
+#endif /* NX_DISABLE_RX_SIZE_CHECKING */
+
/* Initialize the ND cache table entry to NULL */
nd_entry = NX_NULL;
diff --git a/common/src/nx_icmpv6_process_redirect.c b/common/src/nx_icmpv6_process_redirect.c
index 8c42db68..43f50fa8 100644
--- a/common/src/nx_icmpv6_process_redirect.c
+++ b/common/src/nx_icmpv6_process_redirect.c
@@ -38,7 +38,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_icmpv6_process_redirect PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* 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 */
+/* 10-31-2023 Bo Chen Modified comment(s), improved */
+/* packet length verification, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
@@ -115,7 +118,11 @@ NX_IPV6_DESTINATION_ENTRY *dest_entry_ptr;
NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
#ifndef NX_DISABLE_RX_SIZE_CHECKING
- if (packet_ptr -> nx_packet_length < sizeof(NX_ICMPV6_REDIRECT_MESSAGE))
+ if ((packet_ptr -> nx_packet_length < sizeof(NX_ICMPV6_REDIRECT_MESSAGE))
+#ifndef NX_DISABLE_PACKET_CHAIN
+ || (packet_ptr -> nx_packet_next) /* Ignore chained packet. */
+#endif /* NX_DISABLE_PACKET_CHAIN */
+ )
{
#ifndef NX_DISABLE_ICMP_INFO
diff --git a/common/src/nx_igmp_packet_process.c b/common/src/nx_igmp_packet_process.c
index 4c11c0b2..914d5fad 100644
--- a/common/src/nx_igmp_packet_process.c
+++ b/common/src/nx_igmp_packet_process.c
@@ -28,6 +28,7 @@
#include "nx_api.h"
#include "nx_packet.h"
#include "nx_igmp.h"
+#include "nx_ip.h"
#ifndef NX_DISABLE_IPV4
@@ -36,7 +37,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_igmp_packet_process PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -76,6 +77,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), */
+/* unified checksum calculate, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
VOID _nx_igmp_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
@@ -86,11 +90,6 @@ ULONG update_time;
NX_IGMP_HEADER *header_ptr;
USHORT max_update_time;
ULONG checksum;
-ULONG length;
-UCHAR *word_ptr;
-NX_PACKET *current_packet;
-ULONG long_temp;
-USHORT short_temp;
/* Add debug information. */
@@ -107,113 +106,9 @@ USHORT short_temp;
/* First verify the checksum is correct. */
-
- /* Setup the length of the packet checksum. */
- length = packet_ptr -> nx_packet_length;
-
- /* Determine if we need to add a padding byte. */
- if (((length / sizeof(USHORT)) * sizeof(USHORT)) != length)
- {
-
- /* We have single byte alignment and we need two byte alignment. */
- length++;
-
-#ifndef NX_DISABLE_PACKET_CHAIN
- /* Determine if there is a last packet pointer. */
- if (packet_ptr -> nx_packet_last)
- {
-
- /* Multi-packet message, add a zero byte at the end. */
- *((packet_ptr -> nx_packet_last) -> nx_packet_append_ptr) = 0;
- }
- else
- {
-#endif
-
- /* Write a zero byte at the end of the first and only packet. */
- *(packet_ptr -> nx_packet_append_ptr) = 0;
-#ifndef NX_DISABLE_PACKET_CHAIN
- }
-#endif
- }
-
- /* Setup the pointer to the start of the packet. */
- word_ptr = (UCHAR *)packet_ptr -> nx_packet_prepend_ptr;
-
- /* Initialize the current packet to the input packet pointer. */
- current_packet = packet_ptr;
-
- checksum = 0;
-
-
- /* Loop to calculate the checksum over the entire packet. */
- while (length)
- {
- /* Determine if there is at least one ULONG left. */
- if ((UINT)(current_packet -> nx_packet_append_ptr - word_ptr) >= sizeof(ULONG))
- {
-
- /* Pickup a whole ULONG. */
- long_temp = *((ULONG *)word_ptr);
-
- /* Add upper 16-bits into checksum. */
- checksum = checksum + (long_temp >> NX_SHIFT_BY_16);
-
- /* Check for carry bits. */
- if (checksum & NX_CARRY_BIT)
- {
- checksum = (checksum & NX_LOWER_16_MASK) + 1;
- }
-
- /* Add lower 16-bits into checksum. */
- checksum = checksum + (long_temp & NX_LOWER_16_MASK);
-
- /* Check for carry bits. */
-
- if (checksum & NX_CARRY_BIT)
- {
- checksum = (checksum & NX_LOWER_16_MASK) + 1;
- }
-
- /* Move the word pointer and decrease the length. */
- word_ptr = word_ptr + sizeof(ULONG);
- length = length - (ULONG)sizeof(ULONG);
- }
- else
- {
-
- /* Pickup the 16-bit word. */
- short_temp = *((USHORT *)word_ptr);
-
- /* Add next 16-bit word into checksum. */
- checksum = checksum + short_temp;
-
- /* Check for carry bits. */
- if (checksum & NX_CARRY_BIT)
- {
- checksum = (checksum & NX_LOWER_16_MASK) + 1;
- }
-
- /* Move the word pointer and decrease the length. */
- word_ptr = word_ptr + sizeof(USHORT);
- length = length - (ULONG)sizeof(USHORT);
- }
-
-#ifndef NX_DISABLE_PACKET_CHAIN
- /* Determine if we are at the end of the current packet. */
- if ((word_ptr >= (UCHAR *)current_packet -> nx_packet_append_ptr) &&
- (current_packet -> nx_packet_next))
- {
-
- /* We have crossed the packet boundary. Move to the next packet
- structure. */
- current_packet = current_packet -> nx_packet_next;
-
- /* Setup the new word pointer. */
- word_ptr = (UCHAR *)current_packet -> nx_packet_prepend_ptr;
- }
-#endif
- }
+ checksum = _nx_ip_checksum_compute(packet_ptr, NX_IP_IGMP,
+ (UINT)packet_ptr -> nx_packet_length,
+ NX_NULL, NX_NULL);
checksum = ~checksum & NX_LOWER_16_MASK;
diff --git a/common/src/nx_ip_create.c b/common/src/nx_ip_create.c
index e4d82e8d..5f9a43f2 100644
--- a/common/src/nx_ip_create.c
+++ b/common/src/nx_ip_create.c
@@ -35,7 +35,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_ip_create PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -82,9 +82,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Tiejun Zhou Modified comment(s), */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), */
/* supported random IP id, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_ip_create(NX_IP *ip_ptr, CHAR *name, ULONG ip_address, ULONG network_mask,
diff --git a/common/src/nx_ip_header_add.c b/common/src/nx_ip_header_add.c
index 1f401fbc..f0f65002 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.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -83,9 +83,9 @@
/* 08-02-2021 Yuxin Zhou Modified comment(s), and */
/* supported TCP/IP offload, */
/* resulting in version 6.1.8 */
-/* xx-xx-xxxx Tiejun Zhou Modified comment(s), */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), */
/* supported random IP id, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_ip_header_add(NX_IP *ip_ptr, NX_PACKET *packet_ptr, ULONG source_ip, ULONG destination_ip,
diff --git a/common/src/nx_ipv4_packet_receive.c b/common/src/nx_ipv4_packet_receive.c
index f2e996a8..66b5deb6 100644
--- a/common/src/nx_ipv4_packet_receive.c
+++ b/common/src/nx_ipv4_packet_receive.c
@@ -37,7 +37,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_ipv4_packet_receive PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -79,6 +79,10 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), */
+/* validated packet length for */
+/* fragments, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
VOID _nx_ipv4_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
@@ -571,6 +575,21 @@ UINT packet_consumed;
/* Yes, fragmenting is available. Place the packet on the incoming
fragment queue. */
+ /* Check packet length with more fragment bit. If not multiple of 8 bytes... */
+ if ((ip_header_ptr -> nx_ip_header_word_1 & NX_IP_MORE_FRAGMENT) &&
+ (((pkt_length - (ULONG)sizeof(NX_IPV4_HEADER)) & 0x7) != 0))
+ {
+
+ /* Invalid length. Drop the packet. */
+#ifndef NX_DISABLE_IP_INFO
+
+ /* Increment the IP receive packets dropped count. */
+ ip_ptr -> nx_ip_receive_packets_dropped++;
+#endif
+ _nx_packet_release(packet_ptr);
+ return;
+ }
+
/* Disable interrupts. */
TX_DISABLE
diff --git a/common/src/nx_ipv6_fragment_process.c b/common/src/nx_ipv6_fragment_process.c
index 57e6e71e..2114215f 100644
--- a/common/src/nx_ipv6_fragment_process.c
+++ b/common/src/nx_ipv6_fragment_process.c
@@ -39,7 +39,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_ipv6_fragment_process PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -84,9 +84,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Tiejun Zhou Modified comment(s), */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), */
/* supported random IP id, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
VOID _nx_ipv6_fragment_process(struct NX_IP_DRIVER_STRUCT *driver_req_ptr, UINT mtu)
diff --git a/common/src/nx_tcp_free_port_find.c b/common/src/nx_tcp_free_port_find.c
index 5997831a..f194c8ea 100644
--- a/common/src/nx_tcp_free_port_find.c
+++ b/common/src/nx_tcp_free_port_find.c
@@ -34,7 +34,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_tcp_free_port_find PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -71,6 +71,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 10-31-2023 Haiqing Zhao Modified comment(s), improved */
+/* internal logic, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_tcp_free_port_find(NX_IP *ip_ptr, UINT port, UINT *free_port_ptr)
@@ -175,6 +178,12 @@ ULONG trace_timestamp;
if (port > NX_MAX_PORT)
{
+ /* Jump out if the original port is ahead of the defined search start port. */
+ if (starting_port <= NX_SEARCH_PORT_START)
+ {
+ break;
+ }
+
/* Yes, we need to wrap around. */
port = NX_SEARCH_PORT_START;
}
diff --git a/common/src/nx_tcp_packet_process.c b/common/src/nx_tcp_packet_process.c
index 31dbe41e..0d6bd566 100644
--- a/common/src/nx_tcp_packet_process.c
+++ b/common/src/nx_tcp_packet_process.c
@@ -44,7 +44,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_tcp_packet_process PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -92,6 +92,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), */
+/* validated TCP header buffer,*/
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
VOID _nx_tcp_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
@@ -215,6 +218,22 @@ ULONG rwin_scale = 0xFF;
}
}
+#ifndef NX_DISABLE_RX_SIZE_CHECKING
+ /* Make sure the TCP header is in the first packet. */
+ if ((UINT)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) < sizeof(NX_TCP_HEADER))
+ {
+
+#ifndef NX_DISABLE_TCP_INFO
+ /* Increment the TCP invalid packet error. */
+ ip_ptr -> nx_ip_tcp_invalid_packets++;
+#endif
+
+ /* Not supported. */
+ _nx_packet_release(packet_ptr);
+ return;
+ }
+#endif /* NX_DISABLE_RX_SIZE_CHECKING */
+
/* 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 */
tcp_header_ptr = (NX_TCP_HEADER *)packet_ptr -> nx_packet_prepend_ptr;
@@ -232,7 +251,9 @@ ULONG rwin_scale = 0xFF;
#ifndef NX_DISABLE_RX_SIZE_CHECKING
/* Check for valid packet length. */
- if (((INT)option_words < 0) || (packet_ptr -> nx_packet_length < (sizeof(NX_TCP_HEADER) + (option_words << 2))))
+ if (((INT)option_words < 0) ||
+ ((UINT)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) <
+ (sizeof(NX_TCP_HEADER) + (option_words << 2))))
{
#ifndef NX_DISABLE_TCP_INFO
diff --git a/common/src/nx_tcp_socket_state_data_check.c b/common/src/nx_tcp_socket_state_data_check.c
index e23023d0..95b53c47 100644
--- a/common/src/nx_tcp_socket_state_data_check.c
+++ b/common/src/nx_tcp_socket_state_data_check.c
@@ -282,7 +282,7 @@ ULONG work_length;
/* FUNCTION RELEASE */
/* */
/* _nx_tcp_socket_state_data_check PORTABLE C */
-/* 6.2.0 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -333,6 +333,9 @@ ULONG work_length;
/* 10-31-2022 Wenhui Xie Modified comment(s), and */
/* supported HTTP Proxy, */
/* resulting in version 6.2.0 */
+/* 10-31-2023 Bo Chen Modified comment(s), corrected */
+/* the acked packet count, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_tcp_socket_state_data_check(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr)
@@ -925,6 +928,9 @@ NX_IP *ip_ptr;
if ((INT)(expected_sequence - search_begin_sequence) >= 0)
{
+ /* Increment the acked packet count. */
+ acked_packets++;
+
if ((INT)(search_end_sequence - expected_sequence) > 0)
{
/* Sequence number is within this packet. Advance sequence number. */
@@ -932,8 +938,6 @@ NX_IP *ip_ptr;
socket_ptr -> nx_tcp_socket_rx_sequence = expected_sequence;
- acked_packets++;
-
/* Mark this packet as ready for retrieval. */
/*lint -e{923} suppress cast of ULONG to pointer. */
search_ptr -> nx_packet_queue_next = (NX_PACKET *)NX_PACKET_READY;
diff --git a/common/src/nx_udp_free_port_find.c b/common/src/nx_udp_free_port_find.c
index 4acadf0e..6df31e9d 100644
--- a/common/src/nx_udp_free_port_find.c
+++ b/common/src/nx_udp_free_port_find.c
@@ -34,7 +34,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_udp_free_port_find PORTABLE C */
-/* 6.1 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
@@ -71,6 +71,9 @@
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
+/* 10-31-2023 Haiqing Zhao Modified comment(s), improved */
+/* internal logic, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_udp_free_port_find(NX_IP *ip_ptr, UINT port, UINT *free_port_ptr)
@@ -175,6 +178,12 @@ ULONG trace_timestamp;
if (port > NX_MAX_PORT)
{
+ /* Jump out if the original port is ahead of the defined search start port. */
+ if (starting_port <= NX_SEARCH_PORT_START)
+ {
+ break;
+ }
+
/* Yes, we need to wrap around. */
port = NX_SEARCH_PORT_START;
}
diff --git a/crypto_libraries/src/nx_crypto_3des.c b/crypto_libraries/src/nx_crypto_3des.c
index 111a59f2..802dc025 100644
--- a/crypto_libraries/src/nx_crypto_3des.c
+++ b/crypto_libraries/src/nx_crypto_3des.c
@@ -223,7 +223,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_3des_decrypt(NX_CRYPTO_3DES *context, UCHAR sour
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_3des_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -265,8 +265,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_3des_decrypt(NX_CRYPTO_3DES *context, UCHAR sour
/* warning supression for */
/* obsolete DES/3DES, */
/* resulting in version 6.1.11 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_3des_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -376,7 +376,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_3des_cleanup(VOID *crypto_metadata)
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_3des_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -427,8 +427,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_3des_cleanup(VOID *crypto_metadata)
/* warning supression for */
/* obsolete DES/3DES, */
/* resulting in version 6.1.11 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_3des_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
diff --git a/crypto_libraries/src/nx_crypto_aes.c b/crypto_libraries/src/nx_crypto_aes.c
index bf7d5234..2dc5a06a 100644
--- a/crypto_libraries/src/nx_crypto_aes.c
+++ b/crypto_libraries/src/nx_crypto_aes.c
@@ -1702,7 +1702,7 @@ UINT i;
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_aes_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -1739,8 +1739,8 @@ UINT i;
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_aes_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -1848,7 +1848,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_aes_cleanup(VOID *crypto_metadata)
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_aes_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -1898,8 +1898,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_aes_cleanup(VOID *crypto_metadata)
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_aes_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
@@ -1998,7 +1998,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_aes_cbc_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -2045,8 +2045,8 @@ UINT status;
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_aes_cbc_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
@@ -2173,7 +2173,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_aes_ccm_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -2224,8 +2224,8 @@ UINT status;
/* 03-08-2023 Tiejun Zhou Modified comment(s), and */
/* fixed compiler warnings, */
/* resulting in version 6.2.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_aes_ccm_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
@@ -2475,7 +2475,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_aes_gcm_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -2523,8 +2523,8 @@ UINT status;
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_aes_gcm_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
@@ -2773,7 +2773,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_aes_ctr_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -2820,8 +2820,8 @@ UINT status;
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_aes_ctr_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
@@ -2925,7 +2925,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_aes_xcbc_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -2972,8 +2972,8 @@ UINT status;
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_aes_xcbc_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
diff --git a/crypto_libraries/src/nx_crypto_des.c b/crypto_libraries/src/nx_crypto_des.c
index d6fd84fe..dc469977 100644
--- a/crypto_libraries/src/nx_crypto_des.c
+++ b/crypto_libraries/src/nx_crypto_des.c
@@ -574,7 +574,7 @@ UINT round;
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_des_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -616,8 +616,8 @@ UINT round;
/* warning supression for */
/* obsolete DES/3DES, */
/* resulting in version 6.1.11 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_des_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -719,7 +719,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_des_cleanup(VOID *crypto_metadata)
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_des_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -770,8 +770,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_des_cleanup(VOID *crypto_metadata)
/* warning supression for */
/* obsolete DES/3DES, */
/* resulting in version 6.1.11 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_des_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
diff --git a/crypto_libraries/src/nx_crypto_drbg.c b/crypto_libraries/src/nx_crypto_drbg.c
index 94f24342..fcebf0a5 100644
--- a/crypto_libraries/src/nx_crypto_drbg.c
+++ b/crypto_libraries/src/nx_crypto_drbg.c
@@ -921,7 +921,7 @@ VOID *handler = NX_CRYPTO_NULL;
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_drbg_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -959,8 +959,8 @@ VOID *handler = NX_CRYPTO_NULL;
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_drbg_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -1059,7 +1059,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_drbg_cleanup(VOID *crypto_metadata)
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_drbg_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -1103,8 +1103,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_drbg_cleanup(VOID *crypto_metadata)
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_drbg_operation(UINT op,
diff --git a/crypto_libraries/src/nx_crypto_ecdh.c b/crypto_libraries/src/nx_crypto_ecdh.c
index a9fde0d0..f54d1252 100644
--- a/crypto_libraries/src/nx_crypto_ecdh.c
+++ b/crypto_libraries/src/nx_crypto_ecdh.c
@@ -447,7 +447,7 @@ NX_CRYPTO_EC_POINT public_key, shared_secret;
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_ecdh_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -485,8 +485,8 @@ NX_CRYPTO_EC_POINT public_key, shared_secret;
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_ecdh_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -585,7 +585,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_ecdh_cleanup(VOID *crypto_metadata)
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_ecdh_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -631,8 +631,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_ecdh_cleanup(VOID *crypto_metadata)
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_ecdh_operation(UINT op,
diff --git a/crypto_libraries/src/nx_crypto_ecdsa.c b/crypto_libraries/src/nx_crypto_ecdsa.c
index f1eceb16..291d0111 100644
--- a/crypto_libraries/src/nx_crypto_ecdsa.c
+++ b/crypto_libraries/src/nx_crypto_ecdsa.c
@@ -481,7 +481,7 @@ UINT buffer_size = curve -> nx_crypto_ec_n.nx_crypto_huge_buffe
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_ecdsa_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -519,8 +519,8 @@ UINT buffer_size = curve -> nx_crypto_ec_n.nx_crypto_huge_buffe
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_ecdsa_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -626,7 +626,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_ecdsa_cleanup(VOID *crypto_metadata)
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_ecdsa_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -672,8 +672,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_ecdsa_cleanup(VOID *crypto_metadata)
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_ecdsa_operation(UINT op,
diff --git a/crypto_libraries/src/nx_crypto_ecjpake.c b/crypto_libraries/src/nx_crypto_ecjpake.c
index d1e4754c..fc87bb7f 100644
--- a/crypto_libraries/src/nx_crypto_ecjpake.c
+++ b/crypto_libraries/src/nx_crypto_ecjpake.c
@@ -1594,7 +1594,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_ecjpake_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -1631,8 +1631,8 @@ UINT status;
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_ecjpake_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -1753,7 +1753,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_ecjpake_cleanup(VOID *crypto_metadata)
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_ecjpake_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -1804,8 +1804,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_ecjpake_cleanup(VOID *crypto_metadata)
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_ecjpake_operation(UINT op,
diff --git a/crypto_libraries/src/nx_crypto_hkdf.c b/crypto_libraries/src/nx_crypto_hkdf.c
index 18ed8e7e..1404dddc 100644
--- a/crypto_libraries/src/nx_crypto_hkdf.c
+++ b/crypto_libraries/src/nx_crypto_hkdf.c
@@ -28,7 +28,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_hkdf_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -67,8 +67,8 @@
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_hkdf_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -195,7 +195,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_hkdf_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -244,8 +244,8 @@ UINT status;
/* buffer length verification, */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_hkdf_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
diff --git a/crypto_libraries/src/nx_crypto_hmac.c b/crypto_libraries/src/nx_crypto_hmac.c
index 8b694e6e..c110143e 100644
--- a/crypto_libraries/src/nx_crypto_hmac.c
+++ b/crypto_libraries/src/nx_crypto_hmac.c
@@ -629,7 +629,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_hmac_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -668,8 +668,8 @@ UINT status;
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -778,7 +778,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_cleanup(VOID *crypto_metadata)
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_hmac_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* */
/* AUTHOR */
/* */
@@ -823,8 +823,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_cleanup(VOID *crypto_metadata)
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
diff --git a/crypto_libraries/src/nx_crypto_hmac_md5.c b/crypto_libraries/src/nx_crypto_hmac_md5.c
index fdb4120c..7d2b6565 100644
--- a/crypto_libraries/src/nx_crypto_hmac_md5.c
+++ b/crypto_libraries/src/nx_crypto_hmac_md5.c
@@ -30,7 +30,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_hmac_md5_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -68,8 +68,8 @@
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_md5_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -167,7 +167,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_md5_cleanup(VOID *crypto_metadata)
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_hmac_md5_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -217,8 +217,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_md5_cleanup(VOID *crypto_metadata)
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_md5_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
diff --git a/crypto_libraries/src/nx_crypto_hmac_sha1.c b/crypto_libraries/src/nx_crypto_hmac_sha1.c
index 7d7617b6..364fbe27 100644
--- a/crypto_libraries/src/nx_crypto_hmac_sha1.c
+++ b/crypto_libraries/src/nx_crypto_hmac_sha1.c
@@ -30,7 +30,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_hmac_sha1_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -68,8 +68,8 @@
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_sha1_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -167,7 +167,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_sha1_cleanup(VOID *crypto_metadata)
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_hmac_sha1_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -216,8 +216,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_sha1_cleanup(VOID *crypto_metadata)
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_sha1_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
diff --git a/crypto_libraries/src/nx_crypto_hmac_sha2.c b/crypto_libraries/src/nx_crypto_hmac_sha2.c
index 1310f99d..32f0f55a 100644
--- a/crypto_libraries/src/nx_crypto_hmac_sha2.c
+++ b/crypto_libraries/src/nx_crypto_hmac_sha2.c
@@ -30,7 +30,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_hmac_sha256_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -68,8 +68,8 @@
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_sha256_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -168,7 +168,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_sha256_cleanup(VOID *crypto_metadata
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_hmac_sha256_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -217,8 +217,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_sha256_cleanup(VOID *crypto_metadata
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_sha256_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
diff --git a/crypto_libraries/src/nx_crypto_hmac_sha5.c b/crypto_libraries/src/nx_crypto_hmac_sha5.c
index eafb17fe..bda888c6 100644
--- a/crypto_libraries/src/nx_crypto_hmac_sha5.c
+++ b/crypto_libraries/src/nx_crypto_hmac_sha5.c
@@ -30,7 +30,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_hmac_sha512_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -68,8 +68,8 @@
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_sha512_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -167,7 +167,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_sha512_cleanup(VOID *crypto_metadata
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_hmac_sha512_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -216,8 +216,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_sha512_cleanup(VOID *crypto_metadata
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_hmac_sha512_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
diff --git a/crypto_libraries/src/nx_crypto_md5.c b/crypto_libraries/src/nx_crypto_md5.c
index 131f3abe..1a006560 100644
--- a/crypto_libraries/src/nx_crypto_md5.c
+++ b/crypto_libraries/src/nx_crypto_md5.c
@@ -690,7 +690,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_md5_cleanup(VOID *crypto_metadata)
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_md5_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -740,8 +740,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_md5_cleanup(VOID *crypto_metadata)
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_md5_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
diff --git a/crypto_libraries/src/nx_crypto_pkcs1_v1.5.c b/crypto_libraries/src/nx_crypto_pkcs1_v1.5.c
index 41f01606..75c81264 100644
--- a/crypto_libraries/src/nx_crypto_pkcs1_v1.5.c
+++ b/crypto_libraries/src/nx_crypto_pkcs1_v1.5.c
@@ -458,7 +458,7 @@ UINT status;
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_pkcs1_v1_5_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -496,8 +496,8 @@ UINT status;
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_pkcs1_v1_5_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -595,7 +595,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_pkcs1_v1_5_cleanup(VOID *crypto_metadata)
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_pkcs1_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -641,8 +641,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_pkcs1_v1_5_cleanup(VOID *crypto_metadata)
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_pkcs1_v1_5_operation(UINT op,
diff --git a/crypto_libraries/src/nx_crypto_rsa.c b/crypto_libraries/src/nx_crypto_rsa.c
index 2d6184ed..b843e155 100644
--- a/crypto_libraries/src/nx_crypto_rsa.c
+++ b/crypto_libraries/src/nx_crypto_rsa.c
@@ -165,7 +165,7 @@ NX_CRYPTO_HUGE_NUMBER modulus_hn, exponent_hn, input_hn, output_hn, p_hn, q_hn;
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_rsa_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -202,8 +202,8 @@ NX_CRYPTO_HUGE_NUMBER modulus_hn, exponent_hn, input_hn, output_hn, p_hn, q_hn;
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_rsa_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -313,7 +313,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_rsa_cleanup(VOID *crypto_metadata)
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_rsa_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -359,8 +359,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_rsa_cleanup(VOID *crypto_metadata)
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_rsa_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
diff --git a/crypto_libraries/src/nx_crypto_sha1.c b/crypto_libraries/src/nx_crypto_sha1.c
index aa25f3be..8faa53f0 100644
--- a/crypto_libraries/src/nx_crypto_sha1.c
+++ b/crypto_libraries/src/nx_crypto_sha1.c
@@ -667,7 +667,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_sha1_cleanup(VOID *crypto_metadata)
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_sha1_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -716,8 +716,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_sha1_cleanup(VOID *crypto_metadata)
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_sha1_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
diff --git a/crypto_libraries/src/nx_crypto_sha2.c b/crypto_libraries/src/nx_crypto_sha2.c
index 21ddb622..4f199376 100644
--- a/crypto_libraries/src/nx_crypto_sha2.c
+++ b/crypto_libraries/src/nx_crypto_sha2.c
@@ -588,7 +588,7 @@ ULONG a, b, c, d, e, f, g, h;
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_sha256_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -626,8 +626,8 @@ ULONG a, b, c, d, e, f, g, h;
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_sha256_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -726,7 +726,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_sha256_cleanup(VOID *crypto_metadata)
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_sha256_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -775,8 +775,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_sha256_cleanup(VOID *crypto_metadata)
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_sha256_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
diff --git a/crypto_libraries/src/nx_crypto_sha5.c b/crypto_libraries/src/nx_crypto_sha5.c
index 3bb86a71..51a42e69 100644
--- a/crypto_libraries/src/nx_crypto_sha5.c
+++ b/crypto_libraries/src/nx_crypto_sha5.c
@@ -580,7 +580,7 @@ ULONG64 a, b, c, d, e, f, g, h;
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_sha512_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -618,8 +618,8 @@ ULONG64 a, b, c, d, e, f, g, h;
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_sha512_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -718,7 +718,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_sha512_cleanup(VOID *crypto_metadata)
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_sha512_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -767,8 +767,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_sha512_cleanup(VOID *crypto_metadata)
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_sha512_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
diff --git a/crypto_libraries/src/nx_crypto_tls_prf_1.c b/crypto_libraries/src/nx_crypto_tls_prf_1.c
index d36f629d..0400e218 100644
--- a/crypto_libraries/src/nx_crypto_tls_prf_1.c
+++ b/crypto_libraries/src/nx_crypto_tls_prf_1.c
@@ -28,7 +28,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_prf_1_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -65,8 +65,8 @@
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_prf_1_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -174,7 +174,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_prf_1_cleanup(VOID *crypto_metadata)
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_prf_1_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -223,8 +223,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_prf_1_cleanup(VOID *crypto_metadata)
/* buffer length verification, */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_prf_1_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
diff --git a/crypto_libraries/src/nx_crypto_tls_prf_sha256.c b/crypto_libraries/src/nx_crypto_tls_prf_sha256.c
index 81b308b6..5e461f22 100644
--- a/crypto_libraries/src/nx_crypto_tls_prf_sha256.c
+++ b/crypto_libraries/src/nx_crypto_tls_prf_sha256.c
@@ -28,7 +28,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_prf_sha_256_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -65,8 +65,8 @@
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_prf_sha_256_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -174,7 +174,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_prf_sha_256_cleanup(VOID *crypto_metadata
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_prf_sha_256_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -223,8 +223,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_prf_sha_256_cleanup(VOID *crypto_metadata
/* buffer length verification, */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_prf_sha_256_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
diff --git a/crypto_libraries/src/nx_crypto_tls_prf_sha384.c b/crypto_libraries/src/nx_crypto_tls_prf_sha384.c
index f6654448..78b96d17 100644
--- a/crypto_libraries/src/nx_crypto_tls_prf_sha384.c
+++ b/crypto_libraries/src/nx_crypto_tls_prf_sha384.c
@@ -29,7 +29,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_prf_sha384_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -66,8 +66,8 @@
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_prf_sha384_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -175,7 +175,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_prf_sha384_cleanup(VOID *crypto_metadata)
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_prf_sha384_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -223,8 +223,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_prf_sha384_cleanup(VOID *crypto_metadata)
/* buffer length verification, */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_prf_sha384_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
diff --git a/crypto_libraries/src/nx_crypto_tls_prf_sha512.c b/crypto_libraries/src/nx_crypto_tls_prf_sha512.c
index b47d48f4..d59594ac 100644
--- a/crypto_libraries/src/nx_crypto_tls_prf_sha512.c
+++ b/crypto_libraries/src/nx_crypto_tls_prf_sha512.c
@@ -29,7 +29,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_prf_sha512_init PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -66,8 +66,8 @@
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_prf_sha512_init(struct NX_CRYPTO_METHOD_STRUCT *method,
@@ -175,7 +175,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_prf_sha512_cleanup(VOID *crypto_metadata)
/* FUNCTION RELEASE */
/* */
/* _nx_crypto_method_prf_sha512_operation PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -223,8 +223,8 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_prf_sha512_cleanup(VOID *crypto_metadata)
/* buffer length verification, */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
-/* resulting in version 6.x */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
NX_CRYPTO_KEEP UINT _nx_crypto_method_prf_sha512_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
diff --git a/nx_secure/inc/nx_secure_tls.h b/nx_secure/inc/nx_secure_tls.h
index 419690bd..8ce7e821 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.2.0 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -101,6 +101,9 @@
/* added function to set packet*/
/* pool, */
/* resulting in version 6.2.0 */
+/* 10-31-2022 Bo Chen Modified comment(s), and */
+/* updated product constants, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
@@ -163,7 +166,7 @@ extern "C" {
#define AZURE_RTOS_NETX_SECURE
#define NETX_SECURE_MAJOR_VERSION 6
-#define NETX_SECURE_MINOR_VERSION 2
+#define NETX_SECURE_MINOR_VERSION 3
#define NETX_SECURE_PATCH_VERSION 0
/* The following symbols are defined for backward compatibility reasons. */
diff --git a/nx_secure/ports/nx_secure_port.h b/nx_secure/ports/nx_secure_port.h
index 410eb548..cf367da1 100644
--- a/nx_secure/ports/nx_secure_port.h
+++ b/nx_secure/ports/nx_secure_port.h
@@ -69,7 +69,7 @@
#ifdef NX_SECURE_SYSTEM_INIT
CHAR _nx_secure_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Secure Generic Version G6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Secure Generic Version G6.3.0 *";
#else
extern CHAR _nx_secure_version_id[];
#endif
diff --git a/nx_secure/src/nx_secure_dtls_send_record.c b/nx_secure/src/nx_secure_dtls_send_record.c
index d3cc68b0..7374bcf3 100644
--- a/nx_secure/src/nx_secure_dtls_send_record.c
+++ b/nx_secure/src/nx_secure_dtls_send_record.c
@@ -33,7 +33,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_dtls_send_record PORTABLE C */
-/* 6.1.12 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -89,6 +89,10 @@
/* 07-29-2022 Yuxin Zhou Modified comment(s), and */
/* checked seq number overflow,*/
/* resulting in version 6.1.12 */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), and */
+/* removed packet release on */
+/* send failure, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_secure_dtls_send_record(NX_SECURE_DTLS_SESSION *dtls_session, NX_PACKET *send_packet,
@@ -310,7 +314,6 @@ UCHAR epoch_seq_num[8];
if (status != NX_SUCCESS)
{
- nx_secure_tls_packet_release(send_packet);
return(NX_SECURE_TLS_TCP_SEND_FAILED);
}
diff --git a/nx_secure/src/nx_secure_dtls_server_handshake.c b/nx_secure/src/nx_secure_dtls_server_handshake.c
index b1f2482d..e8808805 100644
--- a/nx_secure/src/nx_secure_dtls_server_handshake.c
+++ b/nx_secure/src/nx_secure_dtls_server_handshake.c
@@ -33,7 +33,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_dtls_server_handshake PORTABLE C */
-/* 6.1.12 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -119,6 +119,9 @@
/* 07-29-2022 Yuxin Zhou Modified comment(s), */
/* removed duplicated alert, */
/* resulting in version 6.1.12 */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), and */
+/* released packet on failure, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_secure_dtls_server_handshake(NX_SECURE_DTLS_SESSION *dtls_session, UCHAR *packet_buffer,
@@ -551,6 +554,9 @@ UCHAR *fragment_buffer;
if (status != NX_SUCCESS)
{
+
+ /* Release packet on send error. */
+ nx_secure_tls_packet_release(send_packet);
break;
}
diff --git a/nx_secure/src/nx_secure_dtls_session_end.c b/nx_secure/src/nx_secure_dtls_session_end.c
index e9c37420..5492fe30 100644
--- a/nx_secure/src/nx_secure_dtls_session_end.c
+++ b/nx_secure/src/nx_secure_dtls_session_end.c
@@ -29,7 +29,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_dtls_session_end PORTABLE C */
-/* 6.1.10 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -75,7 +75,10 @@
/* resulting in version 6.1 */
/* 01-31-2022 Timothy Stapko Modified comment(s), */
/* fixed out-of-order handling,*/
-/* resulting in version 6.1.10 */
+/* resulting in version 6.1.10 */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), */
+/* handled close notify packet,*/
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_secure_dtls_session_end(NX_SECURE_DTLS_SESSION *dtls_session, UINT wait_option)
@@ -152,28 +155,22 @@ NX_SECURE_TLS_SESSION *tls_session;
/* Release the protection. */
tx_mutex_put(&_nx_secure_tls_protection);
- /* See if we recevied the CloseNotify, or if we need to wait. */
- if(tls_session -> nx_secure_tls_received_alert_level != NX_SECURE_TLS_ALERT_LEVEL_WARNING &&
+ /* See if we received the CloseNotify, or if we need to wait. */
+ if(tls_session -> nx_secure_tls_received_alert_level != NX_SECURE_TLS_ALERT_LEVEL_WARNING ||
tls_session -> nx_secure_tls_received_alert_value != NX_SECURE_TLS_ALERT_CLOSE_NOTIFY)
{
- while (status != NX_SECURE_TLS_ALERT_RECEIVED)
+ while (status == NX_SUCCESS)
{
/* Wait for the CloseNotify response. */
- /* Get the protection after nx_packet_allocate. */
- tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
status = _nx_secure_dtls_session_receive(dtls_session, &incoming_packet, wait_option);
- /* Release the protection. */
- tx_mutex_put(&_nx_secure_tls_protection);
-
- if (status == NX_SECURE_TLS_CLOSE_NOTIFY_RECEIVED)
+ if (status == NX_SUCCESS)
{
- status = NX_SUCCESS;
- break;
+
+ /* Release the packet. */
+ nx_secure_tls_packet_release(incoming_packet);
}
- /* Release the alert packet. */
- nx_secure_tls_packet_release(incoming_packet);
}
}
diff --git a/nx_secure/src/nx_secure_dtls_session_receive.c b/nx_secure/src/nx_secure_dtls_session_receive.c
index b3899282..3906f7c4 100644
--- a/nx_secure/src/nx_secure_dtls_session_receive.c
+++ b/nx_secure/src/nx_secure_dtls_session_receive.c
@@ -29,7 +29,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_dtls_session_receive PORTABLE C */
-/* 6.1.12 */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -87,6 +87,9 @@
/* fixed compiler errors when */
/* IPv4 is disabled, */
/* resulting in version 6.1.12 */
+/* 10-31-2023 Tiejun Zhou Modified comment(s), and */
+/* released packet on failure, */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_secure_dtls_session_receive(NX_SECURE_DTLS_SESSION *dtls_session,
@@ -378,7 +381,12 @@ UINT source_port;
tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
_nx_secure_tls_send_alert(tls_session, send_packet, (UCHAR)alert_number, (UCHAR)alert_level);
- _nx_secure_dtls_send_record(dtls_session, send_packet, NX_SECURE_TLS_ALERT, wait_option);
+ if (_nx_secure_dtls_send_record(dtls_session, send_packet, NX_SECURE_TLS_ALERT, wait_option) != NX_SUCCESS)
+ {
+
+ /* Release packet on send error. */
+ nx_secure_tls_packet_release(send_packet);
+ }
/* Release the protection. */
tx_mutex_put(&_nx_secure_tls_protection);
diff --git a/nx_secure/src/nx_secure_tls_send_certificate.c b/nx_secure/src/nx_secure_tls_send_certificate.c
index 2162c5c0..3f794fdc 100644
--- a/nx_secure/src/nx_secure_tls_send_certificate.c
+++ b/nx_secure/src/nx_secure_tls_send_certificate.c
@@ -29,7 +29,7 @@
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_send_certificate PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -83,9 +83,9 @@
/* fixed compiler errors when */
/* x509 is disabled, */
/* resulting in version 6.2.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), */
+/* 10-31-2023 Yanwu Cai Modified comment(s), */
/* fixed packet buffer overrun,*/
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nx_secure_tls_send_certificate(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *send_packet,
diff --git a/nx_secure/src/nxe_secure_tls_session_send.c b/nx_secure/src/nxe_secure_tls_session_send.c
index 7609b5fb..771cc720 100644
--- a/nx_secure/src/nxe_secure_tls_session_send.c
+++ b/nx_secure/src/nxe_secure_tls_session_send.c
@@ -36,7 +36,7 @@ NX_SECURE_CALLER_CHECKING_EXTERNS
/* FUNCTION RELEASE */
/* */
/* _nxe_secure_tls_session_send PORTABLE C */
-/* 6.x */
+/* 6.3.0 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
@@ -71,9 +71,9 @@ NX_SECURE_CALLER_CHECKING_EXTERNS
/* 05-19-2020 Timothy Stapko Initial Version 6.0 */
/* 09-30-2020 Timothy Stapko Modified comment(s), */
/* resulting in version 6.1 */
-/* xx-xx-xxxx Yanwu Cai Modified comment(s), added */
+/* 10-31-2023 Yanwu Cai Modified comment(s), added */
/* record length checking, */
-/* resulting in version 6.x */
+/* resulting in version 6.3.0 */
/* */
/**************************************************************************/
UINT _nxe_secure_tls_session_send(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *packet_ptr,
diff --git a/ports/arc_em/metaware/inc/nx_port.h b/ports/arc_em/metaware/inc/nx_port.h
index 064e026e..91504eba 100644
--- a/ports/arc_em/metaware/inc/nx_port.h
+++ b/ports/arc_em/metaware/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo ARCv2_EM/MetaWare Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo ARCv2_EM/MetaWare Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/arc_hs/metaware/inc/nx_port.h b/ports/arc_hs/metaware/inc/nx_port.h
index 857342ea..36f4862c 100644
--- a/ports/arc_hs/metaware/inc/nx_port.h
+++ b/ports/arc_hs/metaware/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo ARC_HS/MetaWare Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo ARC_HS/MetaWare Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_a15/gnu/inc/nx_port.h b/ports/cortex_a15/gnu/inc/nx_port.h
index d8e5e90a..bbf89b97 100644
--- a/ports/cortex_a15/gnu/inc/nx_port.h
+++ b/ports/cortex_a15/gnu/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A15/GNU Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A15/GNU Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_a5/ac5/inc/nx_port.h b/ports/cortex_a5/ac5/inc/nx_port.h
index 2a11de16..a1ff318c 100644
--- a/ports/cortex_a5/ac5/inc/nx_port.h
+++ b/ports/cortex_a5/ac5/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A5/AC5 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A5/AC5 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_a5/gnu/inc/nx_port.h b/ports/cortex_a5/gnu/inc/nx_port.h
index 7e1eb656..fbb28523 100644
--- a/ports/cortex_a5/gnu/inc/nx_port.h
+++ b/ports/cortex_a5/gnu/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A7/GNU Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A7/GNU Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_a5/iar/inc/nx_port.h b/ports/cortex_a5/iar/inc/nx_port.h
index 9a18c11e..64c7ad5b 100644
--- a/ports/cortex_a5/iar/inc/nx_port.h
+++ b/ports/cortex_a5/iar/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A5/IAR Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A5/IAR Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_a5x/ac6/inc/nx_port.h b/ports/cortex_a5x/ac6/inc/nx_port.h
index 61b1a3d1..09162b5a 100644
--- a/ports/cortex_a5x/ac6/inc/nx_port.h
+++ b/ports/cortex_a5x/ac6/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A5x/AC6 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A5x/AC6 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_a7/ac5/inc/nx_port.h b/ports/cortex_a7/ac5/inc/nx_port.h
index b77072d8..e27925f7 100644
--- a/ports/cortex_a7/ac5/inc/nx_port.h
+++ b/ports/cortex_a7/ac5/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A7/AC5 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A7/AC5 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_a7/gnu/inc/nx_port.h b/ports/cortex_a7/gnu/inc/nx_port.h
index d7f04b90..7e11c1a0 100644
--- a/ports/cortex_a7/gnu/inc/nx_port.h
+++ b/ports/cortex_a7/gnu/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A7/GNU Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A7/GNU Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_a7/iar/inc/nx_port.h b/ports/cortex_a7/iar/inc/nx_port.h
index da354258..1593b72d 100644
--- a/ports/cortex_a7/iar/inc/nx_port.h
+++ b/ports/cortex_a7/iar/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A7/IAR Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A7/IAR Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_a8/ac5/inc/nx_port.h b/ports/cortex_a8/ac5/inc/nx_port.h
index 8652fb4c..1d017dd3 100644
--- a/ports/cortex_a8/ac5/inc/nx_port.h
+++ b/ports/cortex_a8/ac5/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A8/AC5 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A8/AC5 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_a8/gnu/inc/nx_port.h b/ports/cortex_a8/gnu/inc/nx_port.h
index 382f197a..9ea25b9a 100644
--- a/ports/cortex_a8/gnu/inc/nx_port.h
+++ b/ports/cortex_a8/gnu/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A8/GNU Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A8/GNU Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_a8/iar/inc/nx_port.h b/ports/cortex_a8/iar/inc/nx_port.h
index 159cf9af..47abb472 100644
--- a/ports/cortex_a8/iar/inc/nx_port.h
+++ b/ports/cortex_a8/iar/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A8/IAR Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A8/IAR Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_a9/ac5/inc/nx_port.h b/ports/cortex_a9/ac5/inc/nx_port.h
index ab59a16d..72df6ab6 100644
--- a/ports/cortex_a9/ac5/inc/nx_port.h
+++ b/ports/cortex_a9/ac5/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A9/AC5 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A9/AC5 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_a9/gnu/inc/nx_port.h b/ports/cortex_a9/gnu/inc/nx_port.h
index e835ae3e..a3805b1e 100644
--- a/ports/cortex_a9/gnu/inc/nx_port.h
+++ b/ports/cortex_a9/gnu/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A9/GNU Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A9/GNU Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_a9/iar/inc/nx_port.h b/ports/cortex_a9/iar/inc/nx_port.h
index b39c38b7..04e765a0 100644
--- a/ports/cortex_a9/iar/inc/nx_port.h
+++ b/ports/cortex_a9/iar/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A9/IAR Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A9/IAR Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_a9/rvds/inc/nx_port.h b/ports/cortex_a9/rvds/inc/nx_port.h
index ab59a16d..72df6ab6 100644
--- a/ports/cortex_a9/rvds/inc/nx_port.h
+++ b/ports/cortex_a9/rvds/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A9/AC5 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A9/AC5 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m0/ac5/inc/nx_port.h b/ports/cortex_m0/ac5/inc/nx_port.h
index bfc15676..d0c776d0 100644
--- a/ports/cortex_m0/ac5/inc/nx_port.h
+++ b/ports/cortex_m0/ac5/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M0/AC5 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M0/AC5 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m0/gnu/inc/nx_port.h b/ports/cortex_m0/gnu/inc/nx_port.h
index d031f9bd..e6a4843d 100644
--- a/ports/cortex_m0/gnu/inc/nx_port.h
+++ b/ports/cortex_m0/gnu/inc/nx_port.h
@@ -187,7 +187,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M0/GNU Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M0/GNU Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m0/iar/inc/nx_port.h b/ports/cortex_m0/iar/inc/nx_port.h
index e7183f51..4cb6c6e9 100644
--- a/ports/cortex_m0/iar/inc/nx_port.h
+++ b/ports/cortex_m0/iar/inc/nx_port.h
@@ -181,7 +181,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M0/IAR Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M0/IAR Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m23/ac5/inc/nx_port.h b/ports/cortex_m23/ac5/inc/nx_port.h
index 8d4ebe45..1e5ad5e2 100644
--- a/ports/cortex_m23/ac5/inc/nx_port.h
+++ b/ports/cortex_m23/ac5/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M23/AC5 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M23/AC5 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m23/gnu/inc/nx_port.h b/ports/cortex_m23/gnu/inc/nx_port.h
index 13a57c14..b38d3e0e 100644
--- a/ports/cortex_m23/gnu/inc/nx_port.h
+++ b/ports/cortex_m23/gnu/inc/nx_port.h
@@ -183,7 +183,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M23/GNU Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M23/GNU Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m23/iar/inc/nx_port.h b/ports/cortex_m23/iar/inc/nx_port.h
index 323f794f..08f2c649 100644
--- a/ports/cortex_m23/iar/inc/nx_port.h
+++ b/ports/cortex_m23/iar/inc/nx_port.h
@@ -181,7 +181,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M23/IAR Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M23/IAR Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m3/ac5/inc/nx_port.h b/ports/cortex_m3/ac5/inc/nx_port.h
index 937da0d0..5d7ae134 100644
--- a/ports/cortex_m3/ac5/inc/nx_port.h
+++ b/ports/cortex_m3/ac5/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M3/AC5 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M3/AC5 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m3/gnu/inc/nx_port.h b/ports/cortex_m3/gnu/inc/nx_port.h
index 8fbfbe9a..479756bb 100644
--- a/ports/cortex_m3/gnu/inc/nx_port.h
+++ b/ports/cortex_m3/gnu/inc/nx_port.h
@@ -187,7 +187,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M3/GNU Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M3/GNU Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m3/iar/inc/nx_port.h b/ports/cortex_m3/iar/inc/nx_port.h
index f6320461..cd388a46 100644
--- a/ports/cortex_m3/iar/inc/nx_port.h
+++ b/ports/cortex_m3/iar/inc/nx_port.h
@@ -181,7 +181,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M3/IAR Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M3/IAR Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m3/keil/inc/nx_port.h b/ports/cortex_m3/keil/inc/nx_port.h
index ec97688e..78635716 100644
--- a/ports/cortex_m3/keil/inc/nx_port.h
+++ b/ports/cortex_m3/keil/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M3/Keil Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M3/Keil Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m33/ac5/inc/nx_port.h b/ports/cortex_m33/ac5/inc/nx_port.h
index b7c5a59d..6132c435 100644
--- a/ports/cortex_m33/ac5/inc/nx_port.h
+++ b/ports/cortex_m33/ac5/inc/nx_port.h
@@ -207,7 +207,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M33/AC5 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M33/AC5 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m33/ac6/inc/nx_port.h b/ports/cortex_m33/ac6/inc/nx_port.h
index c46b306e..13fbddce 100644
--- a/ports/cortex_m33/ac6/inc/nx_port.h
+++ b/ports/cortex_m33/ac6/inc/nx_port.h
@@ -180,7 +180,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M33/AC6 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M33/AC6 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m33/gnu/inc/nx_port.h b/ports/cortex_m33/gnu/inc/nx_port.h
index 3001a10a..e1a47e10 100644
--- a/ports/cortex_m33/gnu/inc/nx_port.h
+++ b/ports/cortex_m33/gnu/inc/nx_port.h
@@ -184,7 +184,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M33/GNU Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M33/GNU Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m33/iar/inc/nx_port.h b/ports/cortex_m33/iar/inc/nx_port.h
index ea4fac76..4e9bd925 100644
--- a/ports/cortex_m33/iar/inc/nx_port.h
+++ b/ports/cortex_m33/iar/inc/nx_port.h
@@ -184,7 +184,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M33/IAR Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M33/IAR Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m4/ac5/inc/nx_port.h b/ports/cortex_m4/ac5/inc/nx_port.h
index 2a835156..fbdf1c79 100644
--- a/ports/cortex_m4/ac5/inc/nx_port.h
+++ b/ports/cortex_m4/ac5/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M4/AC5 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M4/AC5 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m4/gnu/inc/nx_port.h b/ports/cortex_m4/gnu/inc/nx_port.h
index da312994..2239df01 100644
--- a/ports/cortex_m4/gnu/inc/nx_port.h
+++ b/ports/cortex_m4/gnu/inc/nx_port.h
@@ -187,7 +187,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M4/GNU Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M4/GNU Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m4/iar/inc/nx_port.h b/ports/cortex_m4/iar/inc/nx_port.h
index a416b756..b9395266 100644
--- a/ports/cortex_m4/iar/inc/nx_port.h
+++ b/ports/cortex_m4/iar/inc/nx_port.h
@@ -181,7 +181,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M4/IAR Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M4/IAR Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m4/keil/inc/nx_port.h b/ports/cortex_m4/keil/inc/nx_port.h
index ce141fcf..37344253 100644
--- a/ports/cortex_m4/keil/inc/nx_port.h
+++ b/ports/cortex_m4/keil/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M4/Keil Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M4/Keil Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m55/ac5/inc/nx_port.h b/ports/cortex_m55/ac5/inc/nx_port.h
index 986ee078..8baef642 100644
--- a/ports/cortex_m55/ac5/inc/nx_port.h
+++ b/ports/cortex_m55/ac5/inc/nx_port.h
@@ -201,7 +201,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M55/AC5 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M55/AC5 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m55/ac6/inc/nx_port.h b/ports/cortex_m55/ac6/inc/nx_port.h
index fb23876f..12ae2c3b 100644
--- a/ports/cortex_m55/ac6/inc/nx_port.h
+++ b/ports/cortex_m55/ac6/inc/nx_port.h
@@ -180,7 +180,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M55/AC6 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M55/AC6 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m55/gnu/inc/nx_port.h b/ports/cortex_m55/gnu/inc/nx_port.h
index 2a0d7994..3ed734a7 100644
--- a/ports/cortex_m55/gnu/inc/nx_port.h
+++ b/ports/cortex_m55/gnu/inc/nx_port.h
@@ -180,7 +180,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M55/GNU Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M55/GNU Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m55/iar/inc/nx_port.h b/ports/cortex_m55/iar/inc/nx_port.h
index 9c59526b..4f31d14f 100644
--- a/ports/cortex_m55/iar/inc/nx_port.h
+++ b/ports/cortex_m55/iar/inc/nx_port.h
@@ -180,7 +180,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M55/IAR Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M55/IAR Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m7/ac5/inc/nx_port.h b/ports/cortex_m7/ac5/inc/nx_port.h
index fafe7a76..e51807b0 100644
--- a/ports/cortex_m7/ac5/inc/nx_port.h
+++ b/ports/cortex_m7/ac5/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M7/AC5 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M7/AC5 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m7/ac6/inc/nx_port.h b/ports/cortex_m7/ac6/inc/nx_port.h
index ff16dc15..3a0b4b76 100644
--- a/ports/cortex_m7/ac6/inc/nx_port.h
+++ b/ports/cortex_m7/ac6/inc/nx_port.h
@@ -180,7 +180,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M7/AC6 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M7/AC6 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m7/gnu/inc/nx_port.h b/ports/cortex_m7/gnu/inc/nx_port.h
index edf04bfa..74d062b8 100644
--- a/ports/cortex_m7/gnu/inc/nx_port.h
+++ b/ports/cortex_m7/gnu/inc/nx_port.h
@@ -187,7 +187,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M7/GNU Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M7/GNU Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m7/iar/inc/nx_port.h b/ports/cortex_m7/iar/inc/nx_port.h
index 5ffdc4a3..a49c1466 100644
--- a/ports/cortex_m7/iar/inc/nx_port.h
+++ b/ports/cortex_m7/iar/inc/nx_port.h
@@ -181,7 +181,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M7/IAR Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M7/IAR Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m85/ac5/inc/nx_port.h b/ports/cortex_m85/ac5/inc/nx_port.h
index 61895e71..d627d6fa 100644
--- a/ports/cortex_m85/ac5/inc/nx_port.h
+++ b/ports/cortex_m85/ac5/inc/nx_port.h
@@ -201,7 +201,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M85/AC5 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M85/AC5 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m85/ac6/inc/nx_port.h b/ports/cortex_m85/ac6/inc/nx_port.h
index 1196170b..2241280d 100644
--- a/ports/cortex_m85/ac6/inc/nx_port.h
+++ b/ports/cortex_m85/ac6/inc/nx_port.h
@@ -180,7 +180,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M85/AC6 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M85/AC6 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m85/gnu/inc/nx_port.h b/ports/cortex_m85/gnu/inc/nx_port.h
index cc5f1830..03066afd 100644
--- a/ports/cortex_m85/gnu/inc/nx_port.h
+++ b/ports/cortex_m85/gnu/inc/nx_port.h
@@ -180,7 +180,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M85/GNU Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M85/GNU Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_m85/iar/inc/nx_port.h b/ports/cortex_m85/iar/inc/nx_port.h
index 470a3ff5..53ae959b 100644
--- a/ports/cortex_m85/iar/inc/nx_port.h
+++ b/ports/cortex_m85/iar/inc/nx_port.h
@@ -180,7 +180,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M85/IAR Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M85/IAR Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_r4/ac5/inc/nx_port.h b/ports/cortex_r4/ac5/inc/nx_port.h
index e68e40f5..14895766 100644
--- a/ports/cortex_r4/ac5/inc/nx_port.h
+++ b/ports/cortex_r4/ac5/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R4/AC5 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R4/AC5 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_r4/ac6/inc/nx_port.h b/ports/cortex_r4/ac6/inc/nx_port.h
index 7483608e..b40e3738 100644
--- a/ports/cortex_r4/ac6/inc/nx_port.h
+++ b/ports/cortex_r4/ac6/inc/nx_port.h
@@ -183,7 +183,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R4/AC6 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R4/AC6 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_r4/gnu/inc/nx_port.h b/ports/cortex_r4/gnu/inc/nx_port.h
index 896ebe21..38d5fbee 100644
--- a/ports/cortex_r4/gnu/inc/nx_port.h
+++ b/ports/cortex_r4/gnu/inc/nx_port.h
@@ -183,7 +183,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R4/GNU Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R4/GNU Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_r4/iar/inc/nx_port.h b/ports/cortex_r4/iar/inc/nx_port.h
index 2f8be98d..64703ff3 100644
--- a/ports/cortex_r4/iar/inc/nx_port.h
+++ b/ports/cortex_r4/iar/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R4/IAR Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R4/IAR Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_r5/ac5/inc/nx_port.h b/ports/cortex_r5/ac5/inc/nx_port.h
index 9747d469..675fdbdd 100644
--- a/ports/cortex_r5/ac5/inc/nx_port.h
+++ b/ports/cortex_r5/ac5/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R5/AC5 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R5/AC5 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_r5/gnu/inc/nx_port.h b/ports/cortex_r5/gnu/inc/nx_port.h
index a9ad5718..4cc4327b 100644
--- a/ports/cortex_r5/gnu/inc/nx_port.h
+++ b/ports/cortex_r5/gnu/inc/nx_port.h
@@ -183,7 +183,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Cortex-R5/GNU Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Cortex-R5/GNU Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/cortex_r5/iar/inc/nx_port.h b/ports/cortex_r5/iar/inc/nx_port.h
index b6d77cfe..ab3c6b0d 100644
--- a/ports/cortex_r5/iar/inc/nx_port.h
+++ b/ports/cortex_r5/iar/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R5/IAR Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R5/IAR Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/linux/gnu/inc/nx_port.h b/ports/linux/gnu/inc/nx_port.h
index 512222a7..fd27bbed 100644
--- a/ports/linux/gnu/inc/nx_port.h
+++ b/ports/linux/gnu/inc/nx_port.h
@@ -200,7 +200,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Linux/GNU Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Linux/GNU Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/mips/gnu/inc/nx_port.h b/ports/mips/gnu/inc/nx_port.h
index cb176751..6364af2b 100644
--- a/ports/mips/gnu/inc/nx_port.h
+++ b/ports/mips/gnu/inc/nx_port.h
@@ -192,7 +192,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo PIC32x/MPLAB Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo PIC32x/MPLAB Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/rxv2/ccrx/inc/nx_port.h b/ports/rxv2/ccrx/inc/nx_port.h
index 815219c5..a4aed240 100644
--- a/ports/rxv2/ccrx/inc/nx_port.h
+++ b/ports/rxv2/ccrx/inc/nx_port.h
@@ -208,7 +208,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo RXv2/CCRX Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo RXv2/CCRX Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/rxv2/gnu/inc/nx_port.h b/ports/rxv2/gnu/inc/nx_port.h
index 0a82febb..1ff377b5 100644
--- a/ports/rxv2/gnu/inc/nx_port.h
+++ b/ports/rxv2/gnu/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo RXv2/GNU Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo RXv2/GNU Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/rxv2/iar/inc/nx_port.h b/ports/rxv2/iar/inc/nx_port.h
index c75aac9a..8921fda3 100644
--- a/ports/rxv2/iar/inc/nx_port.h
+++ b/ports/rxv2/iar/inc/nx_port.h
@@ -204,7 +204,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo RXv2/IAR Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo RXv2/IAR Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/ports/win32/vs_2019/inc/nx_port.h b/ports/win32/vs_2019/inc/nx_port.h
index 66f7ec10..7220256e 100644
--- a/ports/win32/vs_2019/inc/nx_port.h
+++ b/ports/win32/vs_2019/inc/nx_port.h
@@ -201,7 +201,7 @@
#ifdef NX_SYSTEM_INIT
CHAR _nx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Win32/VS2019 Version 6.2.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Win32/VS2019 Version 6.3.0 *";
#else
extern CHAR _nx_version_id[];
#endif
diff --git a/samples/demo_rtsp_over_rtp.c b/samples/demo_rtsp_over_rtp.c
new file mode 100644
index 00000000..696bc523
--- /dev/null
+++ b/samples/demo_rtsp_over_rtp.c
@@ -0,0 +1,956 @@
+/* This is the test control routine the NetX RTSP module. All tests are dispatched from this routine. */
+
+#include "tx_api.h"
+#include "nx_api.h"
+#include "nx_rtsp_server.h"
+#include "nx_rtp_sender.h"
+#include "demo_rtsp_over_rtp.h"
+
+
+/* Define the stack size for demo tasks. */
+#define DEMO_TEST_STACK_SIZE 2048
+#define DEMO_RTSP_SERVER_STACK_SIZE 2048
+static UCHAR test_thread_stack[DEMO_TEST_STACK_SIZE];
+static UCHAR rtsp_server_stack[DEMO_RTSP_SERVER_STACK_SIZE];
+
+/* Define rtp cname which is typically used in rtcp sender report. */
+#define DEMO_RTP_CNAME "[email protected]"
+
+/* Define multicast corresponding parameters. !Note: these parameters in sdp shall be changed with the same values. */
+#ifdef DEMO_MULTICAST_ENABLED
+
+#ifndef DEMO_MULTICAST_IP_ADDRESS
+#define DEMO_MULTICAST_IP_ADDRESS IP_ADDRESS(224, 1, 0, 55)
+#endif /* DEMO_MULTICAST_IP_ADDRESS */
+
+#ifndef DEMO_MULTICAST_RTP_PORT
+#define DEMO_MULTICAST_RTP_PORT 6002
+#endif /* DEMO_MULTICAST_RTP_PORT */
+
+#ifndef DEMO_MULTICAST_RTCP_PORT
+#define DEMO_MULTICAST_RTCP_PORT 6003
+#endif /* DEMO_MULTICAST_RTCP_PORT */
+
+#endif /* DEMO_MULTICAST_ENABLED */
+
+/* The RTSP server listening port. */
+#ifndef DEMO_RTSP_SERVER_PORT
+#define DEMO_RTSP_SERVER_PORT 554
+#endif /* DEMO_RTSP_SERVER_PORT */
+
+/* The RTSP server thread priority. */
+#ifndef DEMO_RTSP_SERVER_PRIORITY
+#define DEMO_RTSP_SERVER_PRIORITY 3
+#endif /* DEMO_RTSP_SERVER_PRIORITY */
+
+/* File name shown in rtsp SETUP request */
+#ifndef DEMO_RTSP_VIDEO_FILE_NAME
+#define DEMO_RTSP_VIDEO_FILE_NAME "trackID=0"
+#endif /* DEMO_RTSP_VIDEO_FILE_NAME */
+
+#ifndef DEMO_RTSP_AUDIO_FILE_NAME
+#define DEMO_RTSP_AUDIO_FILE_NAME "trackID=1"
+#endif /* DEMO_RTSP_AUDIO_FILE_NAME */
+
+/* Define RTP payload type for medias. !Note: payload type in sdp shall be changed with the same values */
+#ifndef DEMO_RTP_PAYLOAD_TYPE_VIDEO
+#if (DEMO_VIDEO_FORMAT == DEMO_VIDEO_FORMAT_MJPEG)
+#define DEMO_RTP_PAYLOAD_TYPE_VIDEO 26
+#else
+#define DEMO_RTP_PAYLOAD_TYPE_VIDEO 96 /* Use dynamic type range from 96 to 127 */
+#endif /* (DEMO_VIDEO_FORMAT == DEMO_VIDEO_FORMAT_MJPEG) */
+#endif /* DEMO_RTP_PAYLOAD_TYPE_VIDEO */
+
+#ifndef DEMO_RTP_PAYLOAD_TYPE_AUDIO
+#if (DEMO_AUDIO_FORMAT == DEMO_AUDIO_FORMAT_AAC)
+#define DEMO_RTP_PAYLOAD_TYPE_AUDIO 97
+#else
+#define DEMO_RTP_PAYLOAD_TYPE_AUDIO 11
+#endif /* (DEMO_AUDIO_FORMAT == DEMO_AUDIO_FORMAT_AAC) */
+#endif /* DEMO_RTP_PAYLOAD_TYPE_AUDIO */
+
+/* Define video & audio play fps. !Note: this macro shall be the same as the real FPS to guarantee video playing normally */
+#ifndef DEMO_VIDEO_FRAME_PER_SECOND
+#define DEMO_VIDEO_FRAME_PER_SECOND 30
+#endif /* DEMO_VIDEO_FRAME_PER_SECOND */
+
+#ifndef DEMO_AUDIO_FRAME_PER_SECOND
+#define DEMO_AUDIO_FRAME_PER_SECOND 43 /* Reference the comment of DEMO_RTP_AUDIO_SAMPLING_PERIOD
+ to understand how this macro is calculated and defined. */
+#endif /* DEMO_AUDIO_FRAME_PER_SECOND */
+
+#ifndef DEMO_AUDIO_SAMPLE_SIZE
+#define DEMO_AUDIO_SAMPLE_SIZE 16 /* Indicate the size in bits for each audio sample. */
+#endif /* DEMO_AUDIO_SAMPLE_SIZE */
+
+#ifndef DEMO_AUDIO_CHANNEL_NUM
+#define DEMO_AUDIO_CHANNEL_NUM 1
+#endif /* DEMO_AUDIO_CHANNEL_NUM */
+
+/* The sampling periods define rtp timestamp increase rate for medias. */
+#define DEMO_RTP_VIDEO_SAMPLING_PERIOD (90000 / DEMO_VIDEO_FRAME_PER_SECOND)
+#define DEMO_RTP_AUDIO_SAMPLING_PERIOD (44100 / DEMO_AUDIO_FRAME_PER_SECOND) /* Assume the default AAC sampling rate is 44100.
+ Normally, a single ACC frame contains 1024 samples;
+ So, there are 44100 / 1024 = 43 frames per second.
+ Therefore, sampling period is 44100 / 43 = 1025. */
+
+/* Define frame play internal for medias */
+#define DEMO_RTP_VIDEO_PLAY_INTERVAL (1000 / DEMO_VIDEO_FRAME_PER_SECOND)
+#define DEMO_RTP_AUDIO_PLAY_INTERVAL (1000 / DEMO_AUDIO_FRAME_PER_SECOND)
+
+#ifndef DEMO_PLAY_TIMER_INTERVAL
+#define DEMO_PLAY_TIMER_INTERVAL 10 /* Per miliseconds */
+#endif /* DEMO_PLAY_TIMER_INTERVAL */
+
+/* Declare the prototypes for the test entry points. */
+TX_THREAD test_thread;
+NX_RTSP_SERVER rtsp_0;
+NX_RTP_SENDER rtp_0;
+
+/* Declare events to use in threads. */
+TX_EVENT_FLAGS_GROUP demo_test_events;
+
+/* Declare the timer to trigger events (e.g., playing video/audio). */
+TX_TIMER demo_timer;
+
+/* Declare the sample structure to support multiple clients interaction. */
+typedef struct SAMPLE_CLIENT_STRUCT
+{
+ NX_RTSP_CLIENT *rtsp_client_ptr;
+
+ /* RTP sessions */
+ NX_RTP_SESSION rtp_session_video;
+ NX_RTP_SESSION rtp_session_audio;
+
+ /* Count the number of clients setup in the specific rtp session */
+ USHORT rtp_session_video_client_count;
+ USHORT rtp_session_audio_client_count;
+
+ /* RTP timestamp and NTP timestamp */
+ ULONG rtp_session_video_timestamp;
+ ULONG rtp_session_audio_timestamp;
+
+#ifdef DEMO_PLAY_BY_TIMER
+ /* Accumulated ticks for determining when to play a video/audio frame */
+ volatile ULONG video_play_time_ms;
+ volatile ULONG audio_play_time_ms;
+#endif /* DEMO_PLAY_BY_TIMER */
+} SAMPLE_CLIENT;
+
+#ifdef DEMO_MULTICAST_ENABLED
+SAMPLE_CLIENT sample_client_multicast;
+#else
+SAMPLE_CLIENT sample_client[NX_RTSP_SERVER_MAX_CLIENTS];
+#endif /* DEMO_MULTICAST_ENABLED */
+
+/* Define an error counter. */
+ULONG error_counter;
+
+
+/* Internal functions prototype. */
+static UINT rtsp_describe_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length);
+static UINT rtsp_setup_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, NX_RTSP_TRANSPORT *transport_ptr);
+static UINT rtsp_play_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length);
+static UINT rtsp_teardown_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length);
+static UINT rtsp_pause_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length);
+static UINT rtsp_set_parameter_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *parameter_ptr, ULONG parameter_length);
+static UINT rtsp_disconnect_callback(NX_RTSP_CLIENT *rtsp_client_ptr);
+
+static UINT test_rtcp_receiver_report_callback(NX_RTP_SESSION *session, NX_RTCP_RECEIVER_REPORT *report);
+static UINT test_rtcp_sdes_callback(NX_RTCP_SDES_INFO *sdes_info);
+
+static VOID (*demo_media_data_init_callback)(VOID) = DEMO_MEDIA_DATA_INIT;
+static UINT (*demo_video_data_read_callback)(ULONG *ntp_msw, ULONG *ntp_lsw, UCHAR **data_ptr, ULONG *data_size) = DEMO_VIDEO_DATA_READ;
+static UINT (*demo_audio_data_read_callback)(ULONG *ntp_msw, ULONG *ntp_lsw, UCHAR **data_ptr, ULONG *data_size) = DEMO_AUDIO_DATA_READ;
+
+
+#ifdef DEMO_PLAY_BY_TIMER
+static VOID demo_timer_entry(ULONG address)
+{
+SAMPLE_CLIENT *client_ptr;
+
+#ifdef DEMO_MULTICAST_ENABLED
+ client_ptr = &sample_client_multicast;
+#else
+ for (UINT i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
+ {
+ client_ptr = &sample_client[i];
+#endif /* DEMO_MULTICAST_ENABLED */
+
+ if (client_ptr -> rtp_session_video_client_count)
+ {
+ client_ptr -> video_play_time_ms += DEMO_PLAY_TIMER_INTERVAL;
+ if (client_ptr -> video_play_time_ms >= DEMO_RTP_VIDEO_PLAY_INTERVAL)
+ {
+
+ /* Send the video ready event. */
+ tx_event_flags_set(&demo_test_events, DEMO_VIDEO_DATA_READY_EVENT, TX_OR);
+ }
+ }
+ if (client_ptr -> rtp_session_audio_client_count)
+ {
+ client_ptr -> audio_play_time_ms += DEMO_PLAY_TIMER_INTERVAL;
+ if (client_ptr -> audio_play_time_ms >= DEMO_RTP_AUDIO_PLAY_INTERVAL)
+ {
+
+ /* Send the audio ready event. */
+ tx_event_flags_set(&demo_test_events, DEMO_AUDIO_DATA_READY_EVENT, TX_OR);
+ }
+ }
+#ifndef DEMO_MULTICAST_ENABLED
+ }
+#endif /* DEMO_MULTICAST_ENABLED */
+}
+#endif /* DEMO_PLAY_BY_TIMER */
+
+/* Define what the initial system looks like. */
+void sample_entry(NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, VOID *dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time))
+{
+UINT i = 0;
+UINT status;
+ULONG events = 0;
+UCHAR initialized = NX_FALSE;
+ULONG ntp_msw, ntp_lsw;
+UCHAR *data;
+ULONG data_length;
+#if (DEMO_AUDIO_FORMAT == DEMO_AUDIO_FORMAT_PCM)
+NX_PACKET *send_packet = NX_NULL;
+#endif /* (DEMO_AUDIO_FORMAT == DEMO_AUDIO_FORMAT_PCM) */
+#ifndef DEMO_MULTICAST_ENABLED
+SAMPLE_CLIENT *client_ptr;
+#else
+SAMPLE_CLIENT *client_ptr = &sample_client_multicast;
+
+
+ /* Enable IGMP. */
+ status = nx_igmp_enable(ip_ptr);
+
+ /* Join multicast group. */
+ status += nx_ipv4_multicast_interface_join(ip_ptr, DEMO_MULTICAST_IP_ADDRESS, 0);
+ if (status)
+ error_counter++;
+#endif /* DEMO_MULTICAST_ENABLED */
+
+ status = nx_ip_fragment_enable(ip_ptr);
+ if (status)
+ error_counter++;
+
+ /* Create RTP sender */
+ nx_rtp_sender_create(&rtp_0, ip_ptr, pool_ptr, DEMO_RTP_CNAME, sizeof(DEMO_RTP_CNAME) - 1);
+ nx_rtp_sender_rtcp_receiver_report_callback_set(&rtp_0, test_rtcp_receiver_report_callback);
+ nx_rtp_sender_rtcp_sdes_callback_set(&rtp_0, test_rtcp_sdes_callback);
+
+ /* Create RTSP server. */
+ nx_rtsp_server_create(&rtsp_0, "RTSP Server", sizeof("RTSP Server") - 1, ip_ptr, pool_ptr,
+ rtsp_server_stack, DEMO_RTSP_SERVER_STACK_SIZE, DEMO_RTSP_SERVER_PRIORITY, DEMO_RTSP_SERVER_PORT, rtsp_disconnect_callback);
+
+ /* Set callback functions. */
+ nx_rtsp_server_describe_callback_set(&rtsp_0, rtsp_describe_callback);
+ nx_rtsp_server_setup_callback_set(&rtsp_0, rtsp_setup_callback);
+ nx_rtsp_server_play_callback_set(&rtsp_0, rtsp_play_callback);
+ nx_rtsp_server_teardown_callback_set(&rtsp_0, rtsp_teardown_callback);
+ nx_rtsp_server_pause_callback_set(&rtsp_0, rtsp_pause_callback);
+ nx_rtsp_server_set_parameter_callback_set(&rtsp_0, rtsp_set_parameter_callback);
+
+ /* Start RTSP server. */
+ nx_rtsp_server_start(&rtsp_0);
+
+ printf("RTSP server started!\r\n");
+
+ /* Create event for the play thread */
+ status = tx_event_flags_create(&demo_test_events, "Demo events");
+ if (status)
+ error_counter++;
+
+#ifdef DEMO_PLAY_BY_TIMER
+ /* Create the global timeout timer. */
+ status = tx_timer_create(&demo_timer, "Demo Timer", demo_timer_entry, 0,
+ (DEMO_PLAY_TIMER_INTERVAL * NX_IP_PERIODIC_RATE / 1000),
+ (DEMO_PLAY_TIMER_INTERVAL * NX_IP_PERIODIC_RATE / 1000),
+ TX_AUTO_ACTIVATE);
+ if (status)
+ error_counter++;
+#endif /* DEMO_PLAY_BY_TIMER */
+
+ /* Enter server test. */
+ while (1)
+ {
+
+ tx_event_flags_get(&demo_test_events, DEMO_ALL_EVENTS, TX_OR_CLEAR, &events, TX_WAIT_FOREVER);
+
+ /*********************************************
+ ************** DEMO_PLAY_EVENT ***************
+ *********************************************/
+ if (events & DEMO_PLAY_EVENT)
+ {
+ if (initialized == NX_FALSE)
+ {
+
+ /* Call user registered callback function to initialize. */
+ if (demo_media_data_init_callback)
+ {
+ demo_media_data_init_callback();
+ }
+
+#ifdef DEMO_PLAY_BY_TIMER
+ /* Set an initial value to eliminate too many ticks accumulation. */
+#ifdef DEMO_MULTICAST_ENABLED
+ client_ptr -> video_play_time_ms = 0;
+ client_ptr -> audio_play_time_ms = 0;
+#else
+ for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
+ {
+ client_ptr = &sample_client[i];
+ sample_client[i].video_play_time_ms = 0;
+ sample_client[i].audio_play_time_ms = 0;
+ }
+#endif /* DEMO_MULTICAST_ENABLED */
+#endif /* DEMO_PLAY_BY_TIMER */
+ }
+
+ /* Set the initialized flag */
+ initialized = NX_TRUE;
+ }
+
+ /*********************************************
+ ************ DEMO_TEARDOWN_EVENT *************
+ *********************************************/
+ if (events & DEMO_TEARDOWN_EVENT)
+ {
+#ifdef DEMO_MULTICAST_ENABLED
+ if ((client_ptr -> rtp_session_video_client_count == 0) &&
+ (client_ptr -> rtp_session_audio_client_count == 0))
+ {
+ initialized = NX_FALSE;
+ }
+
+#ifdef DEMO_PLAY_BY_TIMER
+ client_ptr -> video_play_time_ms = 0;
+ client_ptr -> audio_play_time_ms = 0;
+#endif /* DEMO_PLAY_BY_TIMER */
+#else
+ /* Check all client count to determine whether to clear the initialized flag */
+ for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
+ {
+ client_ptr = &sample_client[i];
+ if ((client_ptr -> rtp_session_video_client_count) ||
+ (client_ptr -> rtp_session_audio_client_count))
+ {
+ break;
+ }
+ }
+ if (i == NX_RTSP_SERVER_MAX_CLIENTS)
+ {
+ initialized = NX_FALSE;
+
+#ifdef DEMO_PLAY_BY_TIMER
+ for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
+ {
+ client_ptr -> video_play_time_ms = 0;
+ client_ptr -> audio_play_time_ms = 0;
+ }
+#endif /* DEMO_PLAY_BY_TIMER */
+ }
+#endif
+ }
+
+ /*********************************************
+ ******** DEMO_VIDEO_DATA_READY_EVENT *********
+ *********************************************/
+ if (events & DEMO_VIDEO_DATA_READY_EVENT)
+ {
+
+ /* Check if a play event has already triggered. */
+ if (initialized == NX_TRUE)
+ {
+
+ /* Check if the user has redefined DEMO_VIDEO_DATA_READ which registers video data read callback function. */
+ if (demo_video_data_read_callback == NX_NULL)
+ {
+ printf("User must implement video data read function and redefine DEMO_VIDEO_DATA_READ\r\n");
+ continue;
+ }
+
+ /* Read video data and transmit it */
+ data_length = 0;
+ if ((demo_video_data_read_callback(&ntp_msw, &ntp_lsw, &data, &data_length) == NX_SUCCESS) && (data_length > 0))
+ {
+#ifndef DEMO_MULTICAST_ENABLED
+ for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
+ {
+ client_ptr = &sample_client[i];
+#endif /* DEMO_MULTICAST_ENABLED */
+
+ /* Make sure at least one client having setup the connection. */
+ if (client_ptr -> rtp_session_video_client_count == 0)
+ {
+ continue;
+ }
+
+#if (DEMO_VIDEO_FORMAT == DEMO_VIDEO_FORMAT_H264)
+ status = nx_rtp_sender_session_h264_send(&(client_ptr -> rtp_session_video), data, data_length,
+ client_ptr -> rtp_session_video_timestamp, ntp_msw, ntp_lsw, NX_TRUE);
+#else
+ status = nx_rtp_sender_session_jpeg_send(&(client_ptr -> rtp_session_video), data, data_length,
+ client_ptr -> rtp_session_video_timestamp, ntp_msw, ntp_lsw, NX_TRUE);
+#endif /* (DEMO_VIDEO_FORMAT == DEMO_VIDEO_FORMAT_H264) */
+ if (status)
+ {
+ printf("Fail to send video frame: %d, %d\r\n", i, status);
+ }
+
+ /* Update rtp timestamp video sampling period. */
+ client_ptr -> rtp_session_video_timestamp += DEMO_RTP_VIDEO_SAMPLING_PERIOD;
+
+#ifdef DEMO_PLAY_BY_TIMER
+ if (client_ptr -> video_play_time_ms >= DEMO_RTP_VIDEO_PLAY_INTERVAL)
+ {
+ client_ptr -> video_play_time_ms -= DEMO_RTP_VIDEO_PLAY_INTERVAL;
+ }
+#endif /* DEMO_PLAY_BY_TIMER */
+#ifndef DEMO_MULTICAST_ENABLED
+ }
+#endif /* DEMO_MULTICAST_ENABLED */
+ }
+ }
+ }
+
+ /*********************************************
+ ******** DEMO_AUDIO_DATA_READY_EVENT *********
+ *********************************************/
+ if (events & DEMO_AUDIO_DATA_READY_EVENT)
+ {
+
+ /* Check if a play event has already triggered. */
+ if (initialized == NX_TRUE)
+ {
+
+ /* Check if the user has redefined DEMO_AUDIO_DATA_READ which registers audio data read callback function. */
+ if (demo_audio_data_read_callback == NX_NULL)
+ {
+ printf("User must implement audio data read function and redefine DEMO_AUDIO_DATA_READ\r\n");
+ continue;
+ }
+
+ /* Read audio data and transmit it */
+ data_length = 0;
+ if ((demo_audio_data_read_callback(&ntp_msw, &ntp_lsw, &data, &data_length) == NX_SUCCESS) && (data_length > 0))
+ {
+#ifndef DEMO_MULTICAST_ENABLED
+ for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
+ {
+ client_ptr = &sample_client[i];
+#endif /* DEMO_MULTICAST_ENABLED */
+
+ /* Make sure at least one client having setup the connection. */
+ if (client_ptr -> rtp_session_audio_client_count == 0)
+ {
+ continue;
+ }
+
+#if (DEMO_AUDIO_FORMAT == DEMO_AUDIO_FORMAT_AAC)
+ status = nx_rtp_sender_session_aac_send(&(client_ptr -> rtp_session_audio), data, data_length,
+ client_ptr -> rtp_session_audio_timestamp, ntp_msw, ntp_lsw, NX_TRUE);
+ if (status)
+ {
+ printf("Fail to send audio frame: %d, %d\r\n", i, status);
+ }
+
+ client_ptr -> rtp_session_audio_timestamp += DEMO_RTP_AUDIO_SAMPLING_PERIOD;
+#else
+ /* Allocate a rtp packet. */
+ nx_rtp_sender_session_packet_allocate(&(client_ptr -> rtp_session_audio), &send_packet, NX_WAIT_FOREVER);
+
+ /* Copy payload data into the packet. */
+ status = nx_packet_data_append(send_packet, (void *)data, data_length,
+ client_ptr -> rtp_session_audio.nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_WAIT_FOREVER);
+ if (status)
+ {
+ nx_packet_release(send_packet);
+ }
+
+ /* Send audio data frame through rtp */
+ status = nx_rtp_sender_session_packet_send(&(client_ptr -> rtp_session_audio), send_packet,
+ client_ptr -> rtp_session_audio_timestamp, ntp_msw, ntp_lsw, NX_FALSE);
+ if (status)
+ {
+ nx_packet_release(send_packet);
+ printf("Fail to send audio data: %d, %d\r\n", i, status);
+ }
+
+ /* Update rtp timestamp by the number of sampling bytes. */
+ client_ptr -> rtp_session_audio_timestamp += (data_length / (DEMO_AUDIO_SAMPLE_SIZE / 8));
+#endif /* (DEMO_AUDIO_FORMAT == DEMO_AUDIO_FORMAT_AAC) */
+
+#ifdef DEMO_PLAY_BY_TIMER
+ if (client_ptr -> audio_play_time_ms >= DEMO_RTP_AUDIO_PLAY_INTERVAL)
+ {
+ client_ptr -> audio_play_time_ms -= DEMO_RTP_AUDIO_PLAY_INTERVAL;
+ }
+#endif /* DEMO_PLAY_BY_TIMER */
+#ifndef DEMO_MULTICAST_ENABLED
+ }
+#endif /* DEMO_MULTICAST_ENABLED */
+ }
+ }
+ }
+ }
+}
+
+
+/* SDP string options. */
+#ifdef DEMO_MULTICAST_ENABLED
+#if (DEMO_VIDEO_FORMAT == DEMO_VIDEO_FORMAT_H264)
+#define DEMO_SDP \
+"v=0\r\ns=H264 video with AAC audio, streamed by the NetX RTSP Server\r\n"\
+"m=video 6002 RTP/AVP 96\r\n"\
+"c=IN IP4 224.1.0.55/128\r\n"\
+"a=rtpmap:96 H264/90000\r\n"\
+"a=fmtp:96 profile-level-id=42A01E; packetization-mode=1\r\n"\
+"a=control:trackID=0\r\n"\
+"m=audio 6002 RTP/AVP 97\r\n"\
+"c=IN IP4 224.1.0.55/128\r\n"\
+"a=rtpmap:97 mpeg4-generic/44100/1\r\n"\
+"a=fmtp:97 mode=AAC-hbr; SizeLength=13\r\n"\
+"a=control:trackID=1\r\n"
+#else
+#define DEMO_SDP \
+"v=0\r\ns=MJPEG video with AAC audio, streamed by the NetX RTSP Server\r\n"\
+"m=video 6002 RTP/AVP 26\r\n"\
+"c=IN IP4 224.1.0.55/128\r\n"\
+"a=rtpmap:26 JPEG/90000\r\n"\
+"a=control:trackID=0\r\n"\
+"m=audio 6002 RTP/AVP 11\r\n"\
+"c=IN IP4 224.1.0.55/128\r\n"\
+"a=rtpmap:11 L16/44100/1\r\n"\
+"a=fmtp:11 emphasis=50-15\r\n"\
+"a=ptime:5\r\n"\
+"a=control:trackID=1\r\n"
+#endif /* (DEMO_VIDEO_FORMAT == DEMO_VIDEO_FORMAT_H264) */
+#else
+#if (DEMO_VIDEO_FORMAT == DEMO_VIDEO_FORMAT_H264)
+#define DEMO_SDP \
+"v=0\r\ns=H264 video with AAC audio, streamed by the NetX RTSP Server\r\n"\
+"m=video 0 RTP/AVP 96\r\n"\
+"a=rtpmap:96 H264/90000\r\n"\
+"a=fmtp:96 profile-level-id=42A01E; packetization-mode=1\r\n"\
+"a=control:trackID=0\r\n"\
+"m=audio 0 RTP/AVP 97\r\n"\
+"a=rtpmap:97 mpeg4-generic/44100/1\r\n"\
+"a=fmtp:97 mode=AAC-hbr; SizeLength=13\r\n"\
+"a=control:trackID=1\r\n"
+#else
+#define DEMO_SDP \
+"v=0\r\ns=MJPEG video with AAC audio, streamed by the NetX RTSP Server\r\n"\
+"m=video 0 RTP/AVP 26\r\n"\
+"a=rtpmap:26 JPEG/90000\r\n"\
+"a=control:trackID=0\r\n"\
+"m=audio 0 RTP/AVP 11\r\n"\
+"a=rtpmap:11 L16/44100/1\r\n"\
+"a=fmtp:11 emphasis=50-15\r\n"\
+"a=ptime:5\r\n"\
+"a=control:trackID=1\r\n"
+#endif /* (DEMO_VIDEO_FORMAT == DEMO_VIDEO_FORMAT_H264) */
+#endif /* DEMO_MULTICAST_ENABLED */
+
+
+static UINT rtsp_describe_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length)
+{
+UINT status;
+
+
+ status = nx_rtsp_server_sdp_set(rtsp_client_ptr, (UCHAR *)DEMO_SDP, sizeof(DEMO_SDP));
+ printf("RTSP request received: DESCRIBE.\r\n");
+ return(status);
+}
+
+static UINT rtsp_setup_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, NX_RTSP_TRANSPORT *transport_ptr)
+{
+UINT status;
+UINT rtp_port, rtcp_port;
+SAMPLE_CLIENT *client_ptr = NX_NULL;
+#ifndef DEMO_MULTICAST_ENABLED
+UINT i;
+#endif /* DEMO_MULTICAST_ENABLED */
+
+
+ /* Print information from the client */
+ printf("RTSP request received: SETUP.\r\nuri: %s\r\nclient RTP port %d, RTCP port %d, IP %lu.%lu.%lu.%lu\r\n", uri,
+ transport_ptr -> client_rtp_port, transport_ptr -> client_rtcp_port,
+ (transport_ptr -> client_ip_address.nxd_ip_address.v4 >> 24),
+ (transport_ptr -> client_ip_address.nxd_ip_address.v4 >> 16) & 0xFF,
+ (transport_ptr -> client_ip_address.nxd_ip_address.v4 >> 8) & 0xFF,
+ (transport_ptr -> client_ip_address.nxd_ip_address.v4 & 0xFF));
+
+ /* Get the created and found ports */
+ status = nx_rtp_sender_port_get(&rtp_0, &rtp_port, &rtcp_port);
+ if (status)
+ {
+ return(status);
+ }
+ transport_ptr -> server_rtp_port = rtp_port;
+ transport_ptr -> server_rtcp_port = rtcp_port;
+
+#ifdef DEMO_MULTICAST_ENABLED
+ /* Judge and change to multicast if received ip address is 0 */
+ if (transport_ptr -> client_ip_address.nxd_ip_address.v4 != 0)
+ {
+ return(NX_NOT_SUCCESSFUL);
+ }
+
+ /* Assign multicast ip address and rtp/rtcp ports */
+ transport_ptr -> client_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
+ transport_ptr -> client_ip_address.nxd_ip_address.v4 = DEMO_MULTICAST_IP_ADDRESS;
+ transport_ptr -> client_rtp_port = DEMO_MULTICAST_RTP_PORT;
+ transport_ptr -> client_rtcp_port = DEMO_MULTICAST_RTCP_PORT;
+ transport_ptr -> multicast_ttl = NX_RTP_SENDER_TIME_TO_LIVE;
+
+ /* Directly use sample_client_multicast */
+ client_ptr = &sample_client_multicast;
+#else
+ /* Find and store the RTSP client pointer. */
+ for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
+ {
+
+ /* Check if the client is already linked. */
+ if (sample_client[i].rtsp_client_ptr == rtsp_client_ptr)
+ {
+ client_ptr = &(sample_client[i]);
+ break;
+ }
+
+ if ((client_ptr == NX_NULL) && (sample_client[i].rtsp_client_ptr == NX_NULL))
+ {
+
+ /* Record the unused position. */
+ client_ptr = &(sample_client[i]);
+ }
+ }
+
+ /* Check and return error if reach max connected clients limitation. */
+ if (client_ptr == NX_NULL)
+ {
+ return(NX_NOT_SUCCESSFUL);
+ }
+
+ /* Link the client pointer if it is newly assigned. */
+ if (i == NX_RTSP_SERVER_MAX_CLIENTS)
+ {
+ client_ptr -> rtsp_client_ptr = rtsp_client_ptr;
+ }
+
+#endif /* DEMO_MULTICAST_ENABLED */
+
+ if (strstr((const char *)uri, DEMO_RTSP_VIDEO_FILE_NAME))
+ {
+ printf("Setup Video (track 0)..\r\n");
+
+#ifdef DEMO_MULTICAST_ENABLED
+ if (client_ptr -> rtp_session_video_client_count == 0)
+ {
+#endif /* DEMO_MULTICAST_ENABLED */
+
+ /* Setup rtp sender video session */
+ status = nx_rtp_sender_session_create(&rtp_0, &(client_ptr -> rtp_session_video), DEMO_RTP_PAYLOAD_TYPE_VIDEO,
+ transport_ptr -> interface_index, &(transport_ptr -> client_ip_address),
+ transport_ptr -> client_rtp_port, transport_ptr -> client_rtcp_port);
+ if (status)
+ {
+ printf("Fail to create video session\r\n");
+
+ /* Reset the client pointer if error status happens */
+ client_ptr -> rtsp_client_ptr = NX_NULL;
+ return(status);
+ }
+
+ /* Obtain generated ssrc */
+ status = nx_rtp_sender_session_ssrc_get(&(client_ptr -> rtp_session_video), &(transport_ptr -> rtp_ssrc));
+ if (status)
+ {
+
+ /* Reset the client pointer if error status happens */
+ client_ptr -> rtsp_client_ptr = NX_NULL;
+ return(status);
+ }
+
+ /* Reset corresponding variables */
+ client_ptr -> rtp_session_video_timestamp = (ULONG)NX_RAND();
+#ifdef DEMO_MULTICAST_ENABLED
+ }
+#endif /* DEMO_MULTICAST_ENABLED */
+
+ /* Increase the number of setup client. */
+ client_ptr -> rtp_session_video_client_count++;
+ }
+ else if (strstr((const char *)uri, DEMO_RTSP_AUDIO_FILE_NAME))
+ {
+ printf("Setup Audio (track 1)..\r\n");
+
+#ifdef DEMO_MULTICAST_ENABLED
+ if (client_ptr -> rtp_session_audio_client_count == 0)
+ {
+#endif /* DEMO_MULTICAST_ENABLED */
+
+ /* Setup rtp sender audio session */
+ status = nx_rtp_sender_session_create(&rtp_0, &(client_ptr -> rtp_session_audio), DEMO_RTP_PAYLOAD_TYPE_AUDIO,
+ transport_ptr -> interface_index, &(transport_ptr -> client_ip_address),
+ transport_ptr -> client_rtp_port, transport_ptr -> client_rtcp_port);
+ if (status)
+ {
+ printf("Fail to create audio session\r\n");
+
+ /* Reset the client pointer if error status happens */
+ client_ptr -> rtsp_client_ptr = NX_NULL;
+ return(status);
+ }
+
+ /* Obtain generated ssrc */
+ status = nx_rtp_sender_session_ssrc_get(&(client_ptr -> rtp_session_audio), &(transport_ptr -> rtp_ssrc));
+ if (status)
+ {
+
+ /* Reset the client pointer if error status happens */
+ client_ptr -> rtsp_client_ptr = NX_NULL;
+ return(status);
+ }
+
+ /* Reset corresponding variables */
+ client_ptr -> rtp_session_audio_timestamp = (ULONG)NX_RAND();
+
+#if (DEMO_AUDIO_FORMAT == DEMO_AUDIO_FORMAT_PCM)
+ nx_rtp_sender_session_sample_factor_set(&(client_ptr -> rtp_session_audio), (DEMO_AUDIO_SAMPLE_SIZE / 8) * DEMO_AUDIO_CHANNEL_NUM);
+#endif /* (DEMO_AUDIO_FORMAT == DEMO_AUDIO_FORMAT_PCM) */
+#ifdef DEMO_MULTICAST_ENABLED
+ }
+#endif /* DEMO_MULTICAST_ENABLED */
+
+ /* Increase the number of setup client. */
+ client_ptr -> rtp_session_audio_client_count++;
+ }
+ else
+ {
+ printf("Invalid track ID!\r\n");
+ return(NX_NOT_SUCCESSFUL);
+ }
+
+ return(NX_SUCCESS);
+}
+
+static UINT rtsp_play_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length)
+{
+UINT status;
+UINT video_seq, audio_seq, video_rtptime, audio_rtptime;
+SAMPLE_CLIENT *client_ptr;
+#ifndef DEMO_MULTICAST_ENABLED
+UINT i;
+#endif
+
+
+ printf("RTSP request received: PLAY.\r\n");
+
+#ifndef DEMO_MULTICAST_ENABLED
+ /* Search and find the RTSP client. */
+ for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
+ {
+ if (sample_client[i].rtsp_client_ptr == rtsp_client_ptr)
+ {
+ client_ptr = &sample_client[i];
+ break;
+ }
+ }
+ if (i == NX_RTSP_SERVER_MAX_CLIENTS)
+ {
+ printf("Fail to find rtsp client!\r\n");
+ return(NX_NOT_SUCCESSFUL);
+ }
+#else
+ /* Directly use sample_client_multicast */
+ client_ptr = &sample_client_multicast;
+#endif /* DEMO_MULTICAST_ENABLED */
+
+ if (client_ptr -> rtp_session_video_client_count)
+ {
+
+ /* Retrieve the sequence number through rtp sender functions */
+ nx_rtp_sender_session_sequence_number_get(&(client_ptr -> rtp_session_video), &video_seq);
+
+ /* Assign recorded timestamps */
+ video_rtptime = client_ptr -> rtp_session_video_timestamp;
+
+ /* Set rtp information into rtsp client */
+ status = nx_rtsp_server_rtp_info_set(rtsp_client_ptr, DEMO_RTSP_VIDEO_FILE_NAME, sizeof(DEMO_RTSP_VIDEO_FILE_NAME) - 1, video_seq, video_rtptime);
+ if (status)
+ {
+ return(status);
+ }
+ }
+
+ if (client_ptr -> rtp_session_audio_client_count)
+ {
+
+ /* Retrieve the sequence number through rtp sender functions */
+ nx_rtp_sender_session_sequence_number_get(&(client_ptr -> rtp_session_audio), &audio_seq);
+
+ /* Assign recorded timestamps */
+ audio_rtptime = client_ptr -> rtp_session_audio_timestamp;
+
+ /* Set rtp information into rtsp client */
+ status = nx_rtsp_server_rtp_info_set(rtsp_client_ptr, DEMO_RTSP_AUDIO_FILE_NAME, sizeof(DEMO_RTSP_AUDIO_FILE_NAME) - 1, audio_seq, audio_rtptime);
+ if (status)
+ {
+ return(status);
+ }
+ }
+
+ /* Trigger the play event */
+ tx_event_flags_set(&demo_test_events, DEMO_PLAY_EVENT, TX_OR);
+
+ return(NX_SUCCESS);
+}
+
+static UINT rtsp_teardown_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length)
+{
+SAMPLE_CLIENT *client_ptr;
+#ifndef DEMO_MULTICAST_ENABLED
+UINT i;
+
+
+ printf("RTSP request received: TEARDOWN.\r\n");
+
+ /* Find the RTSP client pointer. */
+ for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
+ {
+ if (sample_client[i].rtsp_client_ptr == rtsp_client_ptr)
+ {
+ client_ptr = &(sample_client[i]);
+ break;
+ }
+ }
+ if (i == NX_RTSP_SERVER_MAX_CLIENTS)
+ {
+ printf("Fail to find rtsp client!\r\n");
+ return(NX_NOT_SUCCESSFUL);
+ }
+#else
+ /* Directly use sample_client_multicast */
+ client_ptr = &sample_client_multicast;
+#endif /* DEMO_MULTICAST_ENABLED */
+
+ /* Decrease session client count */
+ if (client_ptr -> rtp_session_video_client_count > 0)
+ {
+ client_ptr -> rtp_session_video_client_count--;
+#ifdef DEMO_MULTICAST_ENABLED
+ if (client_ptr -> rtp_session_video_client_count == 0)
+#endif
+ {
+ client_ptr -> rtsp_client_ptr = NX_NULL;
+ nx_rtp_sender_session_delete(&(client_ptr -> rtp_session_video));
+ }
+ }
+ if (client_ptr -> rtp_session_audio_client_count > 0)
+ {
+ client_ptr -> rtp_session_audio_client_count--;
+#ifdef DEMO_MULTICAST_ENABLED
+ if (client_ptr -> rtp_session_audio_client_count == 0)
+#endif
+ {
+ client_ptr -> rtsp_client_ptr = NX_NULL;
+ nx_rtp_sender_session_delete(&(client_ptr -> rtp_session_audio));
+ }
+ }
+
+ /* Trigger the tear down event */
+ tx_event_flags_set(&demo_test_events, DEMO_TEARDOWN_EVENT, TX_OR);
+
+ return(NX_SUCCESS);
+}
+
+static UINT rtsp_pause_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length)
+{
+ printf("RTSP request received: PAUSE.\r\n");
+
+ return(NX_SUCCESS);
+}
+
+static UINT rtsp_set_parameter_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *parameter_ptr, ULONG parameter_length)
+{
+ printf("RTSP request received: SET PARAMETER.\r\n");
+
+ return(NX_SUCCESS);
+}
+
+static UINT rtsp_disconnect_callback(NX_RTSP_CLIENT *rtsp_client_ptr)
+{
+
+ /* Trigger the tear down event */
+ tx_event_flags_set(&demo_test_events, DEMO_TEARDOWN_EVENT, TX_OR);
+
+ return(NX_SUCCESS);
+}
+
+static UINT test_rtcp_receiver_report_callback(NX_RTP_SESSION *session, NX_RTCP_RECEIVER_REPORT *report)
+{
+#ifndef DEMO_MULTICAST_ENABLED
+UINT i;
+
+ /* Search the rtsp client table and find which session it is*/
+ for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
+ {
+ if (session == &(sample_client[i].rtp_session_video))
+ {
+ break;
+ }
+ else if (session == &(sample_client[i].rtp_session_audio))
+ {
+ break;
+ }
+ }
+ if (i == NX_RTSP_SERVER_MAX_CLIENTS)
+ {
+
+ /* Unkown session, return directly. */
+ return(NX_SUCCESS);
+ }
+#endif /* DEMO_MULTICAST_ENABLED */
+
+ /*
+ We can add user implementation code here..
+
+ Note!: since this callback is invoked from the IP thread, the application should not block in this callback.
+
+ Tip: in this callback, we can obtain and record below information:
+ 1) report -> receiver_ssrc: the ssrc of the receiver who sends the rr report
+ 2) report -> fraction_loss: the fraction lost of the receiver
+ 3) report -> packet_loss: the cumulative number of packets lost of the receiver
+ 4) report -> extended_max: the extended highest sequence number received of the receiver
+ 5) report -> jitter: the inter-arrival jitter of the receiver
+ 6) report -> last_sr: the last SR timestamp of the receiver
+ 7) report -> delay: the delay since last SR timestamp of the receiver.
+ */
+
+ /* Update the timeout of RTSP server since the RTCP message proves liveness. */
+#ifdef DEMO_MULTICAST_ENABLED
+ nx_rtsp_server_keepalive_update(sample_client_multicast.rtsp_client_ptr);
+#else
+ nx_rtsp_server_keepalive_update(sample_client[i].rtsp_client_ptr);
+#endif /* DEMO_MULTICAST_ENABLED */
+
+ return(NX_SUCCESS);
+}
+
+static UINT test_rtcp_sdes_callback(NX_RTCP_SDES_INFO *sdes_info)
+{
+ /*
+ We can add user implementation code here..
+
+ Note!: since this callback is invoked from the IP thread, the application should not block in this callback.
+
+ Tip: in this callback, we can obtain and record below information:
+ 1) sdes_info -> ssrc: the ssrc of the receiver who sends the sdes packet
+ 2) sdes_info -> cname_length: the length of the cname field
+ 3) sdes_info -> cname: the cname field
+ */
+
+ return NX_SUCCESS;
+}
diff --git a/samples/demo_rtsp_over_rtp.h b/samples/demo_rtsp_over_rtp.h
new file mode 100644
index 00000000..b85839b4
--- /dev/null
+++ b/samples/demo_rtsp_over_rtp.h
@@ -0,0 +1,95 @@
+/* This is an include file for the rtsp over rtp demo programs. It is not part of the official release of NetXDuo RTSP Server or RTP Sender.
+ It is simply a convenience for the user to have a simple demo program to use as a starting point for their application.
+ Please be carefully to read the Note! below and execute the corresponding actions before using this demo program. */
+
+#ifndef DEMO_RTSP_OVER_RTP_H
+#define DEMO_RTSP_OVER_RTP_H
+
+/* Determine if a C++ compiler is being used. If so, ensure that standard
+ C is used to process the API information. */
+
+#ifdef __cplusplus
+
+/* Yes, C++ compiler is present. Use standard C. */
+extern "C" {
+#endif
+
+#include "tx_api.h"
+#include "nx_api.h"
+
+
+/* Note!: declare demo events to use in the threads.
+ 1. For event triggered RTP sending, user can use below example codes to trigger audio/video data reading and sending by rtp:
+ 1) Video data: tx_event_flags_set(&demo_test_events, DEMO_AUDIO_DATA_READY_EVENT, TX_OR);
+ 2) Audio data: tx_event_flags_set(&demo_test_events, DEMO_VIDEO_DATA_READY_EVENT, TX_OR);
+ 2. For timer timeout trigger RTP sending, user can define the macro DEMO_PLAY_BY_TIMER by uncomment it below.
+*/
+extern TX_EVENT_FLAGS_GROUP demo_test_events;
+
+#define DEMO_ALL_EVENTS ((ULONG)0xFFFFFFFF)
+#define DEMO_PLAY_EVENT ((ULONG)0x00000001)
+#define DEMO_TEARDOWN_EVENT ((ULONG)0x00000002)
+#define DEMO_VIDEO_DATA_READY_EVENT ((ULONG)0x00000004)
+#define DEMO_AUDIO_DATA_READY_EVENT ((ULONG)0x00000008)
+
+/* Define user defined macros. */
+/* Using unicast by default, if DEMO_MULTICAST_ENABLED is defined, using multicast. */
+/*
+#define DEMO_MULTICAST_ENABLED
+*/
+
+/* Using user triggered playing by default, if DEMO_PLAY_BY_TIMER is define, using timer timeout event to play medias. */
+/*
+#define DEMO_PLAY_BY_TIMER
+*/
+
+/* Define audio format options. */
+#define DEMO_AUDIO_FORMAT_PCM 0
+#define DEMO_AUDIO_FORMAT_AAC 1
+
+/* Define video format options. */
+#define DEMO_VIDEO_FORMAT_MJPEG 0
+#define DEMO_VIDEO_FORMAT_H264 1
+
+/* Using AAC by default, user can re-define this macro to one of the audio format options above. */
+#ifndef DEMO_AUDIO_FORMAT
+#define DEMO_AUDIO_FORMAT DEMO_AUDIO_FORMAT_AAC
+#endif /* DEMO_AUDIO_FORMAT */
+
+/* Using H.264 by default, user can re-define this macro to one of the video format options above. */
+#ifndef DEMO_VIDEO_FORMAT
+#define DEMO_VIDEO_FORMAT DEMO_VIDEO_FORMAT_H264
+#endif /* DEMO_VIDEO_FORMAT */
+
+
+/* Note!: Below are user implemented callback functions corresponding declarations. The program uses macros
+ DEMO_MEDIA_DATA_INIT, DEMO_VIDEO_DATA_READ and DEMO_AUDIO_DATA_READ as default callback functions
+ for media data initialization, video data reading and audio data reading separately.
+
+ 1. DEMO_MEDIA_DATA_INIT could be its default value NX_NULL if user does not need to execute any code after RTSP PLAY command is received.
+ Otherwise, user can define a callback with the prototype "VOID (*demo_media_data_init_callback)(VOID)" and implement the callback function.
+
+ 2. DEMO_VIDEO_DATA_READ could be its default value NX_NULL if user does not implement video data reading and transmitting.
+ Otherwise, user MUST! define a callback with the prototype "UINT (*demo_video_data_read_callback)(ULONG *ntp_msw, ULONG *ntp_lsw, UCHAR **data_ptr, ULONG *data_size)"
+ and implement the callback function.
+ Both MJPEG and H264 video formats are frame based, so the callback function should return a complete frame data each time.
+
+ 3. DEMO_AUDIO_DATA_READ could be its default value NX_NULL if user does not implement audio data reading and transmitting.
+ Otherwise, user MUST! define a callback with the prototype "UINT (*demo_audio_data_read_callback)(ULONG *ntp_msw, ULONG *ntp_lsw, UCHAR **data_ptr, ULONG *data_size)"
+ and implement the callback function.
+ By default, PCM audio format is data based, so there is no limitation for the data size returned by the callback function.
+ If the macro DEMO_AAC_ENABLED is enabled, the callback function should return a complete AAC frame data each time.
+*/
+#ifndef DEMO_MEDIA_DATA_INIT
+#define DEMO_MEDIA_DATA_INIT NX_NULL
+#endif /* DEMO_MEDIA_DATA_INIT */
+
+#ifndef DEMO_VIDEO_DATA_READ
+#define DEMO_VIDEO_DATA_READ NX_NULL
+#endif /* DEMO_VIDEO_DATA_READ */
+
+#ifndef DEMO_AUDIO_DATA_READ
+#define DEMO_AUDIO_DATA_READ NX_NULL
+#endif /* DEMO_AUDIO_DATA_READ */
+
+#endif /* DEMO_RTSP_OVER_RTP_H */
diff --git a/addons/azure_iot/samples/main.c b/samples/main.c
index 93592de0..f57ad9de 100644
--- a/addons/azure_iot/samples/main.c
+++ b/samples/main.c
@@ -33,7 +33,7 @@
#endif /* SAMPLE_HTTP_PROXY_ENABLE */
/* Include the sample. */
-extern VOID sample_entry(NX_IP* ip_ptr, NX_PACKET_POOL* pool_ptr, NX_DNS* dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time));
+extern VOID sample_entry(NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, VOID *dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time));
/* Define the helper thread for running Azure SDK on ThreadX (THREADX IoT Platform). */
#ifndef SAMPLE_HELPER_STACK_SIZE
@@ -409,7 +409,7 @@ NXD_ADDRESS proxy_server_address;
srand(unix_time);
/* Start sample. */
- sample_entry(&ip_0, &pool_0, &dns_0, unix_time_get);
+ sample_entry(&ip_0, &pool_0, (VOID *)&dns_0, unix_time_get);
}
#ifndef SAMPLE_DHCP_DISABLE
diff --git a/utility/iperf/nx_iperf.c b/utility/iperf/nx_iperf.c
index 907b5ad8..ae8d784c 100644
--- a/utility/iperf/nx_iperf.c
+++ b/utility/iperf/nx_iperf.c
@@ -115,6 +115,14 @@ void nx_iperf_entry(NX_PACKET_POOL *pool_ptr, NX_IP *ip_ptr, UCHAR *http_stac
{
UINT status;
+ /* 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;
+
/* Create a TCP server 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,
@@ -171,14 +179,6 @@ UINT status;
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);