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);