From 531239b44a13845130ff87e9632d9de61d072177 Mon Sep 17 00:00:00 2001 From: Tiejun Zhou Date: Mon, 23 Oct 2023 05:28:48 +0000 Subject: [PATCH] Update on 23 Oct 2023. Expand to see details. 002a5890e Generated rtxp demo in netxduo/samples folder. c09d9da51 Add function header in .h for RTP and RTSP f5a96f35b Update function header and version for 6.3.0 0ff7a6809 Correct dhcpv6 server for ignoring lifetime fields in client request 9a2129c35 Fixed dhcpv6 server not update client record issue e59d2b5f1 Fix dhcp coverage test compile wanrning d00655d71 Fix infinite loop issue in TCP & UDP free port find function c194c74ca Optimize rtp_sender and fix pipeline reported issues b6df8dea0 Add RTxP feature 38e57e633 Added test case for _nx_snmp_utility_object_id_get(). 321c88bd9 Added check for pdu length. 36ffb7c39 Fixed packet double release. 92166d736 Fixed SNMP test cases for v4_small_build 67f071552 Improved buffer length verification for padding. 30cc5d8b2 Fix wait option used in FTP test case 098a97213 Avoid duplicate packet release when DTLS send fails 15313e868 Improved buffer length verification for _nx_snmp_utility_object_id_set(). ecd3904d3 Fixed MSRC 81018 caa004007 Fix the logic of handling close notify packet from peer 2b8c87685 Removed main.c into netxduo/samples folder, then all addons can use it. c72c66cdc Fixed MSARC 81019 and MSRC 81079 8169be7a6 Fixed MSRC81005 and MSRC81020 41389b76b Fixed packet double release issue in _nx_ftp_client_file_write 19348e408 Combined the functions of processing snmp v1 and v2. 9174b6457 Fixed icmpv6 ra buffer overwrite test case. 6bdc703d9 Fixed packet double release issue in _nx_nat_process_packet 403ecd128 Set nx_smtp_server_packet to NULL to avoided duplicate packet release in _nx_smtp_utility_read_server_code af5dd00c6 Disable FTP server MSS test case when packet chain is disabled beadbce12 Enable weekly pipeline build to avoid CodeQL expiration 5a3d88f97 Fixed MSRC 81528 df6a1fc57 unify the code. 18c13bfdb Fixed MSRC 80745. 2cce43f48 Fixed bug in utility/iperf/nx_iperf.c pointer used before set its value. 2477fb81c Update product owners 2f5734ada Fixed MSRC 80686 34e713e26 Fixed data length underflow when TCP MSS is less than 255 7097a7859 Improved the test cases for packet chain. 1ffa13cfa Fixed MSRC 80685 97e2b8d8e Set packet pointer to NULL after released to fix duplicate packet release issue c1e47efa7 Fix ICMPv6 NS buffer overwrite issue. c2770ea68 Add ICMPv6 NA buffer overwrite test case. 36bb05f85 Validated TCP header buffer to avoid span in multiple packets 84070bb2a Correct the length of packet buffer to avoid write overflow 5b3b3a10b Dropped packet chain for SNTP data to avoid write overflow 82699872d Onebranch build Image Update: Move pipelines to supported and compliant OneBranch container images a30171f93 Add a test case to demonstrate IGMP override caused by IP assembly. 72472ff4b Fix MSRC 80746 5d9f1266a Corrected the acked packet count when out of order is enabled b113ebdc9 Fixed DHCP server local variable type issue b70863299 Enable codeql in onebranch pipeline --- addons/BSD/nxd_bsd.c | 220 +- addons/BSD/nxd_bsd.h | 6 +- addons/CMakeLists.txt | 4 + .../samples/sample_azure_iot_embedded_sdk.c | 6 +- .../sample_azure_iot_embedded_sdk_pnp.c | 6 +- addons/dhcp/nxd_dhcp_client.c | 12 +- addons/dhcp/nxd_dhcp_server.c | 25 +- addons/dhcp/nxd_dhcpv6_server.c | 84 +- addons/dns/nxd_dns.c | 9 +- addons/ftp/nxd_ftp_client.c | 14 +- addons/ftp/nxd_ftp_server.c | 3930 ++++++------- addons/mdns/nxd_mdns.h | 6 +- addons/mqtt/nxd_mqtt_client.c | 48 +- addons/mqtt/nxd_mqtt_client.h | 6 +- addons/nat/nx_nat.c | 25 +- addons/ppp/nx_ppp.c | 24 +- addons/ppp/nx_ppp.h | 6 +- addons/rtp/nx_rtp_sender.c | 3981 ++++++++++++++ addons/rtp/nx_rtp_sender.h | 495 ++ addons/rtsp/nx_rtsp_server.c | 4854 +++++++++++++++++ addons/rtsp/nx_rtsp_server.h | 535 ++ addons/smtp/nxd_smtp_client.c | 6 +- addons/snmp/nxd_snmp.c | 1535 ++---- addons/snmp/nxd_snmp.h | 11 +- addons/sntp/nxd_sntp_client.c | 17 +- common/inc/nx_api.h | 10 +- common/inc/nx_icmpv6.h | 22 +- common/inc/nx_user_sample.h | 6 +- common/src/nx_icmpv6_packet_process.c | 18 +- common/src/nx_icmpv6_process_na.c | 32 +- common/src/nx_icmpv6_process_ns.c | 25 +- common/src/nx_icmpv6_process_packet_too_big.c | 13 +- common/src/nx_icmpv6_process_ra.c | 25 +- common/src/nx_icmpv6_process_redirect.c | 11 +- common/src/nx_igmp_packet_process.c | 121 +- common/src/nx_ip_create.c | 6 +- common/src/nx_ip_header_add.c | 6 +- common/src/nx_ipv4_packet_receive.c | 21 +- common/src/nx_ipv6_fragment_process.c | 6 +- common/src/nx_tcp_free_port_find.c | 11 +- common/src/nx_tcp_packet_process.c | 25 +- common/src/nx_tcp_socket_state_data_check.c | 10 +- common/src/nx_udp_free_port_find.c | 11 +- crypto_libraries/src/nx_crypto_3des.c | 12 +- crypto_libraries/src/nx_crypto_aes.c | 42 +- crypto_libraries/src/nx_crypto_des.c | 12 +- crypto_libraries/src/nx_crypto_drbg.c | 12 +- crypto_libraries/src/nx_crypto_ecdh.c | 12 +- crypto_libraries/src/nx_crypto_ecdsa.c | 12 +- crypto_libraries/src/nx_crypto_ecjpake.c | 12 +- crypto_libraries/src/nx_crypto_hkdf.c | 12 +- crypto_libraries/src/nx_crypto_hmac.c | 12 +- crypto_libraries/src/nx_crypto_hmac_md5.c | 12 +- crypto_libraries/src/nx_crypto_hmac_sha1.c | 12 +- crypto_libraries/src/nx_crypto_hmac_sha2.c | 12 +- crypto_libraries/src/nx_crypto_hmac_sha5.c | 12 +- crypto_libraries/src/nx_crypto_md5.c | 6 +- crypto_libraries/src/nx_crypto_pkcs1_v1.5.c | 12 +- crypto_libraries/src/nx_crypto_rsa.c | 12 +- crypto_libraries/src/nx_crypto_sha1.c | 6 +- crypto_libraries/src/nx_crypto_sha2.c | 12 +- crypto_libraries/src/nx_crypto_sha5.c | 12 +- crypto_libraries/src/nx_crypto_tls_prf_1.c | 12 +- .../src/nx_crypto_tls_prf_sha256.c | 12 +- .../src/nx_crypto_tls_prf_sha384.c | 12 +- .../src/nx_crypto_tls_prf_sha512.c | 12 +- nx_secure/inc/nx_secure_tls.h | 7 +- nx_secure/ports/nx_secure_port.h | 2 +- nx_secure/src/nx_secure_dtls_send_record.c | 7 +- .../src/nx_secure_dtls_server_handshake.c | 8 +- nx_secure/src/nx_secure_dtls_session_end.c | 27 +- .../src/nx_secure_dtls_session_receive.c | 12 +- .../src/nx_secure_tls_send_certificate.c | 6 +- nx_secure/src/nxe_secure_tls_session_send.c | 6 +- ports/arc_em/metaware/inc/nx_port.h | 2 +- ports/arc_hs/metaware/inc/nx_port.h | 2 +- ports/cortex_a15/gnu/inc/nx_port.h | 2 +- ports/cortex_a5/ac5/inc/nx_port.h | 2 +- ports/cortex_a5/gnu/inc/nx_port.h | 2 +- ports/cortex_a5/iar/inc/nx_port.h | 2 +- ports/cortex_a5x/ac6/inc/nx_port.h | 2 +- ports/cortex_a7/ac5/inc/nx_port.h | 2 +- ports/cortex_a7/gnu/inc/nx_port.h | 2 +- ports/cortex_a7/iar/inc/nx_port.h | 2 +- ports/cortex_a8/ac5/inc/nx_port.h | 2 +- ports/cortex_a8/gnu/inc/nx_port.h | 2 +- ports/cortex_a8/iar/inc/nx_port.h | 2 +- ports/cortex_a9/ac5/inc/nx_port.h | 2 +- ports/cortex_a9/gnu/inc/nx_port.h | 2 +- ports/cortex_a9/iar/inc/nx_port.h | 2 +- ports/cortex_a9/rvds/inc/nx_port.h | 2 +- ports/cortex_m0/ac5/inc/nx_port.h | 2 +- ports/cortex_m0/gnu/inc/nx_port.h | 2 +- ports/cortex_m0/iar/inc/nx_port.h | 2 +- ports/cortex_m23/ac5/inc/nx_port.h | 2 +- ports/cortex_m23/gnu/inc/nx_port.h | 2 +- ports/cortex_m23/iar/inc/nx_port.h | 2 +- ports/cortex_m3/ac5/inc/nx_port.h | 2 +- ports/cortex_m3/gnu/inc/nx_port.h | 2 +- ports/cortex_m3/iar/inc/nx_port.h | 2 +- ports/cortex_m3/keil/inc/nx_port.h | 2 +- ports/cortex_m33/ac5/inc/nx_port.h | 2 +- ports/cortex_m33/ac6/inc/nx_port.h | 2 +- ports/cortex_m33/gnu/inc/nx_port.h | 2 +- ports/cortex_m33/iar/inc/nx_port.h | 2 +- ports/cortex_m4/ac5/inc/nx_port.h | 2 +- ports/cortex_m4/gnu/inc/nx_port.h | 2 +- ports/cortex_m4/iar/inc/nx_port.h | 2 +- ports/cortex_m4/keil/inc/nx_port.h | 2 +- ports/cortex_m55/ac5/inc/nx_port.h | 2 +- ports/cortex_m55/ac6/inc/nx_port.h | 2 +- ports/cortex_m55/gnu/inc/nx_port.h | 2 +- ports/cortex_m55/iar/inc/nx_port.h | 2 +- ports/cortex_m7/ac5/inc/nx_port.h | 2 +- ports/cortex_m7/ac6/inc/nx_port.h | 2 +- ports/cortex_m7/gnu/inc/nx_port.h | 2 +- ports/cortex_m7/iar/inc/nx_port.h | 2 +- ports/cortex_m85/ac5/inc/nx_port.h | 2 +- ports/cortex_m85/ac6/inc/nx_port.h | 2 +- ports/cortex_m85/gnu/inc/nx_port.h | 2 +- ports/cortex_m85/iar/inc/nx_port.h | 2 +- ports/cortex_r4/ac5/inc/nx_port.h | 2 +- ports/cortex_r4/ac6/inc/nx_port.h | 2 +- ports/cortex_r4/gnu/inc/nx_port.h | 2 +- ports/cortex_r4/iar/inc/nx_port.h | 2 +- ports/cortex_r5/ac5/inc/nx_port.h | 2 +- ports/cortex_r5/gnu/inc/nx_port.h | 2 +- ports/cortex_r5/iar/inc/nx_port.h | 2 +- ports/linux/gnu/inc/nx_port.h | 2 +- ports/mips/gnu/inc/nx_port.h | 2 +- ports/rxv2/ccrx/inc/nx_port.h | 2 +- ports/rxv2/gnu/inc/nx_port.h | 2 +- ports/rxv2/iar/inc/nx_port.h | 2 +- ports/win32/vs_2019/inc/nx_port.h | 2 +- samples/demo_rtsp_over_rtp.c | 956 ++++ samples/demo_rtsp_over_rtp.h | 95 + {addons/azure_iot/samples => samples}/main.c | 4 +- utility/iperf/nx_iperf.c | 16 +- 138 files changed, 14003 insertions(+), 3801 deletions(-) create mode 100644 addons/rtp/nx_rtp_sender.c create mode 100644 addons/rtp/nx_rtp_sender.h create mode 100644 addons/rtsp/nx_rtsp_server.c create mode 100644 addons/rtsp/nx_rtsp_server.h create mode 100644 samples/demo_rtsp_over_rtp.c create mode 100644 samples/demo_rtsp_over_rtp.h rename {addons/azure_iot/samples => samples}/main.c (99%) 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; + /* Set the login as TRUE. */ + client_req_ptr -> nx_ftp_client_request_login = NX_TRUE; - if (status == NX_SUCCESS) - { - - /* 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++; - /* Call the logout function. */ - -#ifndef NX_DISABLE_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); - } -#endif /* NX_DISABLE_IPV4 */ - if (ftp_server_ptr -> nx_ftp_logout) + /* Check if this client login. */ + if (client_req_ptr -> nx_ftp_client_request_login) { - /* 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); - } + /* Call the logout function. */ - /* 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; +#ifndef NX_DISABLE_IPV4 + /* Does this server have an IPv4 login function? */ + if (ftp_server_ptr -> nx_ftp_logout_ipv4) + { - /* 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"); + /* 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) + { - /* If create, cleanup the associated data socket. */ - if (client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_id) - { + /* 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); + } - /* Clean up the client socket. */ - _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr); - } + /* 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; - /* Now disconnect the command socket. */ - nx_tcp_socket_disconnect(&(client_req_ptr -> nx_ftp_client_request_control_socket), NX_FTP_SERVER_TIMEOUT); + /* 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"); - /* Unaccept the server socket. */ - nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_ftp_client_request_control_socket)); + /* If create, cleanup the associated data socket. */ + if (client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_id) + { - /* 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)); + /* Clean up the client socket. */ + _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr); + } - /* Check to see if a packet is queued up. */ - if (client_req_ptr -> nx_ftp_client_request_packet) - { + /* Now disconnect the command socket. */ + nx_tcp_socket_disconnect(&(client_req_ptr -> nx_ftp_client_request_control_socket), NX_FTP_SERVER_TIMEOUT); - /* Yes, release it! */ - nx_packet_release(client_req_ptr -> nx_ftp_client_request_packet); - } + /* Unaccept the server socket. */ + nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_ftp_client_request_control_socket)); - /* Disable the client request activity timeout. */ - client_req_ptr -> nx_ftp_client_request_activity_timeout = 0; - break; - } + /* 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)); - 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); - /* The open for read command is successful! */ + /* If no error is present, register the receive notify function. */ + if (status == NX_SUCCESS) + { - /* 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; + /* 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 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; + /* 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); - /* 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 socket was bound. */ + if (status) + { - /* 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)) - { + /* 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)); + } + else + { - /* 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); + /* 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; - /* Calculate the maximum read size. */ - length = ((ULONG) (packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr)) - NX_PHYSICAL_TRAILER; + /* 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 length is greater than the connected MSS. */ - if (length > client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss) + /* 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 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); - /* Determine if the file create/open was successful. */ - if (status == FX_SUCCESS) - { + /* Truncate the file to a size of 0. */ + status += fx_file_truncate(&(client_req_ptr -> nx_ftp_client_request_file), 0); - /* 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++; + } + + /* If specified path ends with slash or backslash, strip it. */ + if ((j > 1) && ((buffer_ptr[j - 1] == '/') || (buffer_ptr[j - 1] == '\\'))) + { + j--; + } - /* Successful start to the file rename. */ + /* Ensure the name is NULL terminated. */ + buffer_ptr[j] = NX_NULL; - /* Save the packet in the client request structure. */ - client_req_ptr -> nx_ftp_client_request_packet = packet_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); - /* 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); + /* 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); - /* 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 - { + /* Determine if it was successful. */ + if (status == NX_SUCCESS) + { - /* Unsuccessful first half of file rename. */ + /* Successful start to the 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; - } + /* Save the packet in the client request structure. */ + client_req_ptr -> nx_ftp_client_request_packet = packet_ptr; - case NX_FTP_RNTO: - { + /* 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); - /* 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_FILE_PEND, "Rename File From"); + } + else + { - /* Empty message. */ + /* 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 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_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++; + } + + /* 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; - /* 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); + /* 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++; + } - /* 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--; + } - /* Remove the specified directory. */ - status = fx_directory_delete(ftp_server_ptr -> nx_ftp_server_media_ptr, (CHAR *) buffer_ptr); + /* 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); #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); + /* Just set the buffer pointer to NULL since there isn't a string. */ + buffer_ptr = 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; + /* 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; + + /* 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) + { + + /* 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)); + } + 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); + } + } + } + } - /* Determine if the block mode is enabled. */ - if (client_req_ptr -> nx_ftp_client_request_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK) + /* Now check and see if the directory listing command has any errors. */ + if (status == NX_SUCCESS) { - /* Get the directory listing size. */ - _nx_ftp_server_block_size_get(ftp_server_ptr, ftp_command, filename, &block_size); + /* The directory listing is successful! */ - /* 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); - } + /* 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"); - /* 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 block mode is enabled. */ + if (client_req_ptr -> nx_ftp_client_request_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK) + { - /* Calculate the remaining length. */ - remaining_length = (ULONG)((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_append_ptr) - NX_PHYSICAL_TRAILER); + /* Get the directory listing size. */ + _nx_ftp_server_block_size_get(ftp_server_ptr, ftp_command, filename, &block_size); - /* 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 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); + } - /* Reduce the remaining length to the MSS value. */ - remaining_length = client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss; - } + /* 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 generate the full directory listing and send the contents to the client. */ - j = 0; - while (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); - /* Pickup the next directory entry. */ - if (j == 0) + /* 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) { - - /* 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); - + /* Reduce the remaining length to the MSS value. */ + remaining_length = client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss; } - else + + /* Now generate the full directory listing and send the contents to the client. */ + j = 0; + while (status == NX_SUCCESS) { - /* 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); + /* Pickup the next directory entry. */ + if (j == 0) + { - } - /* Increment the entry count. */ - j++; + /* 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); - /* Determine if successful. */ - if (status == NX_SUCCESS) - { + } + else + { - /* Setup pointer to buffer. */ - buffer_ptr = packet_ptr -> nx_packet_append_ptr; + /* 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); - /* Calculate the size of the name. */ - length = 0; - do - { - 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) - { + /* Increment the entry count. */ + j++; - /* Send the current buffer out. */ + /* Determine if successful. */ + if (status == NX_SUCCESS) + { - /* 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); + /* Setup pointer to buffer. */ + buffer_ptr = packet_ptr -> nx_packet_append_ptr; - /* Determine if the send was unsuccessful. */ - if (status) + /* Calculate the size of the name. */ + length = 0; + do + { + 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) { - - /* Release the packet. */ - nx_packet_release(packet_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); + /* Send the current buffer out. */ - /* Determine if the packet allocate was successfull. */ - if (status) - { + /* 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); - /* Get out of the loop! */ - break; - } + /* Determine if the send was unsuccessful. */ + if (status) + { + + /* Release the packet. */ + nx_packet_release(packet_ptr); + } - /* Calculate the remaining length. */ - remaining_length = (ULONG)((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_append_ptr) - NX_PHYSICAL_TRAILER); + /* 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 advertised MSS is even less. */ - if (remaining_length > client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss) - { + /* Determine if the packet allocate was successful. */ + if (status) + { - /* Reduce the remaining length to the MSS value. */ - remaining_length = client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss; - } + /* Get out of the loop! */ + break; + } - /* Setup pointer to buffer. */ - buffer_ptr = packet_ptr -> nx_packet_append_ptr; - } + /* 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); + + /* 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) + { - /* Check if the month is valid before convert it. */ - if ((month < 1) || (month > 12)) - continue; + /* Send the current buffer out. */ - /* Setup pointer to buffer. */ - buffer_ptr = packet_ptr -> nx_packet_append_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); - /* Calculate the size of the name. */ - length = 0; - do - { - if (filename[length]) - length++; - else - break; - } while (length < FX_MAX_LONG_NAME_LEN); + /* Determine if the send was unsuccessful. */ + if (status) + { + + /* Release the packet. */ + nx_packet_release(packet_ptr); + } - /* 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) - { + /* 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 current buffer out. */ + /* Determine if the packet allocate was successfull. */ + if (status) + { - /* 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); + /* Get out of the loop! */ + break; + } - /* Determine if the send was unsuccessful. */ - if (status) - { - - /* Release the packet. */ - nx_packet_release(packet_ptr); - } + /* Calculate the remaining length. */ + remaining_length = (ULONG)((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_append_ptr) - NX_PHYSICAL_TRAILER); - /* 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 advertised MSS is even less. */ + if (remaining_length > client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss) + { - /* Determine if the packet allocate was successfull. */ - if (status) - { + /* Reduce the remaining length to the MSS value. */ + remaining_length = client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_connect_mss; + } - /* Get out of the loop! */ - break; + /* Setup pointer to buffer. */ + buffer_ptr = packet_ptr -> nx_packet_append_ptr; } - /* 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) + /* 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'; - - - /* 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. */ - remaining_length = remaining_length - length; } - } - - /* Now determine if the directory listing was a success. */ - if ((status == FX_NO_MORE_ENTRIES) && (packet_ptr) && (packet_ptr -> nx_packet_length)) - { - - /* 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) + else if (packet_ptr) { - /* Release the packet. */ + /* Release packet just in case! */ 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) { - /* Reset the status for the response processing below. */ - status = FX_NO_MORE_ENTRIES; + /* 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); } - } - 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) - { + /* Clean up the data socket. */ + _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_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); - } + /* 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); - /* Clean up the data socket. */ - _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr); + /* Now determine if the directory listing was a success. */ + if (status == FX_NO_MORE_ENTRIES) + { - /* 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 directory listing was successful! */ - /* Now determine if the directory listing was a success. */ - if (status == FX_NO_MORE_ENTRIES) - { + /* 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 + { - /* The directory listing was successful! */ + /* Directory listing command failed. */ - /* 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"); + /* 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, "Bad Directory"); } + break; } - 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, "Bad Directory"); - } - break; - } #ifndef NX_DISABLE_IPV4 - case NX_FTP_PORT: - { - - - /* 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) + case NX_FTP_PORT: { - /* Illegal PORT 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_NOT_IMPLEMENTED, "PORT illegal in IPv6"); + /* 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. */ - /* Bail out! */ - break; - } - /* Setup pointer to packet buffer area. */ - buffer_ptr = packet_ptr -> nx_packet_prepend_ptr; - - /* 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_NOT_IMPLEMENTED, "PORT illegal in IPv6"); - /* Is a numeric character present? */ - if ((buffer_ptr[j] >= '0') && (buffer_ptr[j] <= '9')) + /* Bail out! */ + break; + } + /* Setup pointer to packet buffer area. */ + buffer_ptr = packet_ptr -> nx_packet_prepend_ptr; + + /* First, pickup the IP address. */ + commas = 0; + ip_address = 0; + j = 0; + temp = 0; + status = NX_SUCCESS; + while (j < packet_ptr -> nx_packet_length) { - /* Yes, numeric character is present. Update the IP address. */ - temp = (temp*10) + (ULONG) (buffer_ptr[j] - '0'); - } + /* Is a numeric character present? */ + if ((buffer_ptr[j] >= '0') && (buffer_ptr[j] <= '9')) + { - /* 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; + /* 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; + } + + /* Determine if a comma is present. */ + if (buffer_ptr[j] == ',') + { + + /* Increment the comma count. */ + commas++; + + /* Setup next byte of IP address. */ + ip_address = (ip_address << 8) & 0xFFFFFFFF; + ip_address = ip_address | (temp & 0xFF); + temp = 0; + + /* Have we finished with the IP address? */ + if (commas == 4) + { + + /* Finished with IP address. */ + j++; + 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. */ + + /* 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++] = '.'; + + /* Set the CR/LF. */ + buffer_ptr[j++] = 13; + buffer_ptr[j++] = 10; + + /* Set the packet length. */ + packet_ptr -> nx_packet_length = j; + + /* Setup the packet append pointer. */ + packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length; + + /* 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); + + /* Determine if the send was unsuccessful. */ + 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)); + + /* Release the packet. */ + nx_packet_release(packet_ptr); + } - /* Delete data socket. */ - 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; - /* And we are done processing. */ break; } +#endif /* NX_DISABLE_IPV4 */ - /* Wait for the data connection to connect. */ - nx_tcp_server_socket_accept(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_NO_WAIT); +#ifdef FEATURE_NX_IPV6 + case NX_FTP_EPRT: + { + - /* 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; + /* 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. */ - /* Reset the packet prepend pointer for alignment. */ - packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_data_start + NX_TCP_PACKET; + /* 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"); - /* Setup pointer to packet buffer area. */ - buffer_ptr = packet_ptr -> nx_packet_prepend_ptr; + /* Bail out! */ + break; + } - /* 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) - { + /* 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)); + /* First, pickup the IPv6 address. */ + status = _nx_ftp_utility_parse_IPv6_address((CHAR *)buffer_ptr, packet_ptr -> nx_packet_length, &ipduo_address); - /* Release the packet. */ - nx_packet_release(packet_ptr); - break; - } + 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"); - /* Build the string. "227 Entering Passive Mode " */ - memcpy(buffer_ptr, "227 Entering Passive Mode ", 26); /* Use case of memcpy is verified. */ - - /* 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++] = '.'; - - /* Set the CR/LF. */ - buffer_ptr[j++] = 13; - buffer_ptr[j++] = 10; - - /* Set the packet length. */ - packet_ptr -> nx_packet_length = j; - - /* Setup the packet append pointer. */ - packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length; - - /* 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); - - /* Determine if the send was unsuccessful. */ - if (status != NX_SUCCESS) - { + return; + } - /* 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 pickup the port number. */ + status = _nx_ftp_utility_parse_port_number((CHAR *)buffer_ptr, packet_ptr -> nx_packet_length, &port); - /* Release the packet. */ - nx_packet_release(packet_ptr); - } + /* Save the data port. */ + client_req_ptr -> nx_ftp_client_request_data_port = port; - /* Yes, passive transfer enabled. */ - client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled = NX_TRUE; + /* Determine if the EPRT command was successful. */ + if (status == NX_SUCCESS) + { - break; - } -#endif /* NX_DISABLE_IPV4 */ + /* Yes, the EPRT command is successful! */ -#ifdef FEATURE_NX_IPV6 - case NX_FTP_EPRT: - { - + /* 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 + { - /* 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. */ + /* 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_NOT_IMPLEMENTED, "EPRT illegal in IPv4"); + /* 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 + { + + /* 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; + } - /* Yes, stream mode is specified and supported. */ - client_req_ptr -> nx_ftp_client_request_transfer_mode = NX_FTP_TRANSFER_MODE_STREAM; + 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 */ @@ -17116,1049 +17104,33 @@ ULONG temp; NX_NULL, NX_NULL, pdu_privacy_ptr); /* Check status. */ - if (status) - { - - /* Release the packet. */ - nx_packet_release(packet_ptr); - return; - } - } - - /* Is the security set to authentication? */ - if (temp & NX_SNMP_SECURITY_AUTHORIZE) - { - - /* Compute our authentication parameter. */ - status = _nx_snmp_agent_add_auth_parameter(agent_ptr, packet_ptr, pdu_auth_parm_ptr); - - /* Check status. */ - if (status) - { - - /* Release the packet. */ - nx_packet_release(packet_ptr); - return; - } - } - } -#endif - - /* 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), 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(packet_ptr); - } - - /* Return to caller. */ - return; -} - -#ifndef NX_SNMP_DISABLE_V1 -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _nx_snmp_version_1_process PORTABLE C */ -/* 6.1 */ -/* AUTHOR */ -/* */ -/* Yuxin Zhou, Microsoft Corporation */ -/* */ -/* DESCRIPTION */ -/* */ -/* This function processes the SNMP v1 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_1_process(NX_SNMP_AGENT *agent_ptr, NX_PACKET *packet_ptr) -{ - -UINT sequence_length, version, request_type, request_length; -UINT error_code, error_index; -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; - - /* Pickup 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. */ - length = _nx_snmp_utility_error_info_get(buffer_ptr, &error_code, &error_index, 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 */ - - if (agent_ptr -> nx_snmp_agent_username_process) - { - - 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++; - -#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) - { - - /* 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); - - /* Release the packet. */ - nx_packet_release(packet_ptr); - - /* Release the response packet. */ - nx_packet_release(response_packet_ptr); - - /* Return to caller. */ - return; - } - } - - /* 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) - { - 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); - } - - /* 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); + if (status) + { - /* 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 packet. */ + nx_packet_release(packet_ptr); + return; + } + } - /* Release the original request packet. */ - nx_packet_release(packet_ptr); + /* Is the security set to authentication? */ + if (temp & NX_SNMP_SECURITY_AUTHORIZE) + { + + /* Compute our authentication parameter. */ + status = _nx_snmp_agent_add_auth_parameter(agent_ptr, packet_ptr, pdu_auth_parm_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++; + /* Check status. */ + if (status) + { + + /* Release the packet. */ + nx_packet_release(packet_ptr); + return; + } + } + } +#endif /* Increment the sent packet counter. */ agent_ptr -> nx_snmp_agent_packets_sent++; @@ -18167,7 +17139,7 @@ INT buffer_length; 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, + status = nxd_udp_socket_send(&(agent_ptr -> nx_snmp_agent_socket), packet_ptr, &(agent_ptr -> nx_snmp_agent_current_manager_ip), agent_ptr -> nx_snmp_agent_current_manager_port); @@ -18176,26 +17148,27 @@ INT buffer_length; { /* Release the packet. */ - nx_packet_release(response_packet_ptr); + nx_packet_release(packet_ptr); } -} -#endif /* NX_SNMP_DISABLE_V1 */ + /* Return to caller. */ + return; +} -#ifndef NX_SNMP_DISABLE_V2 +#if !defined(NX_SNMP_DISABLE_V1) && !defined(NX_SNMP_DISABLE_V2) /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ -/* _nx_snmp_version_2_process PORTABLE C */ -/* 6.1 */ +/* _nx_snmp_version_1_and_2_process PORTABLE C */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ -/* This function processes the SNMP v2 request from the manager. */ +/* This function processes the SNMP v1 request from the manager. */ /* */ /* INPUT */ /* */ @@ -18239,22 +17212,21 @@ INT buffer_length; /* */ /* 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_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) { UINT sequence_length, version, request_type, request_length; -UINT non_repeaters, max_repetitions, current_repetitions, next_object; +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; @@ -18267,6 +17239,7 @@ 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. */ @@ -18355,7 +17328,7 @@ INT buffer_length; /* Save the request type pointer. */ request_type_ptr = buffer_ptr; - /* Pick up the SNMP Request type. */ + /* Pickup the SNMP Request type. */ length = _nx_snmp_utility_request_type_get(buffer_ptr, &request_type, &request_length, buffer_length); /* Check for a valid packet. */ @@ -18440,7 +17413,6 @@ INT buffer_length; } #ifndef NX_DISABLE_PACKET_CHAIN - /* Determine if the received packet size is too big. */ if (packet_ptr -> nx_packet_next) { @@ -18453,14 +17425,12 @@ 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); + 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) @@ -18469,8 +17439,25 @@ INT buffer_length; /* 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); + /* Check the version. */ + if (version == NX_SNMP_VERSION_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); +#endif + } + else + { + + /* 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; @@ -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 "AzureRTOS@microsoft.com" + +/* 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 similarity index 99% rename from addons/azure_iot/samples/main.c rename to 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);