1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** NetX Component */
16 /** */
17 /** Real Time Streaming Protocol (RTSP) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21 #define NX_RTSP_SERVER_SOURCE_CODE
22
23 /* Force error checking to be disabled in this module. */
24
25 #ifndef NX_DISABLE_ERROR_CHECKING
26 #define NX_DISABLE_ERROR_CHECKING
27 #endif
28
29 /* Include necessary system files. */
30
31 #include "tx_api.h"
32 #include "nx_api.h"
33 #include "nx_ip.h"
34 #ifdef FEATURE_NX_IPV6
35 #include "nx_ipv6.h"
36 #endif /* #ifdef FEATURE_NX_IPV6 */
37 #include "nx_rtsp_server.h"
38
39 /* Define the internal functions. */
40
41 static VOID _nx_rtsp_server_thread_entry(ULONG);
42
43 static VOID _nx_rtsp_server_connect_present(NX_TCP_SOCKET *request_socket_ptr, UINT port);
44 static VOID _nx_rtsp_server_connect_process(NX_RTSP_SERVER *rtsp_server_ptr);
45
46 static VOID _nx_rtsp_server_disconnect_present(NX_TCP_SOCKET *request_socket_ptr);
47 static VOID _nx_rtsp_server_disconnect_process(NX_RTSP_SERVER *rtsp_server_ptr);
48
49 static VOID _nx_rtsp_server_request_present(NX_TCP_SOCKET *request_socket_ptr);
50 static VOID _nx_rtsp_server_request_process(NX_RTSP_SERVER *rtsp_server_ptr);
51
52 static VOID _nx_rtsp_server_timeout(ULONG rtsp_server_address);
53 static VOID _nx_rtsp_server_timeout_process(NX_RTSP_SERVER *rtsp_server_ptr);
54
55 static UINT _nx_rtsp_server_request_receive(NX_RTSP_SERVER *rtsp_server_ptr, NX_RTSP_CLIENT *rtsp_client_ptr);
56 static UINT _nx_rtsp_server_request_parse(NX_RTSP_CLIENT *rtsp_client_ptr, NX_RTSP_CLIENT_REQUEST *rtsp_client_request_ptr);
57 static UINT _nx_rtsp_server_request_line_parse(NX_RTSP_CLIENT_REQUEST *rtsp_client_request_ptr, UCHAR **request_buffer, UCHAR *request_buffer_end);
58 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);
59 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);
60 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);
61
62 static VOID _nx_rtsp_server_disconnect(NX_RTSP_SERVER *rtsp_server_ptr, NX_RTSP_CLIENT *rtsp_client_ptr);
63
64 static UINT _nx_rtsp_server_memicmp(UCHAR *src, ULONG src_length, UCHAR *dest, ULONG dest_length);
65 static UCHAR *_nx_rtsp_server_strstr(UCHAR *src, ULONG src_length, UCHAR *dest, ULONG dest_length);
66
67 /* Define macros. */
68
69 #define NX_RTSP_SERVER_STRING_SIZE(str) sizeof(str) - 1
70 #define NX_RTSP_SERVER_STRING_WITH_SIZE(str) (UCHAR *)str, NX_RTSP_SERVER_STRING_SIZE(str)
71
72 /* Bring in externs for caller checking code. */
73
74 NX_CALLER_CHECKING_EXTERNS
75
76 /* Define description table for the RTSP response status code. */
77
78 const NX_RTSP_RESPONSE nx_rtsp_server_response_description_table[] =
79 {
80 { NX_RTSP_STATUS_CODE_OK , "OK" },
81 { NX_RTSP_STATUS_CODE_CREATED , "CREATED" },
82 { NX_RTSP_STATUS_CODE_LOW_ON_STORAGE_SPACE , "LOW ON STORAGE SPACE" },
83 { NX_RTSP_STATUS_CODE_MULTIPLE_CHOICES , "MULTIPLE CHOICES" },
84 { NX_RTSP_STATUS_CODE_MOVED_PERMANENTLY , "MOVED PERMANENTLY" },
85 { NX_RTSP_STATUS_CODE_MOVED_TEMPORARILY , "MOVED TEMPORARILY" },
86 { NX_RTSP_STATUS_CODE_SEE_OTHER , "SEE OTHER" },
87 { NX_RTSP_STATUS_CODE_NOT_MODIFIED , "NOT MODIFIED" },
88 { NX_RTSP_STATUS_CODE_USE_PROXY , "USE PROXY" },
89 { NX_RTSP_STATUS_CODE_GOING_AWAY , "GOING AWAY" },
90 { NX_RTSP_STATUS_CODE_LOAD_BALANCING , "LOAD BALANCING" },
91 { NX_RTSP_STATUS_CODE_BAD_REQUEST , "BAD REQUEST" },
92 { NX_RTSP_STATUS_CODE_UNAUTHORIZED , "UNAUTHORIZED" },
93 { NX_RTSP_STATUS_CODE_PAYMENT_REQUIRED , "PAYMENT REQUIRED" },
94 { NX_RTSP_STATUS_CODE_FORBIDDEN , "FORBIDDEN" },
95 { NX_RTSP_STATUS_CODE_NOT_FOUND , "NOT FOUND" },
96 { NX_RTSP_STATUS_CODE_METHOD_NOT_ALLOWED , "METHOD NOT ALLOWED" },
97 { NX_RTSP_STATUS_CODE_NOT_ACCEPTABLE , "NOT ACCEPTABLE" },
98 { NX_RTSP_STATUS_CODE_PROXY_AUTHENTICATION_REQUIRED , "PROXY AUTHENTICATION REQUIRED" },
99 { NX_RTSP_STATUS_CODE_REQUEST_TIMEOUT , "REQUEST TIMEOUT" },
100 { NX_RTSP_STATUS_CODE_GONE , "GONE" },
101 { NX_RTSP_STATUS_CODE_LENGTH_REQUIRED , "LENGTH REQUIRED" },
102 { NX_RTSP_STATUS_CODE_PRECONDITION_FAILED , "PRECONDITION FAILED" },
103 { NX_RTSP_STATUS_CODE_REQUEST_ENTITY_TOO_LARGE , "REQUEST ENTITY TOO LARGE" },
104 { NX_RTSP_STATUS_CODE_REQUESTURI_TOO_LARGE , "REQUESTURI TOO LARGE" },
105 { NX_RTSP_STATUS_CODE_UNSUPPORTED_MEDIA_TYPE , "UNSUPPORTED MEDIA TYPE" },
106 { NX_RTSP_STATUS_CODE_PARAMETER_NOT_UNDERSTOOD , "PARAMETER NOT UNDERSTOOD" },
107 { NX_RTSP_STATUS_CODE_RESERVED , "RESERVED" },
108 { NX_RTSP_STATUS_CODE_NOT_ENOUGH_BANDWIDTH , "NOT ENOUGH BANDWIDTH" },
109 { NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND , "SESSION NOT FOUND" },
110 { NX_RTSP_STATUS_CODE_METHOD_NOT_VALID_IN_THIS_STATE , "METHOD NOT VALID IN THIS STATE" },
111 { NX_RTSP_STATUS_CODE_HEADER_FIELD_NOT_VALID_FOR_RESOURCE , "HEADER FIELD NOT VALID FOR RESOURCE" },
112 { NX_RTSP_STATUS_CODE_INVALID_RANGE , "INVALID RANGE" },
113 { NX_RTSP_STATUS_CODE_PARAMETER_IS_READONLY , "PARAMETER IS READONLY" },
114 { NX_RTSP_STATUS_CODE_AGGREGATE_OPERATION_NOT_ALLOWED , "AGGREGATE OPERATION NOT ALLOWED" },
115 { NX_RTSP_STATUS_CODE_ONLY_AGGREGATE_OPERATION_ALLOWED , "ONLY AGGREGATE OPERATION ALLOWED" },
116 { NX_RTSP_STATUS_CODE_UNSUPPORTED_TRANSPORT , "UNSUPPORTED TRANSPORT" },
117 { NX_RTSP_STATUS_CODE_DESTINATION_UNREACHABLE , "DESTINATION UNREACHABLE" },
118 { NX_RTSP_STATUS_CODE_INTERNAL_SERVER_ERROR , "INTERNAL SERVER ERROR" },
119 { NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED , "NOT IMPLEMENTED" },
120 { NX_RTSP_STATUS_CODE_BAD_GATEWAY , "BAD GATEWAY" },
121 { NX_RTSP_STATUS_CODE_SERVICE_UNAVAILABLE , "SERVICE UNAVAILABLE" },
122 { NX_RTSP_STATUS_CODE_GATEWAY_TIMEOUT , "GATEWAY TIMEOUT" },
123 { NX_RTSP_STATUS_CODE_RTSP_VERSION_NOT_SUPPORTED , "RTSP VERSION NOT SUPPORTED" },
124 { NX_RTSP_STATUS_CODE_OPTION_NOT_SUPPORTED , "OPTION NOT SUPPORTED" },
125 { NX_NULL , "" }
126 };
127
128 /**************************************************************************/
129 /* */
130 /* FUNCTION RELEASE */
131 /* */
132 /* _nxe_rtsp_server_create PORTABLE C */
133 /* 6.3.0 */
134 /* AUTHOR */
135 /* */
136 /* Wenhui Xie, Microsoft Corporation */
137 /* */
138 /* DESCRIPTION */
139 /* */
140 /* This function checks for errors in RTSP server create function call.*/
141 /* */
142 /* INPUT */
143 /* */
144 /* rtsp_server_ptr Pointer to RTSP server */
145 /* server_name Name of RTSP server */
146 /* server_name_length Length of RTSP server name */
147 /* ip_ptr Pointer to IP instance */
148 /* rtsp_packet_pool Pointer to packet pool */
149 /* stack_ptr Server thread's stack pointer */
150 /* stack_size Server thread's stack size */
151 /* priority The priority of the thread */
152 /* server_port Listening port */
153 /* disconnect_callback Disconnect callback function */
154 /* */
155 /* OUTPUT */
156 /* */
157 /* status Completion status */
158 /* */
159 /* CALLS */
160 /* */
161 /* _nx_rtsp_server_create Create RTSP server */
162 /* */
163 /* CALLED BY */
164 /* */
165 /* Application Code */
166 /* */
167 /* RELEASE HISTORY */
168 /* */
169 /* DATE NAME DESCRIPTION */
170 /* */
171 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
172 /* */
173 /**************************************************************************/
_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))174 UINT _nxe_rtsp_server_create(NX_RTSP_SERVER *rtsp_server_ptr, CHAR *server_name, UINT server_name_length,
175 NX_IP *ip_ptr, NX_PACKET_POOL *rtsp_packet_pool,
176 VOID *stack_ptr, ULONG stack_size, UINT priority, UINT server_port,
177 UINT (*disconnect_callback)(NX_RTSP_CLIENT *rtsp_client_ptr))
178 {
179 UINT status;
180
181
182 /* Check for invalid input pointers. */
183 if ((ip_ptr == NX_NULL) || (ip_ptr -> nx_ip_id != NX_IP_ID) ||
184 (rtsp_server_ptr == NX_NULL) || (stack_ptr == NX_NULL) ||
185 (rtsp_packet_pool == NX_NULL) || rtsp_server_ptr -> nx_rtsp_server_id == NX_RTSP_SERVER_ID)
186 {
187 return(NX_PTR_ERROR);
188 }
189
190 /* Call actual RTSP server create function. */
191 status = _nx_rtsp_server_create(rtsp_server_ptr,server_name, server_name_length, ip_ptr, rtsp_packet_pool,
192 stack_ptr, stack_size, priority, server_port, disconnect_callback);
193
194 /* Return status. */
195 return(status);
196 }
197
198 /**************************************************************************/
199 /* */
200 /* FUNCTION RELEASE */
201 /* */
202 /* _nx_rtsp_server_create PORTABLE C */
203 /* 6.3.0 */
204 /* AUTHOR */
205 /* */
206 /* Wenhui Xie, Microsoft Corporation */
207 /* */
208 /* DESCRIPTION */
209 /* */
210 /* This function creates a RTSP server on the specified IP and port. */
211 /* */
212 /* INPUT */
213 /* */
214 /* rtsp_server_ptr Pointer to RTSP server */
215 /* server_name Name of RTSP server */
216 /* server_name_length Length of RTSP server name */
217 /* ip_ptr Pointer to IP instance */
218 /* rtsp_packet_pool Pointer to packet pool */
219 /* stack_ptr Server thread's stack pointer */
220 /* stack_size Server thread's stack size */
221 /* priority The priority of the thread */
222 /* server_port Listening port */
223 /* disconnect_callback Disconnect callback function */
224 /* */
225 /* OUTPUT */
226 /* */
227 /* status Completion status */
228 /* */
229 /* CALLS */
230 /* */
231 /* memset Reset memory */
232 /* tx_event_flags_create Create thread event flags */
233 /* tx_thread_create Create the server thread */
234 /* tx_timer_create Create the timeout timer */
235 /* tx_event_flags_delete Delete thread event flags */
236 /* tx_thread_delete Delete the server thread */
237 /* */
238 /* CALLED BY */
239 /* */
240 /* Application Code */
241 /* */
242 /* RELEASE HISTORY */
243 /* */
244 /* DATE NAME DESCRIPTION */
245 /* */
246 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
247 /* */
248 /**************************************************************************/
_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))249 UINT _nx_rtsp_server_create(NX_RTSP_SERVER *rtsp_server_ptr, CHAR *server_name, UINT server_name_length,
250 NX_IP *ip_ptr, NX_PACKET_POOL *rtsp_packet_pool,
251 VOID *stack_ptr, ULONG stack_size, UINT priority, UINT server_port,
252 UINT (*disconnect_callback)(NX_RTSP_CLIENT *rtsp_client_ptr))
253 {
254 UINT status;
255
256
257 /* Clear RTSP server object. */
258 memset((VOID *)rtsp_server_ptr, 0, sizeof(NX_RTSP_SERVER));
259
260 /* Set the RTSP server name. */
261 rtsp_server_ptr -> nx_rtsp_server_name = server_name;
262 rtsp_server_ptr -> nx_rtsp_server_name_length = server_name_length;
263
264 /* Record our packet pool. */
265 rtsp_server_ptr -> nx_rtsp_server_packet_pool = rtsp_packet_pool;
266
267 /* Create the ThreadX event flags. These will be used to drive the RTSP server thread. */
268 status = tx_event_flags_create(&(rtsp_server_ptr -> nx_rtsp_server_event_flags), "RTSP Server Thread Events");
269
270 if (status)
271 {
272 return(status);
273 }
274
275 /* Create the RTSP server thread and start the RTSP server. */
276 status = tx_thread_create(&(rtsp_server_ptr -> nx_rtsp_server_thread), server_name,
277 _nx_rtsp_server_thread_entry, (ULONG)rtsp_server_ptr,
278 stack_ptr, stack_size, priority, priority,
279 NX_RTSP_SERVER_TIME_SLICE, TX_NO_ACTIVATE);
280
281 if (status)
282 {
283
284 /* Delete the event flag. */
285 tx_event_flags_delete(&(rtsp_server_ptr -> nx_rtsp_server_event_flags));
286 return(status);
287 }
288
289 /* Create the timeout timer. */
290 status = tx_timer_create(&(rtsp_server_ptr -> nx_rtsp_server_timer), "RTSP Server Timer",
291 _nx_rtsp_server_timeout, (ULONG)rtsp_server_ptr,
292 NX_IP_PERIODIC_RATE, NX_IP_PERIODIC_RATE, TX_NO_ACTIVATE);
293
294 if (status)
295 {
296
297 /* Delete the thread. */
298 tx_thread_delete(&(rtsp_server_ptr -> nx_rtsp_server_thread));
299
300 /* Delete the event flag. */
301 tx_event_flags_delete(&(rtsp_server_ptr -> nx_rtsp_server_event_flags));
302
303 return(status);
304 }
305
306 /* Set the IP pointer. */
307 rtsp_server_ptr -> nx_rtsp_server_ip_ptr = ip_ptr;
308
309 /* Set the TCP port of RTSP server. */
310 rtsp_server_ptr -> nx_rtsp_server_port = (USHORT)server_port;
311
312 /* Set disconnect callback function. */
313 rtsp_server_ptr -> nx_rtsp_server_disconnect_callback = disconnect_callback;
314
315 /* Set the RTSP server ID. */
316 rtsp_server_ptr -> nx_rtsp_server_id = NX_RTSP_SERVER_ID;
317
318 return(NX_SUCCESS);
319 }
320
321 /**************************************************************************/
322 /* */
323 /* FUNCTION RELEASE */
324 /* */
325 /* _nxe_rtsp_server_delete PORTABLE C */
326 /* 6.3.0 */
327 /* AUTHOR */
328 /* */
329 /* Wenhui Xie, Microsoft Corporation */
330 /* */
331 /* DESCRIPTION */
332 /* */
333 /* This function checks for errors in RTSP server delete function call.*/
334 /* */
335 /* INPUT */
336 /* */
337 /* rtsp_server_ptr Pointer to RTSP server */
338 /* */
339 /* OUTPUT */
340 /* */
341 /* status Completion status */
342 /* */
343 /* CALLS */
344 /* */
345 /* _nx_rtsp_server_delete Delete the RTSP server */
346 /* */
347 /* CALLED BY */
348 /* */
349 /* Application Code */
350 /* */
351 /* RELEASE HISTORY */
352 /* */
353 /* DATE NAME DESCRIPTION */
354 /* */
355 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
356 /* */
357 /**************************************************************************/
_nxe_rtsp_server_delete(NX_RTSP_SERVER * rtsp_server_ptr)358 UINT _nxe_rtsp_server_delete(NX_RTSP_SERVER *rtsp_server_ptr)
359 {
360 UINT status;
361
362
363 /* Check for invalid input pointers. */
364 if ((rtsp_server_ptr == NX_NULL) || (rtsp_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
365 {
366 return(NX_PTR_ERROR);
367 }
368
369 /* Call actual RTSP server delete function. */
370 status = _nx_rtsp_server_delete(rtsp_server_ptr);
371
372 /* Return status. */
373 return(status);
374 }
375
376 /**************************************************************************/
377 /* */
378 /* FUNCTION RELEASE */
379 /* */
380 /* _nx_rtsp_server_delete PORTABLE C */
381 /* 6.3.0 */
382 /* AUTHOR */
383 /* */
384 /* Wenhui Xie, Microsoft Corporation */
385 /* */
386 /* DESCRIPTION */
387 /* */
388 /* This function deletes a previously created RTSP server on specified */
389 /* IP and port. */
390 /* */
391 /* INPUT */
392 /* */
393 /* rtsp_server_ptr Pointer to RTSP server */
394 /* */
395 /* OUTPUT */
396 /* */
397 /* status Completion status */
398 /* */
399 /* CALLS */
400 /* */
401 /* _nx_rtsp_server_stop Stop the RTSP server */
402 /* tx_thread_terminate Terminate server thread */
403 /* tx_event_flags_delete Delete thread event flags */
404 /* tx_thread_delete Delete the server thread */
405 /* tx_timer_delete Delete the timeout timer */
406 /* */
407 /* CALLED BY */
408 /* */
409 /* Application Code */
410 /* */
411 /* RELEASE HISTORY */
412 /* */
413 /* DATE NAME DESCRIPTION */
414 /* */
415 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
416 /* */
417 /**************************************************************************/
_nx_rtsp_server_delete(NX_RTSP_SERVER * rtsp_server_ptr)418 UINT _nx_rtsp_server_delete(NX_RTSP_SERVER *rtsp_server_ptr)
419 {
420
421
422 /* Stop the RTSP server if not done yet. */
423 if (rtsp_server_ptr -> nx_rtsp_server_started)
424 {
425 _nx_rtsp_server_stop(rtsp_server_ptr);
426 }
427
428 /* Terminate server thread. */
429 tx_thread_terminate(&(rtsp_server_ptr -> nx_rtsp_server_thread));
430
431 /* Delete server thread. */
432 tx_thread_delete(&(rtsp_server_ptr -> nx_rtsp_server_thread));
433
434 /* Delete the server event flags. */
435 tx_event_flags_delete(&(rtsp_server_ptr -> nx_rtsp_server_event_flags));
436
437 /* Delete the timer. */
438 tx_timer_delete(&(rtsp_server_ptr -> nx_rtsp_server_timer));
439
440 /* Clear the RTSP server ID. */
441 rtsp_server_ptr -> nx_rtsp_server_id = 0;
442
443 return(NX_SUCCESS);
444 }
445
446 /**************************************************************************/
447 /* */
448 /* FUNCTION RELEASE */
449 /* */
450 /* _nxe_rtsp_server_start PORTABLE C */
451 /* 6.3.0 */
452 /* AUTHOR */
453 /* */
454 /* Wenhui Xie, Microsoft Corporation */
455 /* */
456 /* DESCRIPTION */
457 /* */
458 /* This function checks for errors in RTSP server start function call. */
459 /* */
460 /* INPUT */
461 /* */
462 /* rtsp_server_ptr Pointer to RTSP server */
463 /* */
464 /* OUTPUT */
465 /* */
466 /* status Completion status */
467 /* */
468 /* CALLS */
469 /* */
470 /* _nx_rtsp_server_start Start the RTSP server */
471 /* */
472 /* CALLED BY */
473 /* */
474 /* Application Code */
475 /* */
476 /* RELEASE HISTORY */
477 /* */
478 /* DATE NAME DESCRIPTION */
479 /* */
480 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
481 /* */
482 /**************************************************************************/
_nxe_rtsp_server_start(NX_RTSP_SERVER * rtsp_server_ptr)483 UINT _nxe_rtsp_server_start(NX_RTSP_SERVER *rtsp_server_ptr)
484 {
485 UINT status;
486
487
488 /* Check for invalid input pointers. */
489 if ((rtsp_server_ptr == NX_NULL) || (rtsp_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
490 {
491 return(NX_PTR_ERROR);
492 }
493
494 /* Call actual RTSP server start function. */
495 status = _nx_rtsp_server_start(rtsp_server_ptr);
496
497 /* Return status. */
498 return(status);
499 }
500
501 /**************************************************************************/
502 /* */
503 /* FUNCTION RELEASE */
504 /* */
505 /* _nx_rtsp_server_start PORTABLE C */
506 /* 6.3.0 */
507 /* AUTHOR */
508 /* */
509 /* Wenhui Xie, Microsoft Corporation */
510 /* */
511 /* DESCRIPTION */
512 /* */
513 /* This function starts a previously created RTSP server. */
514 /* */
515 /* INPUT */
516 /* */
517 /* rtsp_server_ptr Pointer to RTSP server */
518 /* */
519 /* OUTPUT */
520 /* */
521 /* status Completion status */
522 /* */
523 /* CALLS */
524 /* */
525 /* nx_tcp_socket_create Create TCP socket */
526 /* nx_tcp_socket_receive_notify Set TCP notification callback */
527 /* nx_tcp_socket_delete Delete TCP socket */
528 /* nx_tcp_server_socket_listen Listen on free TCP socket */
529 /* tx_thread_resume Resume the RTSP server thread */
530 /* tx_timer_activate Activate the timeout timer */
531 /* */
532 /* CALLED BY */
533 /* */
534 /* Application Code */
535 /* */
536 /* RELEASE HISTORY */
537 /* */
538 /* DATE NAME DESCRIPTION */
539 /* */
540 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
541 /* */
542 /**************************************************************************/
_nx_rtsp_server_start(NX_RTSP_SERVER * rtsp_server_ptr)543 UINT _nx_rtsp_server_start(NX_RTSP_SERVER *rtsp_server_ptr)
544 {
545 UINT status;
546 int i, j;
547
548
549 /* Check if the RTSP server is started. */
550 if (rtsp_server_ptr -> nx_rtsp_server_started)
551 {
552 return(NX_RTSP_SERVER_ALREADY_STARTED);
553 }
554
555 /* Check if the required method callbacks are set. */
556 if ((rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_setup_callback == NX_NULL) ||
557 (rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_play_callback == NX_NULL) ||
558 (rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_teardown_callback == NX_NULL))
559 {
560 return(NX_RTSP_SERVER_MISSING_REQUIRED_CALLBACKS);
561 }
562
563 /* Loop to create all the RTSP client control sockets. */
564 for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
565 {
566
567 /* Create an RTSP client control socket. */
568 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),
569 "RTSP Client Control Socket", NX_RTSP_SERVER_TYPE_OF_SERVICE, NX_RTSP_SERVER_FRAGMENT_OPTION,
570 NX_RTSP_SERVER_TIME_TO_LIVE, NX_RTSP_SERVER_WINDOW_SIZE, NX_NULL,
571 _nx_rtsp_server_disconnect_present);
572
573 /* If no error is present, register the receive notify function. */
574 if (status == NX_SUCCESS)
575 {
576
577 /* Register the receive function. */
578 nx_tcp_socket_receive_notify(&(rtsp_server_ptr -> nx_rtsp_server_client_list[i].nx_rtsp_client_socket),
579 _nx_rtsp_server_request_present);
580 }
581 else
582 {
583 break;
584 }
585
586 /* Make sure each socket points to the RTSP server. */
587 rtsp_server_ptr -> nx_rtsp_server_client_list[i].nx_rtsp_client_socket.nx_tcp_socket_reserved_ptr = rtsp_server_ptr;
588 }
589
590 /* Determine if an error has occurred. */
591 if (status)
592 {
593
594 /* Loop to delete any created sockets. */
595 for (j = 0; j < i; j++)
596 {
597
598 /* Delete the RTSP socket. */
599 nx_tcp_socket_delete(&(rtsp_server_ptr -> nx_rtsp_server_client_list[j].nx_rtsp_client_socket));
600 }
601
602 /* Return an error. */
603 return(status);
604 }
605
606
607 /* Start listening on the RTSP socket. */
608 status = nx_tcp_server_socket_listen(rtsp_server_ptr -> nx_rtsp_server_ip_ptr, rtsp_server_ptr -> nx_rtsp_server_port,
609 &(rtsp_server_ptr -> nx_rtsp_server_client_list[0].nx_rtsp_client_socket),
610 NX_RTSP_SERVER_MAX_CLIENTS, _nx_rtsp_server_connect_present);
611
612 if (status)
613 {
614 return(status);
615 }
616
617 /* Start thread. */
618 tx_thread_resume(&rtsp_server_ptr -> nx_rtsp_server_thread);
619
620 /* Activate timer. */
621 tx_timer_activate(&rtsp_server_ptr -> nx_rtsp_server_timer);
622
623 rtsp_server_ptr -> nx_rtsp_server_started = NX_TRUE;
624
625 return(NX_SUCCESS);
626 }
627
628 /**************************************************************************/
629 /* */
630 /* FUNCTION RELEASE */
631 /* */
632 /* _nxe_rtsp_server_stop PORTABLE C */
633 /* 6.3.0 */
634 /* AUTHOR */
635 /* */
636 /* Wenhui Xie, Microsoft Corporation */
637 /* */
638 /* DESCRIPTION */
639 /* */
640 /* This function checks for errors in RTSP server stop function call. */
641 /* */
642 /* INPUT */
643 /* */
644 /* rtsp_server_ptr Pointer to RTSP server */
645 /* */
646 /* OUTPUT */
647 /* */
648 /* status Completion status */
649 /* */
650 /* CALLS */
651 /* */
652 /* _nx_rtsp_server_stop Stop the RTSP server */
653 /* */
654 /* CALLED BY */
655 /* */
656 /* Application Code */
657 /* */
658 /* RELEASE HISTORY */
659 /* */
660 /* DATE NAME DESCRIPTION */
661 /* */
662 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
663 /* */
664 /**************************************************************************/
_nxe_rtsp_server_stop(NX_RTSP_SERVER * rtsp_server_ptr)665 UINT _nxe_rtsp_server_stop(NX_RTSP_SERVER *rtsp_server_ptr)
666 {
667 UINT status;
668
669
670 /* Check for invalid input pointers. */
671 if ((rtsp_server_ptr == NX_NULL) || (rtsp_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
672 {
673 return(NX_PTR_ERROR);
674 }
675
676 /* Call actual RTSP server stop function. */
677 status = _nx_rtsp_server_stop(rtsp_server_ptr);
678
679 /* Return status. */
680 return(status);
681 }
682
683 /**************************************************************************/
684 /* */
685 /* FUNCTION RELEASE */
686 /* */
687 /* _nx_rtsp_server_stop PORTABLE C */
688 /* 6.3.0 */
689 /* AUTHOR */
690 /* */
691 /* Wenhui Xie, Microsoft Corporation */
692 /* */
693 /* DESCRIPTION */
694 /* */
695 /* This function stops a previously started RTSP server. */
696 /* */
697 /* INPUT */
698 /* */
699 /* rtsp_server_ptr Pointer to RTSP server */
700 /* */
701 /* OUTPUT */
702 /* */
703 /* status Completion status */
704 /* */
705 /* CALLS */
706 /* */
707 /* tx_thread_suspend Suspend server thread */
708 /* tx_timer_deactivate Stop server timeout timer */
709 /* nx_tcp_socket_disconnect Disconnect TCP socket */
710 /* nx_tcp_server_socket_unaccept Clear accepted socket */
711 /* nx_tcp_socket_delete Delete TCP socket */
712 /* nx_tcp_server_socket_unlisten Stop listening on TCP socket */
713 /* */
714 /* CALLED BY */
715 /* */
716 /* Application Code */
717 /* */
718 /* RELEASE HISTORY */
719 /* */
720 /* DATE NAME DESCRIPTION */
721 /* */
722 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
723 /* */
724 /**************************************************************************/
_nx_rtsp_server_stop(NX_RTSP_SERVER * rtsp_server_ptr)725 UINT _nx_rtsp_server_stop(NX_RTSP_SERVER *rtsp_server_ptr)
726 {
727 UINT client_index;
728
729
730 /* Check if the server is started. */
731 if (rtsp_server_ptr -> nx_rtsp_server_started != NX_TRUE)
732 {
733 return(NX_RTSP_SERVER_NOT_STARTED);
734 }
735
736 /* Suspend thread. */
737 tx_thread_suspend(&(rtsp_server_ptr -> nx_rtsp_server_thread));
738
739 /* Deactivate the timer. */
740 tx_timer_deactivate(&(rtsp_server_ptr -> nx_rtsp_server_timer));
741
742 /* Walk through to close the sockets. */
743 for (client_index = 0; client_index < NX_RTSP_SERVER_MAX_CLIENTS; client_index++)
744 {
745
746 /* Disconnect the socket. */
747 nx_tcp_socket_disconnect(&(rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_socket), NX_NO_WAIT);
748
749 /* Unaccept the socket. */
750 nx_tcp_server_socket_unaccept(&(rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_socket));
751
752 /* Delete the socket. */
753 nx_tcp_socket_delete(&(rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_socket));
754
755 /* Check to see if a packet is queued up. */
756 if (rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_request_packet)
757 {
758
759 /* Yes, release it! */
760 nx_packet_release(rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_request_packet);
761 rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_request_packet = NX_NULL;
762 rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_request_bytes_total = 0;
763 }
764
765 /* Check to see if a packet is queued up. */
766 if (rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_response_packet)
767 {
768
769 /* Yes, release it! */
770 nx_packet_release(rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_response_packet);
771 rtsp_server_ptr -> nx_rtsp_server_client_list[client_index].nx_rtsp_client_response_packet = NX_NULL;
772 }
773 }
774
775 /* Unlisten for the RTSP server port. */
776 nx_tcp_server_socket_unlisten(rtsp_server_ptr -> nx_rtsp_server_ip_ptr, rtsp_server_ptr -> nx_rtsp_server_port);
777
778 /* Clear the RTSP server started flag. */
779 rtsp_server_ptr -> nx_rtsp_server_started = NX_FALSE;
780
781 return(NX_SUCCESS);
782 }
783
784 /**************************************************************************/
785 /* */
786 /* FUNCTION RELEASE */
787 /* */
788 /* _nxe_rtsp_server_sdp_set PORTABLE C */
789 /* 6.3.0 */
790 /* AUTHOR */
791 /* */
792 /* Wenhui Xie, Microsoft Corporation */
793 /* */
794 /* DESCRIPTION */
795 /* */
796 /* This function checks for errors in SDP set function call. */
797 /* */
798 /* INPUT */
799 /* */
800 /* rtsp_client_ptr Pointer to RTSP client */
801 /* sdp_string Pointer to SDP string */
802 /* sdp_length The length of the SDP string */
803 /* */
804 /* OUTPUT */
805 /* */
806 /* status Completion status */
807 /* */
808 /* CALLS */
809 /* */
810 /* _nx_rtsp_server_sdp_set Set SDP string in response */
811 /* */
812 /* CALLED BY */
813 /* */
814 /* Application Code */
815 /* */
816 /* RELEASE HISTORY */
817 /* */
818 /* DATE NAME DESCRIPTION */
819 /* */
820 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
821 /* */
822 /**************************************************************************/
_nxe_rtsp_server_sdp_set(NX_RTSP_CLIENT * rtsp_client_ptr,UCHAR * sdp_string,UINT sdp_length)823 UINT _nxe_rtsp_server_sdp_set(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *sdp_string, UINT sdp_length)
824 {
825 UINT status;
826
827
828 /* Check for invalid input pointers. */
829 if ((rtsp_client_ptr == NX_NULL) || (sdp_string == NX_NULL) || (sdp_length == 0) ||
830 (rtsp_client_ptr -> nx_rtsp_client_server_ptr == NX_NULL) ||
831 (rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
832 {
833 return(NX_PTR_ERROR);
834 }
835
836 /* Call actual SDP set function. */
837 status = _nx_rtsp_server_sdp_set(rtsp_client_ptr, sdp_string, sdp_length);
838
839 /* Return status. */
840 return(status);
841 }
842
843 /**************************************************************************/
844 /* */
845 /* FUNCTION RELEASE */
846 /* */
847 /* _nx_rtsp_server_sdp_set PORTABLE C */
848 /* 6.3.0 */
849 /* AUTHOR */
850 /* */
851 /* Wenhui Xie, Microsoft Corporation */
852 /* */
853 /* DESCRIPTION */
854 /* */
855 /* This function sets the SDP string to the response packet. This */
856 /* function can only be called in DESCRIBE callback function. */
857 /* */
858 /* INPUT */
859 /* */
860 /* rtsp_client_ptr Pointer to RTSP client */
861 /* sdp_string Pointer to SDP string */
862 /* sdp_length The length of the SDP string */
863 /* */
864 /* OUTPUT */
865 /* */
866 /* status Completion status */
867 /* */
868 /* CALLS */
869 /* */
870 /* nx_packet_data_append Append packet data */
871 /* _nx_utility_uint_to_string Convert integer to string */
872 /* */
873 /* CALLED BY */
874 /* */
875 /* Application Code */
876 /* */
877 /* RELEASE HISTORY */
878 /* */
879 /* DATE NAME DESCRIPTION */
880 /* */
881 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
882 /* */
883 /**************************************************************************/
_nx_rtsp_server_sdp_set(NX_RTSP_CLIENT * rtsp_client_ptr,UCHAR * sdp_string,UINT sdp_length)884 UINT _nx_rtsp_server_sdp_set(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *sdp_string, UINT sdp_length)
885 {
886 UINT status;
887 CHAR temp_buffer[11];
888 UINT temp_length;
889 NX_PACKET *response_packet_ptr = rtsp_client_ptr -> nx_rtsp_client_response_packet;
890
891
892 /* Check if the packet is valid. */
893 if (!response_packet_ptr)
894 {
895 return(NX_RTSP_SERVER_NO_PACKET);
896 }
897
898 /* Check the request method. */
899 if ((!rtsp_client_ptr -> nx_rtsp_client_request_ptr) ||
900 (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_method != NX_RTSP_METHOD_DESCRIBE))
901 {
902 return(NX_RTSP_SERVER_INVALID_REQUEST);
903 }
904
905 /* Add "Content-Type" header. */
906 status = nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("Content-Type: "),
907 rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
908 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(NX_RTSP_SERVER_CONTENT_TYPE_SDP),
909 rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
910 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n"),
911 rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
912
913 /* Add "Content-Length" header. */
914 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("Content-Length: "),
915 rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
916 temp_length = _nx_utility_uint_to_string(sdp_length, 10, temp_buffer, sizeof(temp_buffer));
917 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length,
918 rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
919 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n\r\n"),
920 rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
921
922 /* Add sdp string. */
923 status += nx_packet_data_append(response_packet_ptr, sdp_string, sdp_length,
924 rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
925
926 return(status);
927 }
928
929 /**************************************************************************/
930 /* */
931 /* FUNCTION RELEASE */
932 /* */
933 /* _nxe_rtsp_server_rtp_info_set PORTABLE C */
934 /* 6.3.0 */
935 /* AUTHOR */
936 /* */
937 /* Wenhui Xie, Microsoft Corporation */
938 /* */
939 /* DESCRIPTION */
940 /* */
941 /* This function checks for errors in RTP-Info set function call. */
942 /* */
943 /* INPUT */
944 /* */
945 /* rtsp_client_ptr Pointer to RTSP client */
946 /* track_id The track ID of the media */
947 /* track_id_len The length of the track ID */
948 /* rtp_seq The RTP sequence number */
949 /* rtp_time The RTP timestamp */
950 /* */
951 /* OUTPUT */
952 /* */
953 /* status Completion status */
954 /* */
955 /* CALLS */
956 /* */
957 /* _nx_rtsp_server_rtp_info_set Set RTP-Info in response */
958 /* */
959 /* CALLED BY */
960 /* */
961 /* Application Code */
962 /* */
963 /* RELEASE HISTORY */
964 /* */
965 /* DATE NAME DESCRIPTION */
966 /* */
967 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
968 /* */
969 /**************************************************************************/
_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)970 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)
971 {
972 UINT status;
973
974
975 /* Check for invalid input pointers. */
976 if ((rtsp_client_ptr == NX_NULL) || (track_id == NX_NULL) || (track_id_len == 0) ||
977 (rtsp_client_ptr -> nx_rtsp_client_server_ptr == NX_NULL) ||
978 (rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
979 {
980 return(NX_PTR_ERROR);
981 }
982
983 /* Call actual RTP-Info set function. */
984 status = _nx_rtsp_server_rtp_info_set(rtsp_client_ptr, track_id, track_id_len, rtp_seq, rtp_time);
985
986 /* Return status. */
987 return(status);
988 }
989
990 /**************************************************************************/
991 /* */
992 /* FUNCTION RELEASE */
993 /* */
994 /* _nx_rtsp_server_rtp_info_set PORTABLE C */
995 /* 6.3.0 */
996 /* AUTHOR */
997 /* */
998 /* Wenhui Xie, Microsoft Corporation */
999 /* */
1000 /* DESCRIPTION */
1001 /* */
1002 /* This function sets the RTP-Info to the response packet. This */
1003 /* function can only be called in PLAY callback function. */
1004 /* */
1005 /* INPUT */
1006 /* */
1007 /* rtsp_client_ptr Pointer to RTSP client */
1008 /* track_id The track ID of the media */
1009 /* track_id_len The length of the track ID */
1010 /* rtp_seq The RTP sequence number */
1011 /* rtp_time The RTP timestamp */
1012 /* */
1013 /* OUTPUT */
1014 /* */
1015 /* status Completion status */
1016 /* */
1017 /* CALLS */
1018 /* */
1019 /* nx_packet_data_append Append packet data */
1020 /* _nx_utility_uint_to_string Convert integer to string */
1021 /* */
1022 /* CALLED BY */
1023 /* */
1024 /* Application Code */
1025 /* */
1026 /* RELEASE HISTORY */
1027 /* */
1028 /* DATE NAME DESCRIPTION */
1029 /* */
1030 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
1031 /* */
1032 /**************************************************************************/
_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)1033 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)
1034 {
1035 UINT status;
1036 CHAR temp_buffer[11];
1037 UINT temp_length;
1038 NX_PACKET *response_packet_ptr = rtsp_client_ptr -> nx_rtsp_client_response_packet;
1039
1040
1041 /* Check if the packet is valid. */
1042 if (!response_packet_ptr)
1043 {
1044 return(NX_RTSP_SERVER_NO_PACKET);
1045 }
1046
1047 /* Check the request method. */
1048 if ((!rtsp_client_ptr -> nx_rtsp_client_request_ptr) ||
1049 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_method != NX_RTSP_METHOD_PLAY)
1050 {
1051 return(NX_RTSP_SERVER_INVALID_REQUEST);
1052 }
1053
1054 /* Add "RTP-Info" header. */
1055 status = nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("url="),
1056 rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
1057 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,
1058 rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
1059 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("/"),
1060 rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
1061 status += nx_packet_data_append(response_packet_ptr, track_id, track_id_len,
1062 rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
1063 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(";seq="),
1064 rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
1065 temp_length = _nx_utility_uint_to_string(rtp_seq, 10, temp_buffer, sizeof(temp_buffer));
1066 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length,
1067 rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
1068 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(";rtptime="),
1069 rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
1070 temp_length = _nx_utility_uint_to_string(rtp_time, 10, temp_buffer, sizeof(temp_buffer));
1071 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length,
1072 rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
1073 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(","),
1074 rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
1075
1076 return(status);
1077 }
1078
1079 /**************************************************************************/
1080 /* */
1081 /* FUNCTION RELEASE */
1082 /* */
1083 /* _nxe_rtsp_server_range_npt_set PORTABLE C */
1084 /* 6.3.0 */
1085 /* AUTHOR */
1086 /* */
1087 /* Wenhui Xie, Microsoft Corporation */
1088 /* */
1089 /* DESCRIPTION */
1090 /* */
1091 /* This function checks for errors in NPT set function call. */
1092 /* */
1093 /* INPUT */
1094 /* */
1095 /* rtsp_client_ptr Pointer to RTSP client */
1096 /* npt_start The NPT start time in */
1097 /* milliseconds */
1098 /* npt_end The NPT end time in */
1099 /* milliseconds */
1100 /* */
1101 /* OUTPUT */
1102 /* */
1103 /* status Completion status */
1104 /* */
1105 /* CALLS */
1106 /* */
1107 /* _nx_rtsp_server_range_npt_set Set NPT start and end time */
1108 /* */
1109 /* CALLED BY */
1110 /* */
1111 /* Application Code */
1112 /* */
1113 /* RELEASE HISTORY */
1114 /* */
1115 /* DATE NAME DESCRIPTION */
1116 /* */
1117 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
1118 /* */
1119 /**************************************************************************/
_nxe_rtsp_server_range_npt_set(NX_RTSP_CLIENT * rtsp_client_ptr,UINT npt_start,UINT npt_end)1120 UINT _nxe_rtsp_server_range_npt_set(NX_RTSP_CLIENT *rtsp_client_ptr, UINT npt_start, UINT npt_end)
1121 {
1122 UINT status;
1123
1124
1125 /* Check for invalid input pointers. */
1126 if ((rtsp_client_ptr == NX_NULL) || (rtsp_client_ptr -> nx_rtsp_client_server_ptr == NX_NULL) ||
1127 (rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
1128 {
1129 return(NX_PTR_ERROR);
1130 }
1131
1132 /* Call actual NPT set function. */
1133 status = _nx_rtsp_server_range_npt_set(rtsp_client_ptr, npt_start, npt_end);
1134
1135 /* Return status. */
1136 return(status);
1137 }
1138
1139 /**************************************************************************/
1140 /* */
1141 /* FUNCTION RELEASE */
1142 /* */
1143 /* _nx_rtsp_server_range_npt_set PORTABLE C */
1144 /* 6.3.0 */
1145 /* AUTHOR */
1146 /* */
1147 /* Wenhui Xie, Microsoft Corporation */
1148 /* */
1149 /* DESCRIPTION */
1150 /* */
1151 /* This function sets the NPT start and end time in Range field. This */
1152 /* function can only be called in PLAY and PAUSE callback function. */
1153 /* */
1154 /* INPUT */
1155 /* */
1156 /* rtsp_client_ptr Pointer to RTSP client */
1157 /* npt_start The NPT start time in */
1158 /* milliseconds */
1159 /* npt_end The NPT end time in */
1160 /* milliseconds */
1161 /* */
1162 /* OUTPUT */
1163 /* */
1164 /* status Completion status */
1165 /* */
1166 /* CALLS */
1167 /* */
1168 /* None */
1169 /* */
1170 /* CALLED BY */
1171 /* */
1172 /* Application Code */
1173 /* */
1174 /* RELEASE HISTORY */
1175 /* */
1176 /* DATE NAME DESCRIPTION */
1177 /* */
1178 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
1179 /* */
1180 /**************************************************************************/
_nx_rtsp_server_range_npt_set(NX_RTSP_CLIENT * rtsp_client_ptr,UINT npt_start,UINT npt_end)1181 UINT _nx_rtsp_server_range_npt_set(NX_RTSP_CLIENT *rtsp_client_ptr, UINT npt_start, UINT npt_end)
1182 {
1183
1184 /* Check the request method. */
1185 if ((!rtsp_client_ptr -> nx_rtsp_client_request_ptr) ||
1186 ((rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_method != NX_RTSP_METHOD_PLAY) &&
1187 (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_method != NX_RTSP_METHOD_PAUSE)))
1188 {
1189 return(NX_RTSP_SERVER_INVALID_REQUEST);
1190 }
1191
1192 /* Check start and end time. */
1193 if (npt_end < npt_start)
1194 {
1195 return(NX_RTSP_SERVER_INVALID_PARAMETER);
1196 }
1197
1198 /* Set the NPT start and end time in milliseconds. */
1199 rtsp_client_ptr -> nx_rtsp_client_npt_start = npt_start;
1200 rtsp_client_ptr -> nx_rtsp_client_npt_end = npt_end;
1201
1202 return(NX_SUCCESS);
1203 }
1204 /**************************************************************************/
1205 /* */
1206 /* FUNCTION RELEASE */
1207 /* */
1208 /* _nxe_rtsp_server_error_response_send PORTABLE C */
1209 /* 6.3.0 */
1210 /* AUTHOR */
1211 /* */
1212 /* Wenhui Xie, Microsoft Corporation */
1213 /* */
1214 /* DESCRIPTION */
1215 /* */
1216 /* This function checks for errors in error response send call. */
1217 /* */
1218 /* INPUT */
1219 /* */
1220 /* rtsp_client_ptr Pointer to RTSP client */
1221 /* status_code The status code of response */
1222 /* */
1223 /* OUTPUT */
1224 /* */
1225 /* status Completion status */
1226 /* */
1227 /* CALLS */
1228 /* */
1229 /* _nx_rtsp_server_error_response_send Send error response */
1230 /* */
1231 /* CALLED BY */
1232 /* */
1233 /* Application Code */
1234 /* */
1235 /* RELEASE HISTORY */
1236 /* */
1237 /* DATE NAME DESCRIPTION */
1238 /* */
1239 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
1240 /* */
1241 /**************************************************************************/
_nxe_rtsp_server_error_response_send(NX_RTSP_CLIENT * rtsp_client_ptr,UINT status_code)1242 UINT _nxe_rtsp_server_error_response_send(NX_RTSP_CLIENT *rtsp_client_ptr, UINT status_code)
1243 {
1244 UINT status;
1245
1246
1247 /* Check for invalid input pointers. */
1248 if ((rtsp_client_ptr == NX_NULL) || (rtsp_client_ptr -> nx_rtsp_client_server_ptr == NX_NULL) ||
1249 (rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
1250 {
1251 return(NX_PTR_ERROR);
1252 }
1253
1254 /* Call actual error response send function. */
1255 status = _nx_rtsp_server_error_response_send(rtsp_client_ptr, status_code);
1256
1257 /* Return status. */
1258 return(status);
1259 }
1260
1261 /**************************************************************************/
1262 /* */
1263 /* FUNCTION RELEASE */
1264 /* */
1265 /* _nx_rtsp_server_error_response_send PORTABLE C */
1266 /* 6.3.0 */
1267 /* AUTHOR */
1268 /* */
1269 /* Wenhui Xie, Microsoft Corporation */
1270 /* */
1271 /* DESCRIPTION */
1272 /* */
1273 /* This function sends the error response packet. */
1274 /* */
1275 /* INPUT */
1276 /* */
1277 /* rtsp_client_ptr Pointer to RTSP client */
1278 /* status_code The status code of response */
1279 /* */
1280 /* OUTPUT */
1281 /* */
1282 /* status Completion status */
1283 /* */
1284 /* CALLS */
1285 /* */
1286 /* nx_packet_release Release the packet */
1287 /* nx_packet_data_append Append packet data */
1288 /* _nx_utility_uint_to_string Convert integer to string */
1289 /* _nx_utility_string_length_check Check string length */
1290 /* nx_tcp_socket_send Send TCP packet */
1291 /* */
1292 /* CALLED BY */
1293 /* */
1294 /* Application Code */
1295 /* */
1296 /* RELEASE HISTORY */
1297 /* */
1298 /* DATE NAME DESCRIPTION */
1299 /* */
1300 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
1301 /* */
1302 /**************************************************************************/
_nx_rtsp_server_error_response_send(NX_RTSP_CLIENT * rtsp_client_ptr,UINT status_code)1303 UINT _nx_rtsp_server_error_response_send(NX_RTSP_CLIENT *rtsp_client_ptr, UINT status_code)
1304 {
1305 UINT status;
1306 UINT i;
1307 CHAR temp_buffer[11];
1308 UINT temp_length;
1309 NX_PACKET *response_packet_ptr = rtsp_client_ptr -> nx_rtsp_client_response_packet;
1310 NX_PACKET_POOL *pool_ptr = rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool;
1311
1312
1313 if (!response_packet_ptr)
1314 {
1315 return(NX_RTSP_SERVER_NO_PACKET);
1316 }
1317
1318 /* Loop to find the corresponding description. */
1319 for (i = 0; nx_rtsp_server_response_description_table[i].nx_rtsp_response_code != NX_NULL; i++)
1320 {
1321 if (nx_rtsp_server_response_description_table[i].nx_rtsp_response_code == status_code)
1322 {
1323 break;
1324 }
1325 }
1326
1327 if (nx_rtsp_server_response_description_table[i].nx_rtsp_response_code == NX_NULL)
1328 {
1329 return(NX_RTSP_SERVER_INVALID_PARAMETER);
1330 }
1331
1332 #ifndef NX_DISABLE_PACKET_CHAIN
1333 /* Reuse the response packet to append the error message.
1334 If user has already appended data to this packet and there are packets chained,
1335 remove and release the chained packets. */
1336 if (response_packet_ptr -> nx_packet_next)
1337 {
1338 nx_packet_release(response_packet_ptr -> nx_packet_next);
1339 response_packet_ptr -> nx_packet_next = NX_NULL;
1340 response_packet_ptr -> nx_packet_last = NX_NULL;
1341 }
1342 #endif /* NX_DISABLE_PACKET_CHAIN */
1343
1344 /* Reset the packet. */
1345 response_packet_ptr -> nx_packet_append_ptr = response_packet_ptr -> nx_packet_prepend_ptr;
1346 response_packet_ptr -> nx_packet_length = 0;
1347
1348 /* Add version. */
1349 status = nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(NX_RTSP_VERSION_STRING),
1350 pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
1351 status += nx_packet_data_append(response_packet_ptr, " ", 1, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
1352
1353 /* Add status code. */
1354 temp_length = _nx_utility_uint_to_string(status_code, 10, temp_buffer, sizeof(temp_buffer));
1355 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
1356 status += nx_packet_data_append(response_packet_ptr, " ", 1, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
1357 _nx_utility_string_length_check(nx_rtsp_server_response_description_table[i].nx_rtsp_response_description, &temp_length, NX_MAX_STRING_LENGTH);
1358 status += nx_packet_data_append(response_packet_ptr, nx_rtsp_server_response_description_table[i].nx_rtsp_response_description,
1359 temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
1360 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);
1361
1362 /* Add "CSeq" header. */
1363 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);
1364 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));
1365 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
1366 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);
1367
1368 /* Add "Server" header. */
1369 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);
1370 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,
1371 rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_name_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
1372 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);
1373
1374 if (status == NX_SUCCESS)
1375 {
1376
1377 /* Send the response message back. */
1378 status = nx_tcp_socket_send(&rtsp_client_ptr -> nx_rtsp_client_socket, response_packet_ptr, NX_RTSP_SERVER_SEND_TIMEOUT);
1379 }
1380
1381 /* Determine if the send was unsuccessful. */
1382 if (status)
1383 {
1384
1385 /* Release the packet. */
1386 nx_packet_release(response_packet_ptr);
1387 }
1388
1389 /* Clear the response packet pointer. */
1390 rtsp_client_ptr -> nx_rtsp_client_response_packet = NX_NULL;
1391
1392 return(status);
1393 }
1394
1395 /**************************************************************************/
1396 /* */
1397 /* FUNCTION RELEASE */
1398 /* */
1399 /* _nxe_rtsp_server_keepalive_update PORTABLE C */
1400 /* 6.3.0 */
1401 /* AUTHOR */
1402 /* */
1403 /* Wenhui Xie, Microsoft Corporation */
1404 /* */
1405 /* DESCRIPTION */
1406 /* */
1407 /* This function checks for errors in keepalive update function call. */
1408 /* */
1409 /* INPUT */
1410 /* */
1411 /* rtsp_client_ptr Pointer to RTSP client */
1412 /* */
1413 /* OUTPUT */
1414 /* */
1415 /* status Completion status */
1416 /* */
1417 /* CALLS */
1418 /* */
1419 /* _nx_rtsp_server_keepalive_update Update the timeout timer */
1420 /* */
1421 /* CALLED BY */
1422 /* */
1423 /* Application Code */
1424 /* */
1425 /* RELEASE HISTORY */
1426 /* */
1427 /* DATE NAME DESCRIPTION */
1428 /* */
1429 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
1430 /* */
1431 /**************************************************************************/
_nxe_rtsp_server_keepalive_update(NX_RTSP_CLIENT * rtsp_client_ptr)1432 UINT _nxe_rtsp_server_keepalive_update(NX_RTSP_CLIENT *rtsp_client_ptr)
1433 {
1434 UINT status;
1435
1436
1437 /* Check for invalid input pointers. */
1438 if ((rtsp_client_ptr == NX_NULL) || (rtsp_client_ptr -> nx_rtsp_client_server_ptr == NX_NULL) ||
1439 (rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
1440 {
1441 return(NX_PTR_ERROR);
1442 }
1443
1444 /* Call actual keep-alive update function. */
1445 status = _nx_rtsp_server_keepalive_update(rtsp_client_ptr);
1446
1447 /* Return status. */
1448 return(status);
1449 }
1450
1451 /**************************************************************************/
1452 /* */
1453 /* FUNCTION RELEASE */
1454 /* */
1455 /* _nx_rtsp_server_keepalive_update PORTABLE C */
1456 /* 6.3.0 */
1457 /* AUTHOR */
1458 /* */
1459 /* Wenhui Xie, Microsoft Corporation */
1460 /* */
1461 /* DESCRIPTION */
1462 /* */
1463 /* This function updates the timeout timer of the client. If RTP is */
1464 /* used for media transport, RTCP is used to show liveness of client. */
1465 /* */
1466 /* INPUT */
1467 /* */
1468 /* rtsp_client_ptr Pointer to RTSP client */
1469 /* */
1470 /* OUTPUT */
1471 /* */
1472 /* status Completion status */
1473 /* */
1474 /* CALLS */
1475 /* */
1476 /* None */
1477 /* */
1478 /* CALLED BY */
1479 /* */
1480 /* Application Code */
1481 /* */
1482 /* RELEASE HISTORY */
1483 /* */
1484 /* DATE NAME DESCRIPTION */
1485 /* */
1486 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
1487 /* */
1488 /**************************************************************************/
_nx_rtsp_server_keepalive_update(NX_RTSP_CLIENT * rtsp_client_ptr)1489 UINT _nx_rtsp_server_keepalive_update(NX_RTSP_CLIENT *rtsp_client_ptr)
1490 {
1491
1492 /* Reset the client request activity timeout. */
1493 if (rtsp_client_ptr -> nx_rtsp_client_request_activity_timeout)
1494 {
1495 rtsp_client_ptr -> nx_rtsp_client_request_activity_timeout = NX_RTSP_SERVER_ACTIVITY_TIMEOUT;
1496 }
1497
1498 return(NX_SUCCESS);
1499 }
1500
1501 /**************************************************************************/
1502 /* */
1503 /* FUNCTION RELEASE */
1504 /* */
1505 /* _nxe_rtsp_server_describe_callback_set PORTABLE C */
1506 /* 6.3.0 */
1507 /* AUTHOR */
1508 /* */
1509 /* Wenhui Xie, Microsoft Corporation */
1510 /* */
1511 /* DESCRIPTION */
1512 /* */
1513 /* This function checks for errors in DESCRIBE callback set. */
1514 /* */
1515 /* INPUT */
1516 /* */
1517 /* rtsp_server_ptr Pointer to RTSP server */
1518 /* callback Callback of DESCRIBE request */
1519 /* */
1520 /* OUTPUT */
1521 /* */
1522 /* status Completion status */
1523 /* */
1524 /* CALLS */
1525 /* */
1526 /* _nx_rtsp_server_describe_callback_set Set DESCRIBE callback */
1527 /* */
1528 /* CALLED BY */
1529 /* */
1530 /* Application Code */
1531 /* */
1532 /* RELEASE HISTORY */
1533 /* */
1534 /* DATE NAME DESCRIPTION */
1535 /* */
1536 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
1537 /* */
1538 /**************************************************************************/
_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))1539 UINT _nxe_rtsp_server_describe_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
1540 UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length))
1541 {
1542 UINT status;
1543
1544
1545 /* Check for invalid input pointers. */
1546 if ((rtsp_server_ptr == NX_NULL) || (callback == NX_NULL) ||
1547 (rtsp_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
1548 {
1549 return(NX_PTR_ERROR);
1550 }
1551
1552 /* Call actual DESCRIBE callback set function. */
1553 status = _nx_rtsp_server_describe_callback_set(rtsp_server_ptr, callback);
1554
1555 /* Return status. */
1556 return(status);
1557 }
1558
1559 /**************************************************************************/
1560 /* */
1561 /* FUNCTION RELEASE */
1562 /* */
1563 /* _nx_rtsp_server_describe_callback_set PORTABLE C */
1564 /* 6.3.0 */
1565 /* AUTHOR */
1566 /* */
1567 /* Wenhui Xie, Microsoft Corporation */
1568 /* */
1569 /* DESCRIPTION */
1570 /* */
1571 /* This function installs callback function for DESCRIBE request. */
1572 /* */
1573 /* INPUT */
1574 /* */
1575 /* rtsp_server_ptr Pointer to RTSP server */
1576 /* callback Callback of DESCRIBE request */
1577 /* */
1578 /* OUTPUT */
1579 /* */
1580 /* status Completion status */
1581 /* */
1582 /* CALLS */
1583 /* */
1584 /* None */
1585 /* */
1586 /* CALLED BY */
1587 /* */
1588 /* Application Code */
1589 /* */
1590 /* RELEASE HISTORY */
1591 /* */
1592 /* DATE NAME DESCRIPTION */
1593 /* */
1594 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
1595 /* */
1596 /**************************************************************************/
_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))1597 UINT _nx_rtsp_server_describe_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
1598 UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length))
1599 {
1600
1601 /* Set callback for DESCRIBE method. */
1602 rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_describe_callback = callback;
1603
1604 return(NX_SUCCESS);
1605 }
1606
1607 /**************************************************************************/
1608 /* */
1609 /* FUNCTION RELEASE */
1610 /* */
1611 /* _nxe_rtsp_server_setup_callback_set PORTABLE C */
1612 /* 6.3.0 */
1613 /* AUTHOR */
1614 /* */
1615 /* Wenhui Xie, Microsoft Corporation */
1616 /* */
1617 /* DESCRIPTION */
1618 /* */
1619 /* This function checks for errors in SETUP callback set. */
1620 /* */
1621 /* INPUT */
1622 /* */
1623 /* rtsp_server_ptr Pointer to RTSP server */
1624 /* callback Callback of SETUP request */
1625 /* */
1626 /* OUTPUT */
1627 /* */
1628 /* status Completion status */
1629 /* */
1630 /* CALLS */
1631 /* */
1632 /* _nx_rtsp_server_setup_callback_set Set SETUP callback */
1633 /* */
1634 /* CALLED BY */
1635 /* */
1636 /* Application Code */
1637 /* */
1638 /* RELEASE HISTORY */
1639 /* */
1640 /* DATE NAME DESCRIPTION */
1641 /* */
1642 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
1643 /* */
1644 /**************************************************************************/
_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))1645 UINT _nxe_rtsp_server_setup_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
1646 UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, NX_RTSP_TRANSPORT *transport_ptr))
1647 {
1648 UINT status;
1649
1650
1651 /* Check for invalid input pointers. */
1652 if ((rtsp_server_ptr == NX_NULL) || (callback == NX_NULL) ||
1653 (rtsp_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
1654 {
1655 return(NX_PTR_ERROR);
1656 }
1657
1658 /* Call actual SETUP callback set function. */
1659 status = _nx_rtsp_server_setup_callback_set(rtsp_server_ptr, callback);
1660
1661 /* Return status. */
1662 return(status);
1663 }
1664
1665 /**************************************************************************/
1666 /* */
1667 /* FUNCTION RELEASE */
1668 /* */
1669 /* _nx_rtsp_server_setup_callback_set PORTABLE C */
1670 /* 6.3.0 */
1671 /* AUTHOR */
1672 /* */
1673 /* Wenhui Xie, Microsoft Corporation */
1674 /* */
1675 /* DESCRIPTION */
1676 /* */
1677 /* This function installs callback function for SETUP request. */
1678 /* */
1679 /* INPUT */
1680 /* */
1681 /* rtsp_server_ptr Pointer to RTSP server */
1682 /* callback Callback of SETUP request */
1683 /* */
1684 /* OUTPUT */
1685 /* */
1686 /* status Completion status */
1687 /* */
1688 /* CALLS */
1689 /* */
1690 /* None */
1691 /* */
1692 /* CALLED BY */
1693 /* */
1694 /* Application Code */
1695 /* */
1696 /* RELEASE HISTORY */
1697 /* */
1698 /* DATE NAME DESCRIPTION */
1699 /* */
1700 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
1701 /* */
1702 /**************************************************************************/
_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))1703 UINT _nx_rtsp_server_setup_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
1704 UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, NX_RTSP_TRANSPORT *transport_ptr))
1705 {
1706
1707 /* Set callback for SETUP method. */
1708 rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_setup_callback = callback;
1709
1710 return(NX_SUCCESS);
1711 }
1712
1713 /**************************************************************************/
1714 /* */
1715 /* FUNCTION RELEASE */
1716 /* */
1717 /* _nxe_rtsp_server_play_callback_set PORTABLE C */
1718 /* 6.3.0 */
1719 /* AUTHOR */
1720 /* */
1721 /* Wenhui Xie, Microsoft Corporation */
1722 /* */
1723 /* DESCRIPTION */
1724 /* */
1725 /* This function checks for errors in PLAY callback set. */
1726 /* */
1727 /* INPUT */
1728 /* */
1729 /* rtsp_server_ptr Pointer to RTSP server */
1730 /* callback Callback of PLAY request */
1731 /* */
1732 /* OUTPUT */
1733 /* */
1734 /* status Completion status */
1735 /* */
1736 /* CALLS */
1737 /* */
1738 /* _nx_rtsp_server_play_callback_set Set PLAY callback */
1739 /* */
1740 /* CALLED BY */
1741 /* */
1742 /* Application Code */
1743 /* */
1744 /* RELEASE HISTORY */
1745 /* */
1746 /* DATE NAME DESCRIPTION */
1747 /* */
1748 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
1749 /* */
1750 /**************************************************************************/
_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))1751 UINT _nxe_rtsp_server_play_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
1752 UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length))
1753 {
1754 UINT status;
1755
1756
1757 /* Check for invalid input pointers. */
1758 if ((rtsp_server_ptr == NX_NULL) || (callback == NX_NULL) ||
1759 (rtsp_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
1760 {
1761 return(NX_PTR_ERROR);
1762 }
1763
1764 /* Call actual PLAY callback set function. */
1765 status = _nx_rtsp_server_play_callback_set(rtsp_server_ptr, callback);
1766
1767 /* Return status. */
1768 return(status);
1769 }
1770
1771 /**************************************************************************/
1772 /* */
1773 /* FUNCTION RELEASE */
1774 /* */
1775 /* _nx_rtsp_server_play_callback_set PORTABLE C */
1776 /* 6.3.0 */
1777 /* AUTHOR */
1778 /* */
1779 /* Wenhui Xie, Microsoft Corporation */
1780 /* */
1781 /* DESCRIPTION */
1782 /* */
1783 /* This function installs callback function for PLAY request. */
1784 /* */
1785 /* INPUT */
1786 /* */
1787 /* rtsp_server_ptr Pointer to RTSP server */
1788 /* callback Callback of PLAY request */
1789 /* */
1790 /* OUTPUT */
1791 /* */
1792 /* status Completion status */
1793 /* */
1794 /* CALLS */
1795 /* */
1796 /* None */
1797 /* */
1798 /* CALLED BY */
1799 /* */
1800 /* Application Code */
1801 /* */
1802 /* RELEASE HISTORY */
1803 /* */
1804 /* DATE NAME DESCRIPTION */
1805 /* */
1806 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
1807 /* */
1808 /**************************************************************************/
_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))1809 UINT _nx_rtsp_server_play_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
1810 UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length))
1811 {
1812
1813 /* Set callback for PLAY method. */
1814 rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_play_callback = callback;
1815
1816 return(NX_SUCCESS);
1817 }
1818
1819 /**************************************************************************/
1820 /* */
1821 /* FUNCTION RELEASE */
1822 /* */
1823 /* _nxe_rtsp_server_teardown_callback_set PORTABLE C */
1824 /* 6.3.0 */
1825 /* AUTHOR */
1826 /* */
1827 /* Wenhui Xie, Microsoft Corporation */
1828 /* */
1829 /* DESCRIPTION */
1830 /* */
1831 /* This function checks for errors in TEARDOWN callback set. */
1832 /* */
1833 /* INPUT */
1834 /* */
1835 /* rtsp_server_ptr Pointer to RTSP server */
1836 /* callback Callback of TEARDOWN request */
1837 /* */
1838 /* OUTPUT */
1839 /* */
1840 /* status Completion status */
1841 /* */
1842 /* CALLS */
1843 /* */
1844 /* _nx_rtsp_server_teardown_callback_set Set TEARDOWN callback */
1845 /* */
1846 /* CALLED BY */
1847 /* */
1848 /* Application Code */
1849 /* */
1850 /* RELEASE HISTORY */
1851 /* */
1852 /* DATE NAME DESCRIPTION */
1853 /* */
1854 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
1855 /* */
1856 /**************************************************************************/
_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))1857 UINT _nxe_rtsp_server_teardown_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
1858 UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length))
1859 {
1860 UINT status;
1861
1862
1863 /* Check for invalid input pointers. */
1864 if ((rtsp_server_ptr == NX_NULL) || (callback == NX_NULL) ||
1865 (rtsp_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
1866 {
1867 return(NX_PTR_ERROR);
1868 }
1869
1870 /* Call actual TEARDOWN callback set function. */
1871 status = _nx_rtsp_server_teardown_callback_set(rtsp_server_ptr, callback);
1872
1873 /* Return status. */
1874 return(status);
1875 }
1876
1877 /**************************************************************************/
1878 /* */
1879 /* FUNCTION RELEASE */
1880 /* */
1881 /* _nx_rtsp_server_teardown_callback_set PORTABLE C */
1882 /* 6.3.0 */
1883 /* AUTHOR */
1884 /* */
1885 /* Wenhui Xie, Microsoft Corporation */
1886 /* */
1887 /* DESCRIPTION */
1888 /* */
1889 /* This function installs callback function for TEARDOWN request. */
1890 /* */
1891 /* INPUT */
1892 /* */
1893 /* rtsp_server_ptr Pointer to RTSP server */
1894 /* callback Callback of TEARDOWN request */
1895 /* */
1896 /* OUTPUT */
1897 /* */
1898 /* status Completion status */
1899 /* */
1900 /* CALLS */
1901 /* */
1902 /* None */
1903 /* */
1904 /* CALLED BY */
1905 /* */
1906 /* Application Code */
1907 /* */
1908 /* RELEASE HISTORY */
1909 /* */
1910 /* DATE NAME DESCRIPTION */
1911 /* */
1912 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
1913 /* */
1914 /**************************************************************************/
_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))1915 UINT _nx_rtsp_server_teardown_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
1916 UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length))
1917 {
1918
1919 /* Set callback for TEARDOWN method. */
1920 rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_teardown_callback = callback;
1921
1922 return(NX_SUCCESS);
1923 }
1924
1925 /**************************************************************************/
1926 /* */
1927 /* FUNCTION RELEASE */
1928 /* */
1929 /* _nxe_rtsp_server_pause_callback_set PORTABLE C */
1930 /* 6.3.0 */
1931 /* AUTHOR */
1932 /* */
1933 /* Wenhui Xie, Microsoft Corporation */
1934 /* */
1935 /* DESCRIPTION */
1936 /* */
1937 /* This function checks for errors in PAUSE callback set. */
1938 /* */
1939 /* INPUT */
1940 /* */
1941 /* rtsp_server_ptr Pointer to RTSP server */
1942 /* callback Callback of PAUSE request */
1943 /* */
1944 /* OUTPUT */
1945 /* */
1946 /* status Completion status */
1947 /* */
1948 /* CALLS */
1949 /* */
1950 /* _nx_rtsp_server_pause_callback_set Set PAUSE callback */
1951 /* */
1952 /* CALLED BY */
1953 /* */
1954 /* Application Code */
1955 /* */
1956 /* RELEASE HISTORY */
1957 /* */
1958 /* DATE NAME DESCRIPTION */
1959 /* */
1960 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
1961 /* */
1962 /**************************************************************************/
_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))1963 UINT _nxe_rtsp_server_pause_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
1964 UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length))
1965 {
1966 UINT status;
1967
1968
1969 /* Check for invalid input pointers. */
1970 if ((rtsp_server_ptr == NX_NULL) || (callback == NX_NULL) ||
1971 (rtsp_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
1972 {
1973 return(NX_PTR_ERROR);
1974 }
1975
1976 /* Call actual PAUSE callback set function. */
1977 status = _nx_rtsp_server_pause_callback_set(rtsp_server_ptr, callback);
1978
1979 /* Return status. */
1980 return(status);
1981 }
1982
1983 /**************************************************************************/
1984 /* */
1985 /* FUNCTION RELEASE */
1986 /* */
1987 /* _nx_rtsp_server_pause_callback_set PORTABLE C */
1988 /* 6.3.0 */
1989 /* AUTHOR */
1990 /* */
1991 /* Wenhui Xie, Microsoft Corporation */
1992 /* */
1993 /* DESCRIPTION */
1994 /* */
1995 /* This function installs callback function for PAUSE request. */
1996 /* */
1997 /* INPUT */
1998 /* */
1999 /* rtsp_server_ptr Pointer to RTSP server */
2000 /* callback Callback of PAUSE request */
2001 /* */
2002 /* OUTPUT */
2003 /* */
2004 /* status Completion status */
2005 /* */
2006 /* CALLS */
2007 /* */
2008 /* None */
2009 /* */
2010 /* CALLED BY */
2011 /* */
2012 /* Application Code */
2013 /* */
2014 /* RELEASE HISTORY */
2015 /* */
2016 /* DATE NAME DESCRIPTION */
2017 /* */
2018 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
2019 /* */
2020 /**************************************************************************/
_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))2021 UINT _nx_rtsp_server_pause_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
2022 UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length))
2023 {
2024
2025 /* Set callback for PAUSE method. */
2026 rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_pause_callback = callback;
2027
2028 return(NX_SUCCESS);
2029 }
2030
2031 /**************************************************************************/
2032 /* */
2033 /* FUNCTION RELEASE */
2034 /* */
2035 /* _nxe_rtsp_server_set_parameter_callback_set PORTABLE C */
2036 /* 6.3.0 */
2037 /* AUTHOR */
2038 /* */
2039 /* Wenhui Xie, Microsoft Corporation */
2040 /* */
2041 /* DESCRIPTION */
2042 /* */
2043 /* This function checks for errors in SET_PARAMETER callback set. */
2044 /* */
2045 /* INPUT */
2046 /* */
2047 /* rtsp_server_ptr Pointer to RTSP server */
2048 /* callback Callback of SET_PARAMETER */
2049 /* request */
2050 /* */
2051 /* OUTPUT */
2052 /* */
2053 /* status Completion status */
2054 /* */
2055 /* CALLS */
2056 /* */
2057 /* _nx_rtsp_server_set_parameter_callback_set */
2058 /* Set SET_PARAMETER callback */
2059 /* */
2060 /* CALLED BY */
2061 /* */
2062 /* Application Code */
2063 /* */
2064 /* RELEASE HISTORY */
2065 /* */
2066 /* DATE NAME DESCRIPTION */
2067 /* */
2068 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
2069 /* */
2070 /**************************************************************************/
_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))2071 UINT _nxe_rtsp_server_set_parameter_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
2072 UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *parameter_ptr, ULONG parameter_length))
2073 {
2074 UINT status;
2075
2076
2077 /* Check for invalid input pointers. */
2078 if ((rtsp_server_ptr == NX_NULL) || (callback == NX_NULL) ||
2079 (rtsp_server_ptr -> nx_rtsp_server_id != NX_RTSP_SERVER_ID))
2080 {
2081 return(NX_PTR_ERROR);
2082 }
2083
2084 /* Call actual SET_PARAMETER callback set function. */
2085 status = _nx_rtsp_server_set_parameter_callback_set(rtsp_server_ptr, callback);
2086
2087 /* Return status. */
2088 return(status);
2089 }
2090
2091 /**************************************************************************/
2092 /* */
2093 /* FUNCTION RELEASE */
2094 /* */
2095 /* _nx_rtsp_server_set_parameter_callback_set PORTABLE C */
2096 /* 6.3.0 */
2097 /* AUTHOR */
2098 /* */
2099 /* Wenhui Xie, Microsoft Corporation */
2100 /* */
2101 /* DESCRIPTION */
2102 /* */
2103 /* This function installs callback function for SET_PARAMETER request. */
2104 /* */
2105 /* INPUT */
2106 /* */
2107 /* rtsp_server_ptr Pointer to RTSP server */
2108 /* callback Callback of SET_PARAMETER */
2109 /* request */
2110 /* */
2111 /* OUTPUT */
2112 /* */
2113 /* status Completion status */
2114 /* */
2115 /* CALLS */
2116 /* */
2117 /* None */
2118 /* */
2119 /* CALLED BY */
2120 /* */
2121 /* Application Code */
2122 /* */
2123 /* RELEASE HISTORY */
2124 /* */
2125 /* DATE NAME DESCRIPTION */
2126 /* */
2127 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
2128 /* */
2129 /**************************************************************************/
_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))2130 UINT _nx_rtsp_server_set_parameter_callback_set(NX_RTSP_SERVER *rtsp_server_ptr,
2131 UINT (*callback)(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *parameter_ptr, ULONG parameter_length))
2132 {
2133
2134 /* Set callback for SET_PARAMETER method. */
2135 rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_set_parameter_callback = callback;
2136
2137 return(NX_SUCCESS);
2138 }
2139
2140 /**************************************************************************/
2141 /* */
2142 /* FUNCTION RELEASE */
2143 /* */
2144 /* _nx_rtsp_server_thread_entry PORTABLE C */
2145 /* 6.3.0 */
2146 /* AUTHOR */
2147 /* */
2148 /* Wenhui Xie, Microsoft Corporation */
2149 /* */
2150 /* DESCRIPTION */
2151 /* */
2152 /* This function handles events of RTSP server thread. */
2153 /* */
2154 /* INPUT */
2155 /* */
2156 /* rtsp_server_address Pointer to RTSP server */
2157 /* */
2158 /* OUTPUT */
2159 /* */
2160 /* None */
2161 /* */
2162 /* CALLS */
2163 /* */
2164 /* tx_event_flags_get Get event flags */
2165 /* _nx_rtsp_server_connect_process Process connect event */
2166 /* _nx_rtsp_server_request_process Process request event */
2167 /* _nx_rtsp_server_disconnect_process Process disconnect event */
2168 /* _nx_rtsp_server_timeout_process Process timeout event */
2169 /* */
2170 /* CALLED BY */
2171 /* */
2172 /* ThreadX */
2173 /* */
2174 /* RELEASE HISTORY */
2175 /* */
2176 /* DATE NAME DESCRIPTION */
2177 /* */
2178 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
2179 /* */
2180 /**************************************************************************/
_nx_rtsp_server_thread_entry(ULONG rtsp_server_address)2181 static VOID _nx_rtsp_server_thread_entry(ULONG rtsp_server_address)
2182 {
2183 NX_RTSP_SERVER *rtsp_server_ptr;
2184 UINT status;
2185 ULONG events;
2186
2187
2188 /* Setup the server pointer. */
2189 rtsp_server_ptr = (NX_RTSP_SERVER *)rtsp_server_address;
2190
2191 /* Loop to process RTSP Server requests. */
2192 while (1)
2193 {
2194
2195 /* Wait for an RTSP client activity. */
2196 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);
2197
2198 /* Check the return status. */
2199 if (status)
2200 {
2201
2202 /* If an error occurs, simply continue the loop. */
2203 continue;
2204 }
2205
2206 /* Otherwise, an event is present. Process according to the event. */
2207
2208 /* Check for a client connection event. */
2209 if (events & NX_RTSP_SERVER_CONNECT_EVENT)
2210 {
2211
2212 /* Call the connect process. */
2213 _nx_rtsp_server_connect_process(rtsp_server_ptr);
2214 }
2215
2216 /* Check for a client request event. */
2217 if (events & NX_RTSP_SERVER_REQUEST_EVENT)
2218 {
2219
2220 /* Call the request process. */
2221 _nx_rtsp_server_request_process(rtsp_server_ptr);
2222 }
2223
2224 /* Check for a client disconnect event. */
2225 if (events & NX_RTSP_SERVER_DISCONNECT_EVENT)
2226 {
2227
2228 /* Call the disconnect process. */
2229 _nx_rtsp_server_disconnect_process(rtsp_server_ptr);
2230 }
2231
2232 /* Check for a client activity timeout event. */
2233 if (events & NX_RTSP_SERVER_TIMEOUT_EVENT)
2234 {
2235
2236 /* Call the activity timeout process. */
2237 _nx_rtsp_server_timeout_process(rtsp_server_ptr);
2238 }
2239 }
2240 }
2241
2242 /**************************************************************************/
2243 /* */
2244 /* FUNCTION RELEASE */
2245 /* */
2246 /* _nx_rtsp_server_request_receive PORTABLE C */
2247 /* 6.3.0 */
2248 /* AUTHOR */
2249 /* */
2250 /* Wenhui Xie, Microsoft Corporation */
2251 /* */
2252 /* DESCRIPTION */
2253 /* */
2254 /* This function receives the entire request from client including the */
2255 /* request header and message body. */
2256 /* */
2257 /* INPUT */
2258 /* */
2259 /* rtsp_server_ptr Pointer to RTSP server */
2260 /* rtsp_client_ptr Pointer to RTSP client */
2261 /* */
2262 /* OUTPUT */
2263 /* */
2264 /* None */
2265 /* */
2266 /* CALLS */
2267 /* */
2268 /* nx_tcp_socket_receive Receive TCP packet */
2269 /* _nx_rtsp_server_memicmp Compare two strings */
2270 /* nx_packet_data_append Append packet data */
2271 /* nx_packet_release Release the packet */
2272 /* */
2273 /* CALLED BY */
2274 /* */
2275 /* _nx_rtsp_server_request_process */
2276 /* */
2277 /* RELEASE HISTORY */
2278 /* */
2279 /* DATE NAME DESCRIPTION */
2280 /* */
2281 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
2282 /* */
2283 /**************************************************************************/
_nx_rtsp_server_request_receive(NX_RTSP_SERVER * rtsp_server_ptr,NX_RTSP_CLIENT * rtsp_client_ptr)2284 static UINT _nx_rtsp_server_request_receive(NX_RTSP_SERVER *rtsp_server_ptr, NX_RTSP_CLIENT *rtsp_client_ptr)
2285 {
2286 NX_PACKET *head_packet_ptr = rtsp_client_ptr -> nx_rtsp_client_request_packet;
2287 NX_PACKET *new_packet_ptr;
2288 NX_PACKET *work_ptr;
2289 NX_PACKET *tmp_ptr;
2290 UCHAR *buffer_ptr;
2291 UINT crlf_found = 0;
2292 UINT content_length_found = 0;
2293 UINT content_length = 0;
2294 UINT header_length = 0;
2295 UINT status = NX_SUCCESS;
2296
2297
2298 if (head_packet_ptr == NX_NULL)
2299 {
2300
2301 /* Receive a request from RTSP client. */
2302 status = nx_tcp_socket_receive(&(rtsp_client_ptr -> nx_rtsp_client_socket), &head_packet_ptr, NX_NO_WAIT);
2303
2304 /* Check the return status. */
2305 if (status == NX_NO_PACKET)
2306 {
2307 return(NX_IN_PROGRESS);
2308 }
2309 else if (status != NX_SUCCESS)
2310 {
2311
2312 /* Return an error condition. */
2313 return(status);
2314 }
2315
2316 rtsp_client_ptr -> nx_rtsp_client_request_packet = head_packet_ptr;
2317 }
2318
2319 work_ptr = head_packet_ptr;
2320
2321 /* Build a pointer to the buffer area. */
2322 buffer_ptr = work_ptr -> nx_packet_prepend_ptr;
2323
2324 while (status == NX_SUCCESS)
2325 {
2326
2327 /* nx_rtsp_client_request_bytes_total is not zero means the receiving of request header is complete. */
2328 if (rtsp_client_ptr -> nx_rtsp_client_request_bytes_total == 0)
2329 {
2330
2331 /* See if there is a blank line present in the buffer. */
2332 /* Search the buffer for a cr/lf pair. */
2333 while ((buffer_ptr < work_ptr -> nx_packet_append_ptr) &&
2334 (crlf_found < 4))
2335 {
2336 if (!(crlf_found & 1) && (*buffer_ptr == '\r'))
2337 {
2338
2339 /* Found CR. */
2340 crlf_found++;
2341 }
2342 else if ((crlf_found & 1) && (*buffer_ptr == '\n'))
2343 {
2344
2345 /* Found LF. */
2346 crlf_found++;
2347 }
2348 else
2349 {
2350
2351 /* Reset the CRLF marker. */
2352 crlf_found = 0;
2353 }
2354
2355 if ((content_length_found == NX_FALSE) && ((buffer_ptr + 14) < work_ptr -> nx_packet_append_ptr) &&
2356 (_nx_rtsp_server_memicmp(buffer_ptr, 15, NX_RTSP_SERVER_STRING_WITH_SIZE("Content-length:")) == NX_SUCCESS))
2357 {
2358
2359 /* Set the found flag. */
2360 content_length_found = NX_TRUE;
2361 buffer_ptr += 15;
2362 header_length += 15;
2363
2364 /* Now skip over white space. */
2365 while ((buffer_ptr < work_ptr -> nx_packet_append_ptr) && (*buffer_ptr == ' '))
2366 {
2367 buffer_ptr++;
2368 header_length++;
2369 }
2370
2371 /* Now convert the length into a numeric value. */
2372 while ((buffer_ptr < work_ptr -> nx_packet_append_ptr) && (*buffer_ptr >= '0') && (*buffer_ptr <= '9'))
2373 {
2374
2375 /* Update the content length. */
2376 content_length = content_length * 10;
2377 content_length = content_length + (UINT)(*buffer_ptr) - '0';
2378
2379 /* Move the buffer pointer forward. */
2380 buffer_ptr++;
2381 header_length++;
2382 }
2383 }
2384
2385 /* Move the buffer pointer up. */
2386 buffer_ptr++;
2387 header_length++;
2388 }
2389
2390 if (crlf_found == 4)
2391 {
2392
2393 /* Store content length and total bytes need to be received. */
2394 rtsp_client_ptr -> nx_rtsp_client_request_content_length = content_length;
2395 rtsp_client_ptr -> nx_rtsp_client_request_bytes_total = content_length + header_length;
2396
2397 /* Yes, we have found the end of the HTTP request header. Continue to receive content */
2398 continue;
2399 }
2400
2401 #ifndef NX_DISABLE_PACKET_CHAIN
2402
2403 /* Determine if the packet has already overflowed into another packet. */
2404 if (work_ptr -> nx_packet_next != NX_NULL)
2405 {
2406
2407 /* Get the next packet in the chain. */
2408 work_ptr = work_ptr -> nx_packet_next;
2409 buffer_ptr = work_ptr -> nx_packet_prepend_ptr;
2410
2411 continue;
2412 }
2413 #endif /* NX_DISABLE_PACKET_CHAIN */
2414 }
2415 else
2416 {
2417
2418 /* Check if we have received the total bytes of the request. */
2419 if (head_packet_ptr -> nx_packet_length == rtsp_client_ptr -> nx_rtsp_client_request_bytes_total)
2420 {
2421 break;
2422 }
2423 else if (head_packet_ptr -> nx_packet_length > rtsp_client_ptr -> nx_rtsp_client_request_bytes_total)
2424 {
2425 status = NX_INVALID_PACKET;
2426 break;
2427 }
2428 }
2429
2430 /* Receive another packet from the RTSP Client. */
2431 status = nx_tcp_socket_receive(&(rtsp_client_ptr -> nx_rtsp_client_socket), &new_packet_ptr, NX_NO_WAIT);
2432
2433 /* Check the return status. */
2434 if (status == NX_NO_PACKET)
2435 {
2436 return(NX_IN_PROGRESS);
2437 }
2438 else if (status != NX_SUCCESS)
2439 {
2440 break;
2441 }
2442
2443 /* Successfully received another packet. Its contents now need to be placed in the head packet. */
2444 tmp_ptr = new_packet_ptr;
2445
2446 #ifndef NX_DISABLE_PACKET_CHAIN
2447 while (tmp_ptr)
2448 #endif /* NX_DISABLE_PACKET_CHAIN */
2449 {
2450
2451 /* Copy the contents of the current packet into the head packet. */
2452 status = nx_packet_data_append(head_packet_ptr, (VOID *) tmp_ptr -> nx_packet_prepend_ptr,
2453 (ULONG)(tmp_ptr -> nx_packet_append_ptr - tmp_ptr -> nx_packet_prepend_ptr),
2454 rtsp_server_ptr -> nx_rtsp_server_packet_pool, NX_NO_WAIT);
2455
2456 #ifndef NX_DISABLE_PACKET_CHAIN
2457
2458 /* Determine if an error occurred. */
2459 if (status != NX_SUCCESS)
2460 {
2461 break;
2462 }
2463 else
2464 {
2465 tmp_ptr = tmp_ptr -> nx_packet_next;
2466 }
2467 #endif /* NX_DISABLE_PACKET_CHAIN */
2468 }
2469
2470 /* Release the new packet. */
2471 nx_packet_release(new_packet_ptr);
2472
2473 /* If we haven't received all the request header, and haven't found the content length field. */
2474 if ((rtsp_client_ptr -> nx_rtsp_client_request_bytes_total == 0) && (content_length_found == NX_FALSE))
2475 {
2476
2477 /* Search again from the start of the packet. */
2478 work_ptr = head_packet_ptr;
2479
2480 /* Build a pointer to the buffer area. */
2481 buffer_ptr = work_ptr -> nx_packet_prepend_ptr;
2482
2483 /* Reset the header length. */
2484 header_length = 0;
2485 }
2486 }
2487
2488 if (status)
2489 {
2490
2491 /* Release the packet. */
2492 nx_packet_release(head_packet_ptr);
2493 rtsp_client_ptr -> nx_rtsp_client_request_packet = NX_NULL;
2494 rtsp_client_ptr -> nx_rtsp_client_request_bytes_total = 0;
2495 }
2496
2497 /* Return status. */
2498 return(status);
2499 }
2500
2501 /**************************************************************************/
2502 /* */
2503 /* FUNCTION RELEASE */
2504 /* */
2505 /* _nx_rtsp_server_request_parse PORTABLE C */
2506 /* 6.3.0 */
2507 /* AUTHOR */
2508 /* */
2509 /* Wenhui Xie, Microsoft Corporation */
2510 /* */
2511 /* DESCRIPTION */
2512 /* */
2513 /* This function parses incoming request packet. */
2514 /* */
2515 /* INPUT */
2516 /* */
2517 /* rtsp_client_ptr Pointer to RTSP client */
2518 /* rtsp_client_request_ptr Pointer to request structure */
2519 /* */
2520 /* OUTPUT */
2521 /* */
2522 /* status Completion status */
2523 /* */
2524 /* CALLS */
2525 /* */
2526 /* memset Reset memory */
2527 /* _nx_rtsp_server_request_line_parse Parse request line */
2528 /* _nx_rtsp_server_request_header_parse Parse request header */
2529 /* nx_packet_allocate Allocate a packet */
2530 /* _nx_rtsp_server_error_response_send Send error response */
2531 /* */
2532 /* CALLED BY */
2533 /* */
2534 /* _nx_rtsp_server_request_process */
2535 /* */
2536 /* RELEASE HISTORY */
2537 /* */
2538 /* DATE NAME DESCRIPTION */
2539 /* */
2540 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
2541 /* */
2542 /**************************************************************************/
_nx_rtsp_server_request_parse(NX_RTSP_CLIENT * rtsp_client_ptr,NX_RTSP_CLIENT_REQUEST * rtsp_client_request_ptr)2543 static UINT _nx_rtsp_server_request_parse(NX_RTSP_CLIENT *rtsp_client_ptr, NX_RTSP_CLIENT_REQUEST *rtsp_client_request_ptr)
2544 {
2545 UINT status;
2546 UCHAR *rtsp_client_request_buf;
2547 UCHAR *rtsp_client_request_buf_ptr;
2548 UCHAR *rtsp_client_request_buf_end;
2549 NX_PACKET *rtsp_client_request_packet = rtsp_client_ptr -> nx_rtsp_client_request_packet;
2550
2551
2552 #ifndef NX_DISABLE_PACKET_CHAIN
2553
2554 /* Check if the packet is chained. Chained packet isn't supported now. */
2555 if (rtsp_client_request_packet -> nx_packet_next)
2556 {
2557 return(NX_INVALID_PACKET);
2558 }
2559 #endif /* NX_DISABLE_PACKET_CHAIN */
2560
2561 /* Reset the request info. */
2562 memset(rtsp_client_request_ptr, 0, sizeof(NX_RTSP_CLIENT_REQUEST));
2563
2564 /* Set the buffer pointer. */
2565 rtsp_client_request_buf = rtsp_client_request_packet -> nx_packet_prepend_ptr;
2566 rtsp_client_request_buf_end = rtsp_client_request_packet -> nx_packet_append_ptr - rtsp_client_ptr -> nx_rtsp_client_request_content_length;
2567 rtsp_client_request_buf_ptr = rtsp_client_request_buf;
2568
2569 /* Parse the request line. */
2570 status = _nx_rtsp_server_request_line_parse(rtsp_client_request_ptr, &rtsp_client_request_buf_ptr, rtsp_client_request_buf_end);
2571
2572 if (status == NX_SUCCESS)
2573 {
2574
2575 /* Continue parse headers. */
2576 while (rtsp_client_request_buf_ptr < rtsp_client_request_buf_end)
2577 {
2578
2579 /* Parse the headers. */
2580 status = _nx_rtsp_server_request_header_parse(rtsp_client_ptr, rtsp_client_request_ptr,
2581 &rtsp_client_request_buf_ptr, rtsp_client_request_buf_end);
2582
2583 if (status)
2584 {
2585 break;
2586 }
2587 }
2588 }
2589
2590 if (status)
2591 {
2592
2593 /* Send error response packet. */
2594 if (nx_packet_allocate(rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool,
2595 &(rtsp_client_ptr -> nx_rtsp_client_response_packet),
2596 NX_TCP_PACKET, NX_RTSP_SERVER_PACKET_TIMEOUT) == NX_SUCCESS)
2597 {
2598 _nx_rtsp_server_error_response_send(rtsp_client_ptr, status);
2599 }
2600 else
2601 {
2602
2603 /* There is nothing we can do here. Ideally log this error event. */
2604 rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_allocation_errors++;
2605 }
2606 }
2607
2608 return(status);
2609 }
2610
2611 /**************************************************************************/
2612 /* */
2613 /* FUNCTION RELEASE */
2614 /* */
2615 /* _nx_rtsp_server_request_line_parse PORTABLE C */
2616 /* 6.3.0 */
2617 /* AUTHOR */
2618 /* */
2619 /* Wenhui Xie, Microsoft Corporation */
2620 /* */
2621 /* DESCRIPTION */
2622 /* */
2623 /* This function parses request method, URI and version. */
2624 /* */
2625 /* INPUT */
2626 /* */
2627 /* rtsp_client_request_ptr Pointer to request structure */
2628 /* request_buffer Start of request buffer */
2629 /* request_buffer_end End to request buffer */
2630 /* */
2631 /* OUTPUT */
2632 /* */
2633 /* status Completion status */
2634 /* */
2635 /* CALLS */
2636 /* */
2637 /* memcmp Compare two strings */
2638 /* */
2639 /* CALLED BY */
2640 /* */
2641 /* _nx_rtsp_server_request_parse */
2642 /* */
2643 /* RELEASE HISTORY */
2644 /* */
2645 /* DATE NAME DESCRIPTION */
2646 /* */
2647 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
2648 /* */
2649 /**************************************************************************/
_nx_rtsp_server_request_line_parse(NX_RTSP_CLIENT_REQUEST * rtsp_client_request_ptr,UCHAR ** request_buffer,UCHAR * request_buffer_end)2650 static UINT _nx_rtsp_server_request_line_parse(NX_RTSP_CLIENT_REQUEST *rtsp_client_request_ptr, UCHAR **request_buffer, UCHAR *request_buffer_end)
2651 {
2652 UCHAR *request_buffer_ptr;
2653 UCHAR *temp_ptr;
2654 UINT temp_length = 0;
2655
2656
2657 /* Set the buffer pointer. */
2658 request_buffer_ptr = *request_buffer;
2659
2660 /* We assume the client request is well formatted. */
2661 /* Parse the request line. */
2662
2663 /* Trim the spaces before the method. */
2664 while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr == ' '))
2665 {
2666 request_buffer_ptr++;
2667 }
2668
2669 /* Return error if no more data. */
2670 if (request_buffer_ptr == request_buffer_end)
2671 {
2672 return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
2673 }
2674
2675 /* Set the method pointer. */
2676 temp_ptr = request_buffer_ptr;
2677
2678 /* Find the ending point of the method. */
2679 while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr != ' ') &&
2680 (*request_buffer_ptr != '\r') && (*request_buffer_ptr != '\n'))
2681 {
2682 request_buffer_ptr++;
2683 }
2684
2685 /* Must has space before URI. */
2686 if ((request_buffer_ptr == request_buffer_end) || (*request_buffer_ptr != ' '))
2687 {
2688 return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
2689 }
2690
2691 /* Calculate method length. */
2692 temp_length = (UINT)(request_buffer_ptr - temp_ptr);
2693
2694 /* The method is case-sensitive. */
2695 if ((temp_length == NX_RTSP_SERVER_STRING_SIZE("OPTIONS")) && (memcmp(temp_ptr, "OPTIONS", temp_length) == 0))
2696 {
2697 rtsp_client_request_ptr -> nx_rtsp_client_request_method = NX_RTSP_METHOD_OPTIONS;
2698 }
2699 else if ((temp_length == NX_RTSP_SERVER_STRING_SIZE("DESCRIBE")) && (memcmp(temp_ptr, "DESCRIBE", temp_length) == 0))
2700 {
2701 rtsp_client_request_ptr -> nx_rtsp_client_request_method = NX_RTSP_METHOD_DESCRIBE;
2702 }
2703 else if ((temp_length == NX_RTSP_SERVER_STRING_SIZE("SETUP")) && (memcmp(temp_ptr, "SETUP", temp_length) == 0))
2704 {
2705 rtsp_client_request_ptr -> nx_rtsp_client_request_method = NX_RTSP_METHOD_SETUP;
2706 }
2707 else if ((temp_length == NX_RTSP_SERVER_STRING_SIZE("PLAY")) && (memcmp(temp_ptr, "PLAY", temp_length) == 0))
2708 {
2709 rtsp_client_request_ptr -> nx_rtsp_client_request_method = NX_RTSP_METHOD_PLAY;
2710 }
2711 else if ((temp_length == NX_RTSP_SERVER_STRING_SIZE("PAUSE")) && (memcmp(temp_ptr, "PAUSE", temp_length) == 0))
2712 {
2713 rtsp_client_request_ptr -> nx_rtsp_client_request_method = NX_RTSP_METHOD_PAUSE;
2714 }
2715 else if ((temp_length == NX_RTSP_SERVER_STRING_SIZE("TEARDOWN")) && (memcmp(temp_ptr, "TEARDOWN", temp_length) == 0))
2716 {
2717 rtsp_client_request_ptr -> nx_rtsp_client_request_method = NX_RTSP_METHOD_TEARDOWN;
2718 }
2719 else if ((temp_length == NX_RTSP_SERVER_STRING_SIZE("SET_PARAMETER")) && (memcmp(temp_ptr, "SET_PARAMETER", temp_length) == 0))
2720 {
2721 rtsp_client_request_ptr -> nx_rtsp_client_request_method = NX_RTSP_METHOD_SET_PARAMETER;
2722 }
2723 else
2724 {
2725 rtsp_client_request_ptr -> nx_rtsp_client_request_method = NX_RTSP_METHOD_NOT_SUPPORT;
2726
2727 return(NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED);
2728 }
2729
2730 /* Trim the spaces. */
2731 while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr == ' '))
2732 {
2733 request_buffer_ptr++;
2734 }
2735
2736 /* Return error if no more data. */
2737 if (request_buffer_ptr == request_buffer_end)
2738 {
2739 return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
2740 }
2741
2742 /* Set the URI pointer. */
2743 rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr = request_buffer_ptr;
2744
2745 /* Find the ending point of the URI. */
2746 while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr != ' ') &&
2747 (*request_buffer_ptr != '\r') && (*request_buffer_ptr != '\n'))
2748 {
2749 request_buffer_ptr++;
2750 }
2751
2752 /* Must has space before version. */
2753 if ((request_buffer_ptr == request_buffer_end) || (*request_buffer_ptr != ' '))
2754 {
2755 return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
2756 }
2757
2758 /* Calculate the URI length. */
2759 rtsp_client_request_ptr -> nx_rtsp_client_request_uri_length = (UINT)(request_buffer_ptr - rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr);
2760
2761 /* Trim the spaces. */
2762 while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr == ' '))
2763 {
2764 request_buffer_ptr++;
2765 }
2766
2767 /* Return error if no more data. */
2768 if (request_buffer_ptr == request_buffer_end)
2769 {
2770 return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
2771 }
2772
2773 /* Set the version pointer. */
2774 temp_ptr = request_buffer_ptr;
2775
2776 /* Find the ending point of the version. */
2777 while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr != ' ') &&
2778 (*request_buffer_ptr != '\r') && (*request_buffer_ptr != '\n'))
2779 {
2780 request_buffer_ptr++;
2781 }
2782
2783 /* Calculate version length. */
2784 temp_length = (UINT)(request_buffer_ptr - temp_ptr);
2785
2786 /* Check version. */
2787 if ((temp_length != (sizeof(NX_RTSP_VERSION_STRING) - 1)) ||
2788 memcmp(temp_ptr, NX_RTSP_VERSION_STRING, temp_length) != 0)
2789 {
2790 return(NX_RTSP_STATUS_CODE_RTSP_VERSION_NOT_SUPPORTED);
2791 }
2792
2793 /* Trim the spaces. */
2794 while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr == ' '))
2795 {
2796 request_buffer_ptr++;
2797 }
2798
2799 /* Move to next line. */
2800 /* RFC: https://www.rfc-editor.org/rfc/rfc2326#section-4
2801 Lines are terminated by CRLF, but receivers should be prepared
2802 to also interpret CR and LF by themselves as line terminators. */
2803 if (((request_buffer_ptr + 1) < request_buffer_end) &&
2804 (*request_buffer_ptr == '\r') && (*(request_buffer_ptr + 1) == '\n'))
2805 {
2806 request_buffer_ptr += 2;
2807 }
2808 else if ((request_buffer_ptr < request_buffer_end) &&
2809 ((*request_buffer_ptr == '\r') || (*request_buffer_ptr == '\n')))
2810 {
2811 request_buffer_ptr++;
2812 }
2813 else
2814 {
2815 return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
2816 }
2817
2818 *request_buffer = request_buffer_ptr;
2819
2820 /* Terminate the URI string. */
2821 *(rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr + rtsp_client_request_ptr -> nx_rtsp_client_request_uri_length) = NX_NULL;
2822
2823 return(NX_SUCCESS);
2824 }
2825
2826 /**************************************************************************/
2827 /* */
2828 /* FUNCTION RELEASE */
2829 /* */
2830 /* _nx_rtsp_server_request_header_parse PORTABLE C */
2831 /* 6.3.0 */
2832 /* AUTHOR */
2833 /* */
2834 /* Wenhui Xie, Microsoft Corporation */
2835 /* */
2836 /* DESCRIPTION */
2837 /* */
2838 /* This function parses headers in request packet. */
2839 /* */
2840 /* INPUT */
2841 /* */
2842 /* rtsp_client_ptr Pointer to RTSP client */
2843 /* rtsp_client_request_ptr Pointer to request structure */
2844 /* request_buffer Start of request buffer */
2845 /* request_buffer_end End to request buffer */
2846 /* */
2847 /* OUTPUT */
2848 /* */
2849 /* status Completion status */
2850 /* */
2851 /* CALLS */
2852 /* */
2853 /* _nx_rtsp_server_memicmp Compare two strings */
2854 /* _nx_utility_string_to_uint Convert string to integer */
2855 /* _nx_rtsp_server_strstr Search substring */
2856 /* */
2857 /* CALLED BY */
2858 /* */
2859 /* _nx_rtsp_server_request_parse */
2860 /* */
2861 /* RELEASE HISTORY */
2862 /* */
2863 /* DATE NAME DESCRIPTION */
2864 /* */
2865 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
2866 /* */
2867 /**************************************************************************/
_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)2868 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)
2869 {
2870 UCHAR *request_buffer_ptr;
2871 UCHAR *field_name_ptr;
2872 UCHAR *field_value_ptr;
2873 UINT field_name_length = 0;
2874 UINT field_value_length = 0;
2875 UINT port_length = 0;
2876 UINT status;
2877 NXD_ADDRESS *receiver_ip_address;
2878
2879
2880 /* Set the buffer pointer. */
2881 request_buffer_ptr = *request_buffer;
2882
2883 /* We assume the client request is well formatted. */
2884 /* Parse a header line. */
2885
2886 /* Trim the spaces. */
2887 while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr == ' '))
2888 {
2889 request_buffer_ptr++;
2890 }
2891
2892 if (request_buffer_ptr == request_buffer_end)
2893 {
2894
2895 /* Ignore empty line */
2896 return(NX_SUCCESS);
2897 }
2898
2899 /* Set the pointer of field name. */
2900 field_name_ptr = request_buffer_ptr;
2901
2902 /* Find the ending point of the header name. */
2903 while ((request_buffer_ptr < request_buffer_end) &&
2904 (*request_buffer_ptr != ':') && (*request_buffer_ptr != ' ') &&
2905 (*request_buffer_ptr != '\r') && (*request_buffer_ptr != '\n'))
2906 {
2907 request_buffer_ptr++;
2908 }
2909
2910 /* Calculate the length of the field name. */
2911 field_name_length = (UINT)(request_buffer_ptr - field_name_ptr);
2912
2913 if (field_name_length)
2914 {
2915
2916 /* Trim the colon and spaces. */
2917 while ((request_buffer_ptr < request_buffer_end) &&
2918 ((*request_buffer_ptr == ':') || (*request_buffer_ptr == ' ')))
2919 {
2920 request_buffer_ptr++;
2921 }
2922
2923 /* Set the pointer of the field value. */
2924 field_value_ptr = request_buffer_ptr;
2925
2926 /* Find the end of the field value. */
2927 while ((request_buffer_ptr < request_buffer_end) &&
2928 (*request_buffer_ptr != '\r') && (*request_buffer_ptr != '\n'))
2929 {
2930 request_buffer_ptr++;
2931 }
2932
2933 /* Calculate the length of the field value. */
2934 field_value_length = (UINT)(request_buffer_ptr - field_value_ptr);
2935
2936 if (_nx_rtsp_server_memicmp(field_name_ptr, field_name_length, NX_RTSP_SERVER_STRING_WITH_SIZE("cseq")) == NX_SUCCESS)
2937 {
2938
2939 /* Parse CSeq. */
2940
2941 /* Convert string to integer. */
2942 status = _nx_utility_string_to_uint((CHAR *)field_value_ptr, field_value_length, &(rtsp_client_request_ptr -> nx_rtsp_client_request_sequence_number));
2943 if (status)
2944 {
2945 return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
2946 }
2947 }
2948 else if (_nx_rtsp_server_memicmp(field_name_ptr, field_name_length, NX_RTSP_SERVER_STRING_WITH_SIZE("range")) == NX_SUCCESS)
2949 {
2950
2951 /* Parse Range. */
2952
2953 /* Set the range pointer and length. */
2954 rtsp_client_request_ptr -> nx_rtsp_client_request_range_ptr = field_value_ptr;
2955 rtsp_client_request_ptr -> nx_rtsp_client_request_range_length = field_value_length;
2956 }
2957 else if (_nx_rtsp_server_memicmp(field_name_ptr, field_name_length, NX_RTSP_SERVER_STRING_WITH_SIZE("session")) == NX_SUCCESS)
2958 {
2959
2960 /* Parse Session. */
2961
2962 /* Convert string to integer. */
2963 status = _nx_utility_string_to_uint((CHAR *)field_value_ptr, field_value_length, (UINT *)&(rtsp_client_request_ptr -> nx_rtsp_client_request_session_id));
2964 if (status)
2965 {
2966 return(status);
2967 }
2968 }
2969 else if (_nx_rtsp_server_memicmp(field_name_ptr, field_name_length, NX_RTSP_SERVER_STRING_WITH_SIZE("transport")) == NX_SUCCESS)
2970 {
2971
2972 /* Parse Transport. */
2973
2974 /* RTP/AVP/TCP is not supported. https://www.rfc-editor.org/rfc/rfc2326#section-10.4. */
2975 if (_nx_rtsp_server_strstr(field_value_ptr, field_value_length, NX_RTSP_SERVER_STRING_WITH_SIZE("RTP/AVP/TCP")))
2976 {
2977 rtsp_client_request_ptr -> nx_rtsp_client_request_transport.transport_type = NX_RTSP_TRANSPORT_TYPE_TCP;
2978 return(NX_RTSP_STATUS_CODE_UNSUPPORTED_TRANSPORT);
2979 }
2980 else
2981 {
2982 rtsp_client_request_ptr -> nx_rtsp_client_request_transport.transport_type = NX_RTSP_TRANSPORT_TYPE_UDP;
2983 }
2984
2985 receiver_ip_address = &(rtsp_client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_connect_ip);
2986
2987 /* Check multicast/unicast field. */
2988 if (_nx_rtsp_server_strstr(field_value_ptr, field_value_length, NX_RTSP_SERVER_STRING_WITH_SIZE("unicast")))
2989 {
2990
2991 /* For unicast mode, set the client IP address and return to user. */
2992 rtsp_client_request_ptr -> nx_rtsp_client_request_transport.transport_mode = NX_RTSP_TRANSPORT_MODE_UNICAST;
2993
2994 if (receiver_ip_address -> nxd_ip_version == NX_IP_VERSION_V4)
2995 {
2996 #ifndef NX_DISABLE_IPV4
2997 /* Set client IP address. */
2998 rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
2999 rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_ip_address.nxd_ip_address.v4 = receiver_ip_address -> nxd_ip_address.v4;
3000
3001 /* Set default server IP address. */
3002 rtsp_client_request_ptr -> nx_rtsp_client_request_transport.server_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
3003 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;
3004
3005 /* Record the transport ip interface in order to know where the packet is from. */
3006 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;
3007 #else
3008 return(NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED);
3009 #endif /* NX_DISABLE_IPV4 */
3010 }
3011 else if (receiver_ip_address -> nxd_ip_version == NX_IP_VERSION_V6)
3012 {
3013 #ifdef FEATURE_NX_IPV6
3014 /* Set client IP address. */
3015 rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
3016 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);
3017
3018 /* Set default server IP address. */
3019 rtsp_client_request_ptr -> nx_rtsp_client_request_transport.server_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
3020 COPY_IPV6_ADDRESS(rtsp_client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_ipv6_addr -> nxd_ipv6_address,
3021 rtsp_client_request_ptr -> nx_rtsp_client_request_transport.server_ip_address.nxd_ip_address.v6);
3022
3023 /* Record the transport ip interface in order to know where the packet is from. */
3024 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;
3025 #else
3026 return(NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED);
3027 #endif /* FEATURE_NX_IPV6 */
3028 }
3029 else
3030 {
3031 return(NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED);
3032 }
3033
3034 request_buffer_ptr = _nx_rtsp_server_strstr(field_value_ptr, field_value_length, NX_RTSP_SERVER_STRING_WITH_SIZE("client_port"));
3035 port_length = NX_RTSP_SERVER_STRING_SIZE("client_port");
3036 }
3037 else
3038 {
3039
3040 /* FIXME: Support that client chooses multicast address. Get destination field and convert to IP address. */
3041 if (_nx_rtsp_server_strstr(field_value_ptr, field_value_length, NX_RTSP_SERVER_STRING_WITH_SIZE("destination")) != NX_NULL)
3042 {
3043 rtsp_client_request_ptr -> nx_rtsp_client_request_transport.transport_mode = NX_RTSP_TRANSPORT_MODE_MULTICAST_CLIENT;
3044 return(NX_RTSP_STATUS_CODE_UNSUPPORTED_TRANSPORT);
3045 }
3046
3047 /* Set multicast mode and server will choose multicast address. */
3048 rtsp_client_request_ptr -> nx_rtsp_client_request_transport.transport_mode = NX_RTSP_TRANSPORT_MODE_MULTICAST_SERVER;
3049 request_buffer_ptr = _nx_rtsp_server_strstr(field_value_ptr, field_value_length, NX_RTSP_SERVER_STRING_WITH_SIZE("port"));
3050 port_length = NX_RTSP_SERVER_STRING_SIZE("port");
3051 }
3052
3053 /* Get client port pair. */
3054 if (request_buffer_ptr)
3055 {
3056
3057 /* Find the port value. */
3058 request_buffer_ptr = request_buffer_ptr + port_length;
3059 while ((request_buffer_ptr < request_buffer_end) &&
3060 ((*request_buffer_ptr == ' ') || (*request_buffer_ptr == '=')))
3061 {
3062 request_buffer_ptr++;
3063 }
3064
3065 /* Get pointer of the RTP port. */
3066 field_value_ptr = request_buffer_ptr;
3067
3068 while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr != '-') &&
3069 (*request_buffer_ptr != '\r') && (*request_buffer_ptr != '\n'))
3070 {
3071 request_buffer_ptr++;
3072 }
3073
3074 /* Check the format. */
3075 if (*request_buffer_ptr != '-')
3076 {
3077 return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
3078 }
3079
3080 /* Calculate the length of the RTP port. */
3081 field_value_length = (UINT)(request_buffer_ptr - field_value_ptr);
3082
3083 /* Convert string to integer. */
3084 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));
3085 if (status)
3086 {
3087 return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
3088 }
3089
3090 /* Get pointer of the RTCP port. */
3091 request_buffer_ptr++;
3092 field_value_ptr = request_buffer_ptr;
3093
3094 while ((request_buffer_ptr < request_buffer_end) && (*request_buffer_ptr != ';') &&
3095 (*request_buffer_ptr != '\r') && (*request_buffer_ptr != '\n'))
3096 {
3097 request_buffer_ptr++;
3098 }
3099
3100 /* Calculate the length of the RTCP port. */
3101 field_value_length = (UINT)(request_buffer_ptr - field_value_ptr);
3102
3103 /* Convert string to integer. */
3104 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));
3105 if (status)
3106 {
3107 return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
3108 }
3109 }
3110 else
3111 {
3112
3113 /* If no client port, move to the end of transport field. */
3114 request_buffer_ptr = field_value_ptr + field_value_length;
3115 }
3116 }
3117 }
3118
3119 /* Move to next line. */
3120 /* RFC: https://www.rfc-editor.org/rfc/rfc2326#section-4
3121 Lines are terminated by CRLF, but receivers should be prepared
3122 to also interpret CR and LF by themselves as line terminators. */
3123 if (((request_buffer_ptr + 1) < request_buffer_end) &&
3124 (*request_buffer_ptr == '\r') && (*(request_buffer_ptr + 1) == '\n'))
3125 {
3126
3127 /* Terminate the header line. */
3128 *request_buffer_ptr = NX_NULL;
3129 request_buffer_ptr += 2;
3130 }
3131 else if ((request_buffer_ptr < request_buffer_end) &&
3132 ((*request_buffer_ptr == '\r') || (*request_buffer_ptr == '\n')))
3133 {
3134
3135 /* Terminate the header line. */
3136 *request_buffer_ptr = NX_NULL;
3137 request_buffer_ptr++;
3138 }
3139 else
3140 {
3141 return(NX_RTSP_STATUS_CODE_BAD_REQUEST);
3142 }
3143
3144 *request_buffer = request_buffer_ptr;
3145
3146 return(NX_SUCCESS);
3147 }
3148
3149 /**************************************************************************/
3150 /* */
3151 /* FUNCTION RELEASE */
3152 /* */
3153 /* _nx_rtsp_server_memicmp PORTABLE C */
3154 /* 6.3.0 */
3155 /* AUTHOR */
3156 /* */
3157 /* Wenhui Xie, Microsoft Corporation */
3158 /* */
3159 /* DESCRIPTION */
3160 /* */
3161 /* This function compares two pieces of memory case insensitive. */
3162 /* */
3163 /* INPUT */
3164 /* */
3165 /* src Pointer to source */
3166 /* src_length Length of source */
3167 /* dest Pointer to destination */
3168 /* dest_length Length of destination */
3169 /* */
3170 /* OUTPUT */
3171 /* */
3172 /* status Completion status */
3173 /* */
3174 /* CALLS */
3175 /* */
3176 /* None */
3177 /* */
3178 /* CALLED BY */
3179 /* */
3180 /* _nx_rtsp_server_request_header_parse */
3181 /* _nx_rtsp_server_request_receive */
3182 /* _nx_rtsp_server_strstr */
3183 /* */
3184 /* RELEASE HISTORY */
3185 /* */
3186 /* DATE NAME DESCRIPTION */
3187 /* */
3188 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
3189 /* */
3190 /**************************************************************************/
_nx_rtsp_server_memicmp(UCHAR * src,ULONG src_length,UCHAR * dest,ULONG dest_length)3191 static UINT _nx_rtsp_server_memicmp(UCHAR *src, ULONG src_length, UCHAR *dest, ULONG dest_length)
3192 {
3193 UCHAR ch;
3194
3195
3196 /* Compare the length. */
3197 if(src_length != dest_length)
3198 return(NX_RTSP_SERVER_FAILED);
3199
3200 while(src_length)
3201 {
3202
3203 /* Is src lowercase? */
3204 if((*src >= 'a') && (*src <= 'z'))
3205 ch = (UCHAR)(*src - 'a' + 'A');
3206
3207 /* Is src uppercase? */
3208 else if((*src >= 'A') && (*src <= 'Z'))
3209 ch = (UCHAR)(*src - 'A' + 'a');
3210 else
3211 ch = *src;
3212
3213 /* Compare case insensitive. */
3214 if((*src != *dest) && (ch != *dest))
3215 return(NX_RTSP_SERVER_FAILED);
3216
3217 /* Pickup next character. */
3218 src_length--;
3219 src++;
3220 dest++;
3221 }
3222
3223 return(NX_SUCCESS);
3224 }
3225
3226 /**************************************************************************/
3227 /* */
3228 /* FUNCTION RELEASE */
3229 /* */
3230 /* _nx_rtsp_server_strstr PORTABLE C */
3231 /* 6.3.0 */
3232 /* AUTHOR */
3233 /* */
3234 /* Wenhui Xie, Microsoft Corporation */
3235 /* */
3236 /* DESCRIPTION */
3237 /* */
3238 /* This function searches the substring and returns the pointer. */
3239 /* */
3240 /* INPUT */
3241 /* */
3242 /* src Pointer to source */
3243 /* src_length Length of source */
3244 /* dest Pointer to destination */
3245 /* dest_length Length of destination */
3246 /* */
3247 /* OUTPUT */
3248 /* */
3249 /* pointer Pointer to the substring */
3250 /* */
3251 /* CALLS */
3252 /* */
3253 /* _nx_rtsp_server_memicmp Compare two strings */
3254 /* */
3255 /* CALLED BY */
3256 /* */
3257 /* _nx_rtsp_server_request_header_parse */
3258 /* */
3259 /* RELEASE HISTORY */
3260 /* */
3261 /* DATE NAME DESCRIPTION */
3262 /* */
3263 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
3264 /* */
3265 /**************************************************************************/
_nx_rtsp_server_strstr(UCHAR * src,ULONG src_length,UCHAR * dest,ULONG dest_length)3266 static UCHAR *_nx_rtsp_server_strstr(UCHAR *src, ULONG src_length, UCHAR *dest, ULONG dest_length)
3267 {
3268 UINT index = 0;
3269
3270
3271 /* Check the src and dest length. */
3272 if (src_length < dest_length)
3273 {
3274 return(NX_NULL);
3275 }
3276
3277 /* Loop to search the dest string. */
3278 while ((index + dest_length <= src_length) &&
3279 (_nx_rtsp_server_memicmp(src + index, dest_length, dest, dest_length) != NX_SUCCESS))
3280 {
3281 index++;
3282 }
3283
3284 /* Return the pointer. */
3285 if ((index + dest_length) <= src_length)
3286 {
3287 return(src + index);
3288 }
3289 else
3290 {
3291 return(NX_NULL);
3292 }
3293 }
3294
3295 /**************************************************************************/
3296 /* */
3297 /* FUNCTION RELEASE */
3298 /* */
3299 /* _nx_rtsp_server_response_create PORTABLE C */
3300 /* 6.3.0 */
3301 /* AUTHOR */
3302 /* */
3303 /* Wenhui Xie, Microsoft Corporation */
3304 /* */
3305 /* DESCRIPTION */
3306 /* */
3307 /* This function creates a response packet with common lines. */
3308 /* */
3309 /* INPUT */
3310 /* */
3311 /* rtsp_server_ptr Pointer to RTSP server */
3312 /* rtsp_client_ptr Pointer to RTSP client */
3313 /* rtsp_client_request_ptr Pointer to request structure */
3314 /* */
3315 /* OUTPUT */
3316 /* */
3317 /* status Completion status */
3318 /* */
3319 /* CALLS */
3320 /* */
3321 /* nx_packet_allocate Allocate a packet */
3322 /* nx_packet_data_append Append packet data */
3323 /* nx_packet_release Release the packet */
3324 /* _nx_utility_uint_to_string Convert integer to string */
3325 /* */
3326 /* CALLED BY */
3327 /* */
3328 /* _nx_rtsp_server_request_process */
3329 /* */
3330 /* RELEASE HISTORY */
3331 /* */
3332 /* DATE NAME DESCRIPTION */
3333 /* */
3334 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
3335 /* */
3336 /**************************************************************************/
_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)3337 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)
3338 {
3339 UINT status;
3340 CHAR temp_buffer[11];
3341 UINT temp_length;
3342
3343
3344 /* Allocate response packet. */
3345 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);
3346 if (status)
3347 {
3348 return(status);
3349 }
3350
3351 /* Generate the common response lines. */
3352
3353 /* Set default status as 200 OK. */
3354 status = nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, NX_RTSP_SERVER_STRING_WITH_SIZE(NX_RTSP_VERSION_STRING),
3355 rtsp_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
3356 status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, NX_RTSP_SERVER_STRING_WITH_SIZE(" 200 OK\r\n"),
3357 rtsp_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
3358
3359 /* Add "CSeq" header. */
3360 status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, NX_RTSP_SERVER_STRING_WITH_SIZE("CSeq: "),
3361 rtsp_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
3362 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));
3363 status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, temp_buffer, temp_length,
3364 rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
3365 status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n"),
3366 rtsp_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
3367
3368 /* Add "Server" header. */
3369 status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, NX_RTSP_SERVER_STRING_WITH_SIZE("Server: "),
3370 rtsp_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
3371 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,
3372 rtsp_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
3373 status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n"),
3374 rtsp_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
3375
3376 /* If the request method is PLAY, add RTP-Info header. */
3377 if (rtsp_client_request_ptr -> nx_rtsp_client_request_method == NX_RTSP_METHOD_PLAY)
3378 {
3379
3380 /* Add "RTP-Info" header. */
3381 status += nx_packet_data_append(rtsp_client_ptr -> nx_rtsp_client_response_packet, NX_RTSP_SERVER_STRING_WITH_SIZE("RTP-Info: "),
3382 rtsp_server_ptr -> nx_rtsp_server_packet_pool, NX_RTSP_SERVER_PACKET_TIMEOUT);
3383 }
3384
3385 /* Check if error occurs. */
3386 if (status)
3387 {
3388 nx_packet_release(rtsp_client_ptr -> nx_rtsp_client_response_packet);
3389 rtsp_client_ptr -> nx_rtsp_client_response_packet = NX_NULL;
3390 }
3391
3392 return(status);
3393 }
3394
3395 #ifdef FEATURE_NX_IPV6
3396 /**************************************************************************/
3397 /* */
3398 /* FUNCTION RELEASE */
3399 /* */
3400 /* _nx_rtsp_server_ipv6_address_to_string PORTABLE C */
3401 /* 6.3.0 */
3402 /* AUTHOR */
3403 /* */
3404 /* Haiqing Zhao, Microsoft Corporation */
3405 /* */
3406 /* DESCRIPTION */
3407 /* */
3408 /* This function converts an ipv6 address from ULONG array format into */
3409 /* standard ipv6 address string format. */
3410 /* */
3411 /* INPUT */
3412 /* */
3413 /* ipv6_addr Pointer to ULONG array address */
3414 /* buffer Pointer to output string buffer*/
3415 /* buffer_length Max length of output buffer */
3416 /* size Real size of output buffer */
3417 /* */
3418 /* OUTPUT */
3419 /* */
3420 /* status Completion status */
3421 /* */
3422 /* CALLS */
3423 /* */
3424 /* memset Reset memory */
3425 /* memcpy Copy data memory */
3426 /* */
3427 /* CALLED BY */
3428 /* */
3429 /* _nx_rtsp_server_response_send */
3430 /* */
3431 /* RELEASE HISTORY */
3432 /* */
3433 /* DATE NAME DESCRIPTION */
3434 /* */
3435 /* 10-31-2023 Haiqing Zhao Initial Version 6.3.0 */
3436 /* */
3437 /**************************************************************************/
_nx_rtsp_server_ipv6_address_to_string(ULONG * ipv6_addr,CHAR * buffer,UINT buffer_length,UINT * size)3438 static UINT _nx_rtsp_server_ipv6_address_to_string(ULONG *ipv6_addr, CHAR *buffer, UINT buffer_length, UINT *size)
3439 {
3440 UINT i, j;
3441 UCHAR c;
3442 ULONG val;
3443 CHAR *cur_pos = buffer;
3444
3445
3446 /* Check if the buffer is large enough to contain the ipv6 address in string format. An example ipv6 address string
3447 like "2001:0001:0002:0003:0004:0005:0006:1234" shows that 39 bytes data space is needed for the return buffer.
3448 Overall, the return buffer shall be 40 bytes to include the end '\0' for the output string. */
3449 if (buffer_length < 40)
3450 {
3451 return(NX_SIZE_ERROR);
3452 }
3453
3454 /* Go through each 4 ULONG values in ipv6 address. */
3455 for (i = 0; i < 4; i++)
3456 {
3457
3458 /* Get the current ULONG value. */
3459 val = ipv6_addr[i];
3460
3461 /* Go through each bit of the ULONG to convert. */
3462 for (j = 0; j <= 7; j++)
3463 {
3464
3465 /* Save the bit off the most significant end. */
3466 c = (UCHAR)((val & 0xF0000000) >> 28);
3467
3468 /* Make it the most significant byte. */
3469 val = val << 4;
3470
3471 /* Convert the digit to an ascii character. */
3472 if (c < 10)
3473 {
3474 *cur_pos = (CHAR)('0' + c);
3475 }
3476 else /* Handle HEX digits... */
3477 {
3478 *cur_pos = (CHAR)('A' + (c - 10));
3479 }
3480
3481 /* Move past the digit. */
3482 cur_pos++;
3483
3484 /* Determine if we need to add a colon. */
3485 if ((j == 3) || (j == 7))
3486 {
3487
3488 /* Yes, append the colon and move the pointer past it. */
3489 *cur_pos = ':';
3490 cur_pos++;
3491 }
3492 }
3493 }
3494
3495 /* Assign the last byte to make a complete string. */
3496 buffer[39] = '\0';
3497
3498 /* Assign a constant string size 39 as the returned real output buffer size. So far, the returned real size
3499 will always be 39 even if an example ipv6 address string is like "2004:0000:0000:0000:0000:0000:0000:0001"
3500 since ipv6 abbreviation expression is not supported. */
3501 *size = 39;
3502
3503 return(NX_SUCCESS);
3504 }
3505 #endif /* FEATURE_NX_IPV6 */
3506
3507 /**************************************************************************/
3508 /* */
3509 /* FUNCTION RELEASE */
3510 /* */
3511 /* _nx_rtsp_server_response_send PORTABLE C */
3512 /* 6.3.0 */
3513 /* AUTHOR */
3514 /* */
3515 /* Wenhui Xie, Microsoft Corporation */
3516 /* */
3517 /* DESCRIPTION */
3518 /* */
3519 /* This function sends the response to the client. */
3520 /* */
3521 /* INPUT */
3522 /* */
3523 /* rtsp_server_ptr Pointer to RTSP server */
3524 /* rtsp_client_ptr Pointer to RTSP client */
3525 /* rtsp_client_request_ptr Pointer to request structure */
3526 /* */
3527 /* OUTPUT */
3528 /* */
3529 /* status Completion status */
3530 /* */
3531 /* CALLS */
3532 /* */
3533 /* nx_packet_data_append Append packet data */
3534 /* _nx_utility_uint_to_string Convert integer to string */
3535 /* nx_packet_release Release the packet */
3536 /* nx_tcp_socket_send Send TCP packet */
3537 /* */
3538 /* CALLED BY */
3539 /* */
3540 /* _nx_rtsp_server_request_process */
3541 /* */
3542 /* RELEASE HISTORY */
3543 /* */
3544 /* DATE NAME DESCRIPTION */
3545 /* */
3546 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
3547 /* */
3548 /**************************************************************************/
_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)3549 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)
3550 {
3551 UINT status = NX_SUCCESS;
3552 #ifdef FEATURE_NX_IPV6
3553 CHAR temp_buffer[40]; /* The size for buffer to store an IPv6 address represented in ASCII. */
3554 #else
3555 CHAR temp_buffer[11];
3556 #endif /* FEATURE_NX_IPV6 */
3557 UINT temp_length;
3558 NX_PACKET *temp_packet_ptr;
3559 NX_PACKET *response_packet_ptr = rtsp_client_ptr -> nx_rtsp_client_response_packet;
3560 NX_PACKET_POOL *pool_ptr = rtsp_client_ptr -> nx_rtsp_client_server_ptr -> nx_rtsp_server_packet_pool;
3561 NXD_ADDRESS *source_ip_address;
3562
3563 if (!response_packet_ptr)
3564 {
3565 return(NX_RTSP_SERVER_NO_PACKET);
3566 }
3567
3568 switch (rtsp_client_request_ptr -> nx_rtsp_client_request_method)
3569 {
3570 case NX_RTSP_METHOD_OPTIONS:
3571 {
3572
3573 /* Always support "OPTIONS, SETUP, PLAY, TEARDOWN". */
3574 status = nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("Public: OPTIONS, SETUP, PLAY, TEARDOWN"),
3575 pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3576
3577 /* Check if other methods are supported. */
3578 if (rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_describe_callback != NX_NULL)
3579 {
3580 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(", DESCRIBE"),
3581 pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3582 }
3583
3584 if (rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_pause_callback != NX_NULL)
3585 {
3586 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(", PAUSE"),
3587 pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3588 }
3589
3590 if (rtsp_server_ptr -> nx_rtsp_server_method_callbacks.nx_rtsp_server_method_set_parameter_callback != NX_NULL)
3591 {
3592 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(", SET_PARAMETER"),
3593 pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3594 }
3595
3596 /* Add terminators. */
3597 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n\r\n"),
3598 pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3599
3600 break;
3601 }
3602 case NX_RTSP_METHOD_DESCRIBE:
3603 {
3604
3605 /* The details in DESCRIBE method are fulfilled in the function _nx_rtsp_server_sdp_set
3606 which is normally called in the function nx_rtsp_server_method_describe_callback.
3607 So, directly break here in order to skip adding terminators in the default branch. */
3608 break;
3609 }
3610 case NX_RTSP_METHOD_SETUP:
3611 {
3612
3613 /* Add "Session" header. */
3614 status = nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("Session: "),
3615 pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3616 temp_length = _nx_utility_uint_to_string(rtsp_client_ptr -> nx_rtsp_client_session_id, 10, temp_buffer, sizeof(temp_buffer));
3617 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3618 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(";timeout="),
3619 pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3620 temp_length = _nx_utility_uint_to_string(NX_RTSP_SERVER_ACTIVITY_TIMEOUT, 10, temp_buffer, sizeof(temp_buffer));
3621 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3622
3623 /* Add "Transport" header. */
3624 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\nTransport: RTP/AVP;"),
3625 pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3626
3627 /* Add unicast/multicast start words. */
3628 if (rtsp_client_request_ptr -> nx_rtsp_client_request_transport.transport_mode == NX_RTSP_TRANSPORT_MODE_UNICAST)
3629 {
3630 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("unicast;source="),
3631 pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3632
3633 source_ip_address = &(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.server_ip_address);
3634 }
3635 else
3636 {
3637 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("multicast;destination="),
3638 pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3639
3640 source_ip_address = &(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_ip_address);
3641 }
3642
3643 /* Add source/destination IP address. */
3644 if (rtsp_client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V4)
3645 {
3646 #ifndef NX_DISABLE_IPV4
3647 temp_length = _nx_utility_uint_to_string(source_ip_address -> nxd_ip_address.v4 >> 24, 10, temp_buffer, sizeof(temp_buffer));
3648 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3649 status += nx_packet_data_append(response_packet_ptr, ".", 1, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3650 temp_length = _nx_utility_uint_to_string((source_ip_address -> nxd_ip_address.v4 >> 16) & 0xFF, 10, temp_buffer, sizeof(temp_buffer));
3651 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3652 status += nx_packet_data_append(response_packet_ptr, ".", 1, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3653 temp_length = _nx_utility_uint_to_string((source_ip_address -> nxd_ip_address.v4 >> 8) & 0xFF, 10, temp_buffer, sizeof(temp_buffer));
3654 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3655 status += nx_packet_data_append(response_packet_ptr, ".", 1, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3656 temp_length = _nx_utility_uint_to_string((source_ip_address -> nxd_ip_address.v4) & 0xFF, 10, temp_buffer, sizeof(temp_buffer));
3657 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3658 #else
3659 status = NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED;
3660 break;
3661 #endif /* NX_DISABLE_IPV4 */
3662 }
3663 else if (rtsp_client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
3664 {
3665 #ifdef FEATURE_NX_IPV6
3666 _nx_rtsp_server_ipv6_address_to_string(source_ip_address -> nxd_ip_address.v6, temp_buffer, sizeof(temp_buffer), &temp_length);
3667 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3668 #else
3669 status = NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED;
3670 break;
3671 #endif /* FEATURE_NX_IPV6 */
3672 }
3673
3674 if (rtsp_client_request_ptr -> nx_rtsp_client_request_transport.transport_mode == NX_RTSP_TRANSPORT_MODE_UNICAST)
3675 {
3676 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(";client_port="), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3677 temp_length = _nx_utility_uint_to_string(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_rtp_port,
3678 10, temp_buffer, sizeof(temp_buffer));
3679 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3680 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("-"), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3681 temp_length = _nx_utility_uint_to_string(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_rtcp_port,
3682 10, temp_buffer, sizeof(temp_buffer));
3683 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3684
3685 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(";server_port="), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3686 temp_length = _nx_utility_uint_to_string(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.server_rtp_port,
3687 10, temp_buffer, sizeof(temp_buffer));
3688 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3689 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("-"), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3690 temp_length = _nx_utility_uint_to_string(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.server_rtcp_port,
3691 10, temp_buffer, sizeof(temp_buffer));
3692 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3693
3694 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(";ssrc="), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3695 temp_length = _nx_utility_uint_to_string(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.rtp_ssrc,
3696 10, temp_buffer, sizeof(temp_buffer));
3697 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3698 }
3699 else
3700 {
3701 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(";port="), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3702 temp_length = _nx_utility_uint_to_string(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_rtp_port,
3703 10, temp_buffer, sizeof(temp_buffer));
3704 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3705 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("-"), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3706 temp_length = _nx_utility_uint_to_string(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_rtcp_port,
3707 10, temp_buffer, sizeof(temp_buffer));
3708 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3709
3710 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(";ttl="), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3711 temp_length = _nx_utility_uint_to_string(rtsp_client_request_ptr -> nx_rtsp_client_request_transport.multicast_ttl,
3712 10, temp_buffer, sizeof(temp_buffer));
3713 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3714 }
3715
3716 /* Add terminators. */
3717 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n\r\n"),
3718 pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3719
3720 break;
3721 }
3722 case NX_RTSP_METHOD_PLAY:
3723 {
3724
3725 /* If user has called nx_rtsp_server_rtp_info_set to set RTP-Info field,
3726 there is an extra character ',' appended to the end of the packet. */
3727 temp_packet_ptr = response_packet_ptr;
3728
3729 #ifndef NX_DISABLE_PACKET_CHAIN
3730 /* If the packet is chained, move to the last packet. */
3731 if (response_packet_ptr -> nx_packet_last)
3732 {
3733 temp_packet_ptr = response_packet_ptr -> nx_packet_last;
3734 }
3735 #endif /* NX_DISABLE_PACKET_CHAIN */
3736
3737 /* Remove the last character ','. */
3738 if (*(temp_packet_ptr -> nx_packet_append_ptr - 1) == ',')
3739 {
3740 temp_packet_ptr -> nx_packet_append_ptr--;
3741 temp_packet_ptr -> nx_packet_length--;
3742 }
3743
3744 /* Add terminators. */
3745 status = nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n"),
3746 pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3747 }
3748 /* fallthrough */
3749 case NX_RTSP_METHOD_PAUSE:
3750 {
3751 if ((rtsp_client_request_ptr -> nx_rtsp_client_request_method == NX_RTSP_METHOD_PLAY) ||
3752 (rtsp_client_ptr -> nx_rtsp_client_npt_start) || (rtsp_client_ptr -> nx_rtsp_client_npt_end))
3753 {
3754
3755 /* Add "Range" header. */
3756 status = nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("Range: npt="),
3757 pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3758 temp_length = _nx_utility_uint_to_string((rtsp_client_ptr -> nx_rtsp_client_npt_start / 1000), 10, temp_buffer, sizeof(temp_buffer));
3759 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3760 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("."), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3761 temp_length = _nx_utility_uint_to_string((rtsp_client_ptr -> nx_rtsp_client_npt_start % 1000), 10, temp_buffer, sizeof(temp_buffer));
3762 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3763 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("-"), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3764
3765 if (rtsp_client_ptr -> nx_rtsp_client_npt_end)
3766 {
3767 temp_length = _nx_utility_uint_to_string((rtsp_client_ptr -> nx_rtsp_client_npt_end / 1000), 10, temp_buffer, sizeof(temp_buffer));
3768 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3769 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("."), pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3770 temp_length = _nx_utility_uint_to_string((rtsp_client_ptr -> nx_rtsp_client_npt_end % 1000), 10, temp_buffer, sizeof(temp_buffer));
3771 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3772 }
3773
3774 /* Add terminators. */
3775 status = nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n"),
3776 pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3777 }
3778
3779 /* Add "Session" header. */
3780 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("Session: "),
3781 pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3782 temp_length = _nx_utility_uint_to_string(rtsp_client_ptr -> nx_rtsp_client_session_id, 10, temp_buffer, sizeof(temp_buffer));
3783 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3784 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE(";timeout="),
3785 pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3786 temp_length = _nx_utility_uint_to_string(NX_RTSP_SERVER_ACTIVITY_TIMEOUT, 10, temp_buffer, sizeof(temp_buffer));
3787 status += nx_packet_data_append(response_packet_ptr, temp_buffer, temp_length, pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3788
3789 /* Add terminators. */
3790 status += nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n\r\n"),
3791 pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3792
3793 break;
3794 }
3795 default:
3796 {
3797
3798 /* Add terminators. */
3799 status = nx_packet_data_append(response_packet_ptr, NX_RTSP_SERVER_STRING_WITH_SIZE("\r\n"),
3800 pool_ptr, NX_RTSP_SERVER_PACKET_TIMEOUT);
3801
3802 break;
3803 }
3804 }
3805
3806 if (status == NX_SUCCESS)
3807 {
3808
3809 /* Send the response message back. */
3810 status = nx_tcp_socket_send(&rtsp_client_ptr -> nx_rtsp_client_socket, response_packet_ptr, NX_RTSP_SERVER_SEND_TIMEOUT);
3811 }
3812
3813 /* Determine if the send was unsuccessful. */
3814 if (status)
3815 {
3816
3817 /* Release the packet. */
3818 nx_packet_release(response_packet_ptr);
3819 }
3820
3821 /* Clear the response packet pointer. */
3822 rtsp_client_ptr -> nx_rtsp_client_response_packet = NX_NULL;
3823
3824 return(status);
3825 }
3826
3827 /**************************************************************************/
3828 /* */
3829 /* FUNCTION RELEASE */
3830 /* */
3831 /* _nx_rtsp_server_request_process PORTABLE C */
3832 /* 6.3.0 */
3833 /* AUTHOR */
3834 /* */
3835 /* Wenhui Xie, Microsoft Corporation */
3836 /* */
3837 /* DESCRIPTION */
3838 /* */
3839 /* This function processes RTSP requests. */
3840 /* */
3841 /* INPUT */
3842 /* */
3843 /* rtsp_server_ptr Pointer to RTSP server */
3844 /* */
3845 /* OUTPUT */
3846 /* */
3847 /* status Completion status */
3848 /* */
3849 /* CALLS */
3850 /* */
3851 /* _nx_rtsp_server_request_receive Receive client request */
3852 /* _nx_rtsp_server_request_parse Parse client request */
3853 /* _nx_rtsp_server_response_create Create common response */
3854 /* _nx_rtsp_server_error_response_send Send error response */
3855 /* _nx_rtsp_server_response_send Send common response */
3856 /* nx_packet_release Release the packet */
3857 /* */
3858 /* CALLED BY */
3859 /* */
3860 /* _nx_rtsp_server_thread_entry */
3861 /* */
3862 /* RELEASE HISTORY */
3863 /* */
3864 /* DATE NAME DESCRIPTION */
3865 /* */
3866 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
3867 /* */
3868 /**************************************************************************/
_nx_rtsp_server_request_process(NX_RTSP_SERVER * rtsp_server_ptr)3869 static VOID _nx_rtsp_server_request_process(NX_RTSP_SERVER *rtsp_server_ptr)
3870 {
3871 UINT i;
3872 UINT status;
3873 NX_RTSP_CLIENT *rtsp_client_ptr;
3874 NX_RTSP_SERVER_METHOD_CALLBACKS method_callbacks = rtsp_server_ptr -> nx_rtsp_server_method_callbacks;
3875
3876
3877 /* Now look for a socket that has receive data. */
3878 for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
3879 {
3880
3881 /* Setup pointer to client structure. */
3882 rtsp_client_ptr = &(rtsp_server_ptr -> nx_rtsp_server_client_list[i]);
3883
3884 /* Now see if this socket has data. */
3885 if (rtsp_client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_receive_queue_count)
3886 {
3887
3888 /* Attempt to read a packet from this socket. */
3889 status = _nx_rtsp_server_request_receive(rtsp_server_ptr, rtsp_client_ptr);
3890
3891 /* Check for no data present. */
3892 if (status != NX_SUCCESS)
3893 {
3894
3895 /* Just continue the loop and look at the next socket. */
3896 continue;
3897 }
3898
3899 /* Reset the client request activity timeout. */
3900 rtsp_client_ptr -> nx_rtsp_client_request_activity_timeout = NX_RTSP_SERVER_ACTIVITY_TIMEOUT;
3901
3902 /* Set the pointer to the current Client request. */
3903 rtsp_client_ptr -> nx_rtsp_client_request_ptr = &(rtsp_client_ptr -> nx_rtsp_client_request);
3904
3905 /* Parse the client request. */
3906 status = _nx_rtsp_server_request_parse(rtsp_client_ptr, rtsp_client_ptr -> nx_rtsp_client_request_ptr);
3907
3908 /* Check for error status. */
3909 if (status != NX_SUCCESS)
3910 {
3911
3912 /* Release the request packet. */
3913 nx_packet_release(rtsp_client_ptr -> nx_rtsp_client_request_packet);
3914 rtsp_client_ptr -> nx_rtsp_client_request_packet = NX_NULL;
3915 rtsp_client_ptr -> nx_rtsp_client_request_bytes_total = 0;
3916
3917 /* Clear the pointer of Client request. */
3918 rtsp_client_ptr -> nx_rtsp_client_request_ptr = NX_NULL;
3919
3920 /* Just continue the loop and look at the next socket. */
3921 continue;
3922 }
3923
3924 /* Create the response packet. */
3925 status = _nx_rtsp_server_response_create(rtsp_server_ptr, rtsp_client_ptr, rtsp_client_ptr -> nx_rtsp_client_request_ptr);
3926
3927 /* Packet allocation failure. */
3928 if (status != NX_SUCCESS)
3929 {
3930
3931 /* There is nothing we can do here. Ideally log this error event. */
3932 rtsp_server_ptr -> nx_rtsp_server_allocation_errors++;
3933
3934 /* Release the request packet. */
3935 nx_packet_release(rtsp_client_ptr -> nx_rtsp_client_request_packet);
3936 rtsp_client_ptr -> nx_rtsp_client_request_packet = NX_NULL;
3937 rtsp_client_ptr -> nx_rtsp_client_request_bytes_total = 0;
3938
3939 /* Clear the pointer of Client request. */
3940 rtsp_client_ptr -> nx_rtsp_client_request_ptr = NX_NULL;
3941
3942 /* At this point, just continue the loop and look at the next socket. */
3943 continue;
3944 }
3945
3946 /* Set default response status code to 200 OK. */
3947 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_OK;
3948
3949 switch (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_method)
3950 {
3951 case NX_RTSP_METHOD_OPTIONS:
3952 {
3953
3954 /* OPTIONS is always allowed and supported. */
3955 break;
3956 }
3957 case NX_RTSP_METHOD_DESCRIBE:
3958 {
3959 if (method_callbacks.nx_rtsp_server_method_describe_callback == NX_NULL)
3960 {
3961
3962 /* Method not installed, so we return "method not supported". */
3963 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED;
3964
3965 break;
3966 }
3967
3968 /* Invoke the actual callback routine. */
3969 status = method_callbacks.nx_rtsp_server_method_describe_callback
3970 (rtsp_client_ptr,
3971 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr,
3972 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_length);
3973
3974 if (status != NX_SUCCESS)
3975 {
3976
3977 /* Internal error occurs. */
3978 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_INTERNAL_SERVER_ERROR;
3979 }
3980
3981 break;
3982 }
3983 case NX_RTSP_METHOD_SETUP:
3984 {
3985
3986 /* The callbacks for SETUP, PLAY and TEARDOWN are required to be set and
3987 we have checked this in _nx_rtsp_server_start() function. */
3988
3989 /* If session ID is present, we need to verify session ID. */
3990 if (rtsp_client_ptr -> nx_rtsp_client_session_id &&
3991 (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_session_id != rtsp_client_ptr -> nx_rtsp_client_session_id))
3992 {
3993
3994 /* Session not found. */
3995 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
3996 break;
3997 }
3998
3999 if (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr == NX_NULL)
4000 {
4001
4002 /* No media specified in the request. Invalid case. */
4003 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
4004 break;
4005 }
4006 else if ((rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_transport.transport_mode == NX_RTSP_TRANSPORT_MODE_UNICAST) &&
4007 ((rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_rtp_port == 0) ||
4008 (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_transport.client_rtcp_port == 0)))
4009 {
4010
4011 /* Invalid client port. */
4012 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_UNSUPPORTED_TRANSPORT;
4013 break;
4014 }
4015
4016 status = method_callbacks.nx_rtsp_server_method_setup_callback
4017 (rtsp_client_ptr,
4018 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr,
4019 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_length,
4020 &(rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_transport));
4021
4022 /* If callback returns "SUCCESS". */
4023 if (status == NX_SUCCESS)
4024 {
4025 if (rtsp_client_ptr -> nx_rtsp_client_state == NX_RTSP_STATE_INIT)
4026 {
4027
4028 /* Set client state to ready. */
4029 rtsp_client_ptr -> nx_rtsp_client_state = NX_RTSP_STATE_READY;
4030 }
4031
4032 if (rtsp_client_ptr -> nx_rtsp_client_session_id == 0)
4033 {
4034
4035 /* Remember the session ID for future validation. */
4036 rtsp_client_ptr -> nx_rtsp_client_session_id = (ULONG)NX_RAND();
4037 }
4038 }
4039 else
4040 {
4041
4042 /* Internal error occurs. */
4043 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_INTERNAL_SERVER_ERROR;
4044 }
4045
4046 break;
4047 }
4048 case NX_RTSP_METHOD_PLAY:
4049 {
4050
4051 /* The callbacks for SETUP, PLAY and TEARDOWN are required to be set and
4052 we have checked this in _nx_rtsp_server_start() function. */
4053
4054 if (!(rtsp_client_ptr -> nx_rtsp_client_session_id) ||
4055 (rtsp_client_ptr -> nx_rtsp_client_session_id != rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_session_id))
4056 {
4057
4058 /* Session not found. */
4059 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
4060
4061 break;
4062 }
4063
4064 if (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr == NX_NULL)
4065 {
4066
4067 /* No media specified in the request. Invalid case. */
4068 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
4069 break;
4070 }
4071
4072 /* Reset the npt start and end time. */
4073 rtsp_client_ptr -> nx_rtsp_client_npt_start = 0;
4074 rtsp_client_ptr -> nx_rtsp_client_npt_end = 0;
4075
4076 status = method_callbacks.nx_rtsp_server_method_play_callback
4077 (rtsp_client_ptr,
4078 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr,
4079 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_length,
4080 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_range_ptr,
4081 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_range_length);
4082
4083 /* If callback returns "SUCCESS". */
4084 if (status == NX_SUCCESS)
4085 {
4086
4087 /* Set client state to playing. */
4088 rtsp_client_ptr -> nx_rtsp_client_state = NX_RTSP_STATE_PLAYING;
4089 }
4090 else
4091 {
4092
4093 /* Internal error occurs. */
4094 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_INTERNAL_SERVER_ERROR;
4095 }
4096
4097 break;
4098 }
4099 case NX_RTSP_METHOD_PAUSE:
4100 {
4101 if (method_callbacks.nx_rtsp_server_method_pause_callback == NX_NULL)
4102 {
4103
4104 /* Method not installed, so we return "method not supported". */
4105 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED;
4106
4107 break;
4108 }
4109
4110 /* Validate Session ID. */
4111 if (!(rtsp_client_ptr -> nx_rtsp_client_session_id) ||
4112 (rtsp_client_ptr -> nx_rtsp_client_session_id != rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_session_id))
4113 {
4114
4115 /* Session not found. */
4116 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
4117
4118 break;
4119 }
4120
4121 if (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr == NX_NULL)
4122 {
4123
4124 /* No media specified in the request. Invalid case. */
4125 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
4126 break;
4127 }
4128
4129 /* Reset the npt start and end time. */
4130 rtsp_client_ptr -> nx_rtsp_client_npt_start = 0;
4131 rtsp_client_ptr -> nx_rtsp_client_npt_end = 0;
4132
4133 status = method_callbacks.nx_rtsp_server_method_pause_callback
4134 (rtsp_client_ptr,
4135 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr,
4136 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_length,
4137 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_range_ptr,
4138 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_range_length);
4139
4140 /* If callback returns "SUCCESS". */
4141 if (status == NX_SUCCESS)
4142 {
4143
4144 /* Set client state to ready. */
4145 rtsp_client_ptr -> nx_rtsp_client_state = NX_RTSP_STATE_READY;
4146 }
4147 else
4148 {
4149
4150 /* Internal error occurs. */
4151 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_INTERNAL_SERVER_ERROR;
4152 }
4153
4154 break;
4155 }
4156 case NX_RTSP_METHOD_TEARDOWN:
4157 {
4158
4159 /* The callbacks for SETUP, PLAY and TEARDOWN are required to be set and
4160 we have checked this in _nx_rtsp_server_start() function. */
4161
4162 /* Validate session ID. */
4163 if (!(rtsp_client_ptr -> nx_rtsp_client_session_id) ||
4164 (rtsp_client_ptr -> nx_rtsp_client_session_id != rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_session_id))
4165 {
4166
4167 /* Session not found. */
4168 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
4169
4170 break;
4171 }
4172
4173 if (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr == NX_NULL)
4174 {
4175
4176 /* No media specified in the request. Invalid case. */
4177 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
4178 break;
4179 }
4180
4181 status = method_callbacks.nx_rtsp_server_method_teardown_callback
4182 (rtsp_client_ptr,
4183 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr,
4184 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_length);
4185
4186
4187 /* If got positive response from media handler. */
4188 if (status == NX_SUCCESS)
4189 {
4190
4191 /* Set client state to init. */
4192 rtsp_client_ptr -> nx_rtsp_client_state = NX_RTSP_STATE_INIT;
4193
4194 /* Clear the session ID. */
4195 rtsp_client_ptr -> nx_rtsp_client_session_id = 0;
4196 }
4197 else
4198 {
4199
4200 /* Internal error occurs. */
4201 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_INTERNAL_SERVER_ERROR;
4202 }
4203
4204 break;
4205 }
4206 case NX_RTSP_METHOD_SET_PARAMETER:
4207 {
4208 if (method_callbacks.nx_rtsp_server_method_set_parameter_callback == NULL)
4209 {
4210
4211 /* Method not installed, so we return "method not supported". */
4212 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED;
4213
4214 break;
4215 }
4216
4217 /* Validate session ID. */
4218 if (!(rtsp_client_ptr -> nx_rtsp_client_session_id) ||
4219 (rtsp_client_ptr -> nx_rtsp_client_session_id != rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_session_id))
4220 {
4221
4222 /* Session not found. */
4223 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
4224
4225 break;
4226 }
4227
4228 if (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr == NX_NULL)
4229 {
4230
4231 /* No media specified in the request. Invalid case. */
4232 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_SESSION_NOT_FOUND;
4233 break;
4234 }
4235
4236 status = method_callbacks.nx_rtsp_server_method_set_parameter_callback
4237 (rtsp_client_ptr,
4238 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_ptr,
4239 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_uri_length,
4240 (rtsp_client_ptr -> nx_rtsp_client_request_packet -> nx_packet_append_ptr - rtsp_client_ptr -> nx_rtsp_client_request_content_length),
4241 rtsp_client_ptr -> nx_rtsp_client_request_content_length);
4242
4243 /* If callback returns "SUCCESS". */
4244 if (status)
4245 {
4246
4247 /* Internal error occurs. */
4248 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_INTERNAL_SERVER_ERROR;
4249 }
4250
4251 break;
4252 }
4253 default:
4254 {
4255
4256 /* Method not installed, so we return "NOT IMPLEMENTED". */
4257 rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code = NX_RTSP_STATUS_CODE_NOT_IMPLEMENTED;
4258
4259 break;
4260 }
4261 }
4262
4263 /* Send the response. */
4264 if (rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code >= 300)
4265 {
4266
4267 /* Handle error response. */
4268 _nx_rtsp_server_error_response_send(rtsp_client_ptr, rtsp_client_ptr -> nx_rtsp_client_request_ptr -> nx_rtsp_client_request_response_code);
4269 }
4270 else
4271 {
4272 _nx_rtsp_server_response_send(rtsp_server_ptr, rtsp_client_ptr, rtsp_client_ptr -> nx_rtsp_client_request_ptr);
4273 }
4274
4275 /* Release the request packet. */
4276 nx_packet_release(rtsp_client_ptr -> nx_rtsp_client_request_packet);
4277 rtsp_client_ptr -> nx_rtsp_client_request_packet = NX_NULL;
4278 rtsp_client_ptr -> nx_rtsp_client_request_bytes_total = 0;
4279
4280 /* Clear the pointer of Client request. */
4281 rtsp_client_ptr -> nx_rtsp_client_request_ptr = NX_NULL;
4282 }
4283 }
4284 }
4285
4286 /**************************************************************************/
4287 /* */
4288 /* FUNCTION RELEASE */
4289 /* */
4290 /* _nx_rtsp_server_connect_process PORTABLE C */
4291 /* 6.3.0 */
4292 /* AUTHOR */
4293 /* */
4294 /* Wenhui Xie, Microsoft Corporation */
4295 /* */
4296 /* DESCRIPTION */
4297 /* */
4298 /* This function processes connections for multiple sessions. */
4299 /* */
4300 /* INPUT */
4301 /* */
4302 /* rtsp_server_ptr Pointer to RTSP server */
4303 /* */
4304 /* OUTPUT */
4305 /* */
4306 /* None */
4307 /* */
4308 /* CALLS */
4309 /* */
4310 /* nx_tcp_server_socket_accept Accept incoming TCP request */
4311 /* nx_tcp_server_socket_unaccept Clear accepted socket */
4312 /* nx_tcp_server_socket_relisten Re-listen on free socket */
4313 /* */
4314 /* CALLED BY */
4315 /* */
4316 /* _nx_rtsp_server_thread_entry */
4317 /* */
4318 /* RELEASE HISTORY */
4319 /* */
4320 /* DATE NAME DESCRIPTION */
4321 /* */
4322 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
4323 /* */
4324 /**************************************************************************/
_nx_rtsp_server_connect_process(NX_RTSP_SERVER * rtsp_server_ptr)4325 static VOID _nx_rtsp_server_connect_process(NX_RTSP_SERVER *rtsp_server_ptr)
4326 {
4327 UINT i;
4328 UINT status;
4329 NX_RTSP_CLIENT *client_ptr;
4330
4331
4332 /* One of the control ports is in the processing of connection.
4333 Search the connections to see which one. */
4334 for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
4335 {
4336
4337 /* Setup pointer to client structure. */
4338 client_ptr = &(rtsp_server_ptr -> nx_rtsp_server_client_list[i]);
4339
4340 /* Now see if this socket was the one that is in being connected. */
4341 if ((client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_state > NX_TCP_CLOSED) &&
4342 (client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_state < NX_TCP_ESTABLISHED) &&
4343 (client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_connect_port))
4344 {
4345
4346 /* Yes, we have found the socket being connected. */
4347
4348 /* Attempt to accept on this socket. */
4349 status = nx_tcp_server_socket_accept(&(client_ptr -> nx_rtsp_client_socket), NX_RTSP_SERVER_ACCEPT_TIMEOUT);
4350
4351 /* Determine if it is successful. */
4352 if (status)
4353 {
4354
4355 /* Not successful, simply unaccept on this socket. */
4356 nx_tcp_server_socket_unaccept(&(client_ptr -> nx_rtsp_client_socket));
4357 }
4358 else
4359 {
4360
4361 /* Reset the client request activity timeout. */
4362 client_ptr -> nx_rtsp_client_request_activity_timeout = NX_RTSP_SERVER_ACTIVITY_TIMEOUT;
4363
4364 /* Set the client as valid. */
4365 client_ptr -> nx_rtsp_client_valid = NX_TRUE;
4366
4367 /* Store the RTSP server pointer. */
4368 client_ptr -> nx_rtsp_client_server_ptr = rtsp_server_ptr;
4369
4370 /* Update the connected client count. */
4371 rtsp_server_ptr -> nx_rtsp_server_connected_client_count++;
4372 }
4373
4374 /* In any case break out of the loop when we find a connection - there can only be one
4375 at a time! */
4376 break;
4377 }
4378 }
4379
4380 /* Now look for a client that is valid to relisten on. */
4381 for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
4382 {
4383
4384 /* Setup pointer to client request structure. */
4385 client_ptr = &(rtsp_server_ptr -> nx_rtsp_server_client_list[i]);
4386
4387 /* Now see if this socket is closed. */
4388 if ((client_ptr -> nx_rtsp_client_valid == NX_FALSE) &&
4389 (client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_state == NX_TCP_CLOSED))
4390 {
4391
4392 /* Relisten on this socket. */
4393 status = nx_tcp_server_socket_relisten(rtsp_server_ptr -> nx_rtsp_server_ip_ptr, rtsp_server_ptr -> nx_rtsp_server_port,
4394 &(client_ptr -> nx_rtsp_client_socket));
4395
4396 /* Check for bad status. */
4397 if ((status != NX_SUCCESS) && (status != NX_CONNECTION_PENDING))
4398 {
4399
4400 /* Increment the error count and keep trying. */
4401 rtsp_server_ptr -> nx_rtsp_server_relisten_errors++;
4402 continue;
4403 }
4404
4405 /* Break out of loop. */
4406 break;
4407 }
4408 }
4409 }
4410
4411 /**************************************************************************/
4412 /* */
4413 /* FUNCTION RELEASE */
4414 /* */
4415 /* _nx_rtsp_server_disconnect_process PORTABLE C */
4416 /* 6.3.0 */
4417 /* AUTHOR */
4418 /* */
4419 /* Wenhui Xie, Microsoft Corporation */
4420 /* */
4421 /* DESCRIPTION */
4422 /* */
4423 /* This function processes disconnect for multiple sessions. */
4424 /* */
4425 /* INPUT */
4426 /* */
4427 /* rtsp_server_ptr Pointer to RTSP server */
4428 /* */
4429 /* OUTPUT */
4430 /* */
4431 /* None */
4432 /* */
4433 /* CALLS */
4434 /* */
4435 /* _nx_rtsp_server_disconnect Disconnect from client */
4436 /* */
4437 /* CALLED BY */
4438 /* */
4439 /* _nx_rtsp_server_thread_entry */
4440 /* */
4441 /* RELEASE HISTORY */
4442 /* */
4443 /* DATE NAME DESCRIPTION */
4444 /* */
4445 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
4446 /* */
4447 /**************************************************************************/
_nx_rtsp_server_disconnect_process(NX_RTSP_SERVER * rtsp_server_ptr)4448 static VOID _nx_rtsp_server_disconnect_process(NX_RTSP_SERVER *rtsp_server_ptr)
4449 {
4450 UINT i;
4451 NX_RTSP_CLIENT *rtsp_client_ptr;
4452
4453
4454 /* Examine all the client structures. */
4455 for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
4456 {
4457
4458 /* Setup pointer to client structure. */
4459 rtsp_client_ptr = &(rtsp_server_ptr -> nx_rtsp_server_client_list[i]);
4460
4461 /* Determine if this socket is in a disconnect state. */
4462 if (rtsp_client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_state > NX_TCP_ESTABLISHED)
4463 {
4464
4465 /* Yes, this socket needs to be torn down. */
4466
4467 /* Increment the number of disconnection requests. */
4468 rtsp_server_ptr -> nx_rtsp_server_disconnection_requests++;
4469
4470 /* Disconnect the socket. */
4471 _nx_rtsp_server_disconnect(rtsp_server_ptr, rtsp_client_ptr);
4472 }
4473 }
4474 }
4475
4476 /**************************************************************************/
4477 /* */
4478 /* FUNCTION RELEASE */
4479 /* */
4480 /* _nx_rtsp_server_timeout_process PORTABLE C */
4481 /* 6.3.0 */
4482 /* AUTHOR */
4483 /* */
4484 /* Wenhui Xie, Microsoft Corporation */
4485 /* */
4486 /* DESCRIPTION */
4487 /* */
4488 /* This function processes timeout event. */
4489 /* */
4490 /* INPUT */
4491 /* */
4492 /* rtsp_server_ptr Pointer to RTSP server */
4493 /* */
4494 /* OUTPUT */
4495 /* */
4496 /* None */
4497 /* */
4498 /* CALLS */
4499 /* */
4500 /* _nx_rtsp_server_disconnect Disconnect from client */
4501 /* */
4502 /* CALLED BY */
4503 /* */
4504 /* _nx_rtsp_server_thread_entry */
4505 /* */
4506 /* RELEASE HISTORY */
4507 /* */
4508 /* DATE NAME DESCRIPTION */
4509 /* */
4510 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
4511 /* */
4512 /**************************************************************************/
_nx_rtsp_server_timeout_process(NX_RTSP_SERVER * rtsp_server_ptr)4513 static VOID _nx_rtsp_server_timeout_process(NX_RTSP_SERVER *rtsp_server_ptr)
4514 {
4515 UINT i;
4516 NX_RTSP_CLIENT *rtsp_client_ptr;
4517
4518
4519 /* Examine all the client structures. */
4520 for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
4521 {
4522
4523 /* Setup pointer to client structure. */
4524 rtsp_client_ptr = &(rtsp_server_ptr -> nx_rtsp_server_client_list[i]);
4525
4526 /* Skip the socket that is not used. */
4527 if (rtsp_client_ptr -> nx_rtsp_client_socket.nx_tcp_socket_state <= NX_TCP_LISTEN_STATE)
4528 {
4529 continue;
4530 }
4531
4532 /* Skip the inactive client. */
4533 if (rtsp_client_ptr -> nx_rtsp_client_request_activity_timeout == 0)
4534 {
4535 continue;
4536 }
4537
4538 /* Decrease the timer count. */
4539 rtsp_client_ptr -> nx_rtsp_client_request_activity_timeout--;
4540
4541 /* Check if the client is timeout. */
4542 if (rtsp_client_ptr -> nx_rtsp_client_request_activity_timeout == 0)
4543 {
4544
4545 /* Disconnect the socket. */
4546 _nx_rtsp_server_disconnect(rtsp_server_ptr, rtsp_client_ptr);
4547 }
4548 }
4549 }
4550
4551 /**************************************************************************/
4552 /* */
4553 /* FUNCTION RELEASE */
4554 /* */
4555 /* _nx_rtsp_server_request_present PORTABLE C */
4556 /* 6.3.0 */
4557 /* AUTHOR */
4558 /* */
4559 /* Wenhui Xie, Microsoft Corporation */
4560 /* */
4561 /* DESCRIPTION */
4562 /* */
4563 /* This function handles all RTSP client commands received on */
4564 /* the control socket. */
4565 /* */
4566 /* */
4567 /* INPUT */
4568 /* */
4569 /* request_socket_ptr Socket event occurred */
4570 /* */
4571 /* OUTPUT */
4572 /* */
4573 /* None */
4574 /* */
4575 /* CALLS */
4576 /* */
4577 /* tx_event_flags_set Set events for server thread */
4578 /* */
4579 /* CALLED BY */
4580 /* */
4581 /* NetX NetX receive packet callback */
4582 /* */
4583 /* RELEASE HISTORY */
4584 /* */
4585 /* DATE NAME DESCRIPTION */
4586 /* */
4587 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
4588 /* */
4589 /**************************************************************************/
_nx_rtsp_server_request_present(NX_TCP_SOCKET * request_socket_ptr)4590 static VOID _nx_rtsp_server_request_present(NX_TCP_SOCKET *request_socket_ptr)
4591 {
4592
4593 NX_RTSP_SERVER *server_ptr;
4594
4595
4596 /* Pickup server pointer. This is setup in the reserved field of the TCP socket. */
4597 server_ptr = request_socket_ptr -> nx_tcp_socket_reserved_ptr;
4598
4599 /* Set the request event flag. */
4600 tx_event_flags_set(&(server_ptr -> nx_rtsp_server_event_flags), NX_RTSP_SERVER_REQUEST_EVENT, TX_OR);
4601 }
4602
4603 /**************************************************************************/
4604 /* */
4605 /* FUNCTION RELEASE */
4606 /* */
4607 /* _nx_rtsp_server_connect_present PORTABLE C */
4608 /* 6.3.0 */
4609 /* AUTHOR */
4610 /* */
4611 /* Wenhui Xie, Microsoft Corporation */
4612 /* */
4613 /* DESCRIPTION */
4614 /* */
4615 /* This function handles all RTSP client connections received on */
4616 /* the control socket. */
4617 /* */
4618 /* */
4619 /* INPUT */
4620 /* */
4621 /* request_socket_ptr Socket event occurred */
4622 /* port Port the connection occurred */
4623 /* */
4624 /* OUTPUT */
4625 /* */
4626 /* None */
4627 /* */
4628 /* CALLS */
4629 /* */
4630 /* tx_event_flags_set Set events for server thread */
4631 /* */
4632 /* CALLED BY */
4633 /* */
4634 /* NetX NetX connect callback */
4635 /* */
4636 /* RELEASE HISTORY */
4637 /* */
4638 /* DATE NAME DESCRIPTION */
4639 /* */
4640 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
4641 /* */
4642 /**************************************************************************/
_nx_rtsp_server_connect_present(NX_TCP_SOCKET * request_socket_ptr,UINT port)4643 static VOID _nx_rtsp_server_connect_present(NX_TCP_SOCKET *request_socket_ptr, UINT port)
4644 {
4645 NX_RTSP_SERVER *server_ptr;
4646
4647
4648 NX_PARAMETER_NOT_USED(port);
4649
4650 /* Pickup server pointer. This is setup in the reserved field of the TCP socket. */
4651 server_ptr = request_socket_ptr -> nx_tcp_socket_reserved_ptr;
4652
4653 /* Set the connect event flag. */
4654 tx_event_flags_set(&(server_ptr -> nx_rtsp_server_event_flags), NX_RTSP_SERVER_CONNECT_EVENT, TX_OR);
4655 }
4656
4657 /**************************************************************************/
4658 /* */
4659 /* FUNCTION RELEASE */
4660 /* */
4661 /* _nx_rtsp_server_disconnect_present PORTABLE C */
4662 /* 6.3.0 */
4663 /* AUTHOR */
4664 /* */
4665 /* Wenhui Xie, Microsoft Corporation */
4666 /* */
4667 /* DESCRIPTION */
4668 /* */
4669 /* This function notifies the RTSP server thread of client disconnects */
4670 /* of the control socket. */
4671 /* */
4672 /* */
4673 /* INPUT */
4674 /* */
4675 /* request_socket_ptr Socket event occurred */
4676 /* */
4677 /* OUTPUT */
4678 /* */
4679 /* None */
4680 /* */
4681 /* CALLS */
4682 /* */
4683 /* tx_event_flags_set Set events for server thread */
4684 /* */
4685 /* CALLED BY */
4686 /* */
4687 /* NetX NetX connect callback */
4688 /* */
4689 /* RELEASE HISTORY */
4690 /* */
4691 /* DATE NAME DESCRIPTION */
4692 /* */
4693 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
4694 /* */
4695 /**************************************************************************/
_nx_rtsp_server_disconnect_present(NX_TCP_SOCKET * request_socket_ptr)4696 static VOID _nx_rtsp_server_disconnect_present(NX_TCP_SOCKET *request_socket_ptr)
4697 {
4698 NX_RTSP_SERVER *server_ptr;
4699
4700
4701 /* Pickup server pointer. This is setup in the reserved field of the TCP socket. */
4702 server_ptr = request_socket_ptr -> nx_tcp_socket_reserved_ptr;
4703
4704 /* Set the disconnect event flag. */
4705 tx_event_flags_set(&(server_ptr -> nx_rtsp_server_event_flags), NX_RTSP_SERVER_DISCONNECT_EVENT, TX_OR);
4706 }
4707
4708 /**************************************************************************/
4709 /* */
4710 /* FUNCTION RELEASE */
4711 /* */
4712 /* _nx_rtsp_server_timeout PORTABLE C */
4713 /* 6.3.0 */
4714 /* AUTHOR */
4715 /* */
4716 /* Wenhui Xie, Microsoft Corporation */
4717 /* */
4718 /* DESCRIPTION */
4719 /* */
4720 /* This internal function is invoked whenever the internal timeout */
4721 /* timer expires, and is passed into tx_timer_create as the callback. */
4722 /* */
4723 /* */
4724 /* INPUT */
4725 /* */
4726 /* rtsp_server_address Pointer to RTSP server */
4727 /* */
4728 /* OUTPUT */
4729 /* */
4730 /* None */
4731 /* */
4732 /* CALLS */
4733 /* */
4734 /* tx_event_flags_set Set events for server thread */
4735 /* */
4736 /* CALLED BY */
4737 /* */
4738 /* ThreadX */
4739 /* */
4740 /* RELEASE HISTORY */
4741 /* */
4742 /* DATE NAME DESCRIPTION */
4743 /* */
4744 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
4745 /* */
4746 /**************************************************************************/
_nx_rtsp_server_timeout(ULONG rtsp_server_address)4747 static VOID _nx_rtsp_server_timeout(ULONG rtsp_server_address)
4748 {
4749 NX_RTSP_SERVER *rtsp_server_ptr = (NX_RTSP_SERVER *)rtsp_server_address;
4750
4751
4752 /* Set the timeout event flag. */
4753 tx_event_flags_set(&(rtsp_server_ptr -> nx_rtsp_server_event_flags), NX_RTSP_SERVER_TIMEOUT_EVENT, TX_OR);
4754 }
4755
4756 /**************************************************************************/
4757 /* */
4758 /* FUNCTION RELEASE */
4759 /* */
4760 /* _nx_rtsp_server_disconnect PORTABLE C */
4761 /* 6.3.0 */
4762 /* AUTHOR */
4763 /* */
4764 /* Wenhui Xie, Microsoft Corporation */
4765 /* */
4766 /* DESCRIPTION */
4767 /* */
4768 /* This function disconnects a client which is disconnected or timeout.*/
4769 /* */
4770 /* */
4771 /* INPUT */
4772 /* */
4773 /* rtsp_server_ptr Pointer to RTSP server */
4774 /* rtsp_client_ptr Pointer to RTSP client */
4775 /* */
4776 /* OUTPUT */
4777 /* */
4778 /* None */
4779 /* */
4780 /* CALLS */
4781 /* */
4782 /* nx_tcp_socket_disconnect Disconnect TCP socket */
4783 /* nx_tcp_server_socket_unaccept Clear accepted socket */
4784 /* nx_packet_release Release the packet */
4785 /* nx_tcp_server_socket_relisten Re-listen on free socket */
4786 /* */
4787 /* CALLED BY */
4788 /* */
4789 /* _nx_rtsp_server_disconnect_process */
4790 /* _nx_rtsp_server_timeout_process */
4791 /* */
4792 /* RELEASE HISTORY */
4793 /* */
4794 /* DATE NAME DESCRIPTION */
4795 /* */
4796 /* 10-31-2023 Wenhui Xie Initial Version 6.3.0 */
4797 /* */
4798 /**************************************************************************/
_nx_rtsp_server_disconnect(NX_RTSP_SERVER * rtsp_server_ptr,NX_RTSP_CLIENT * rtsp_client_ptr)4799 static VOID _nx_rtsp_server_disconnect(NX_RTSP_SERVER *rtsp_server_ptr, NX_RTSP_CLIENT *rtsp_client_ptr)
4800 {
4801
4802 /* Disable the client request activity timeout. */
4803 rtsp_client_ptr -> nx_rtsp_client_request_activity_timeout = 0;
4804
4805 /* Now disconnect the socket. */
4806 nx_tcp_socket_disconnect(&(rtsp_client_ptr -> nx_rtsp_client_socket), NX_NO_WAIT);
4807
4808 /* Unaccept the server socket. */
4809 nx_tcp_server_socket_unaccept(&(rtsp_client_ptr -> nx_rtsp_client_socket));
4810
4811 /* Check to see if a packet is queued up. */
4812 if (rtsp_client_ptr -> nx_rtsp_client_request_packet)
4813 {
4814
4815 /* Yes, release it! */
4816 nx_packet_release(rtsp_client_ptr -> nx_rtsp_client_request_packet);
4817 rtsp_client_ptr -> nx_rtsp_client_request_packet = NX_NULL;
4818 rtsp_client_ptr -> nx_rtsp_client_request_bytes_total = 0;
4819 }
4820
4821 /* Check to see if a packet is queued up. */
4822 if (rtsp_client_ptr -> nx_rtsp_client_response_packet)
4823 {
4824
4825 /* Yes, release it! */
4826 nx_packet_release(rtsp_client_ptr -> nx_rtsp_client_response_packet);
4827 rtsp_client_ptr -> nx_rtsp_client_response_packet = NX_NULL;
4828 }
4829
4830 /* Invoke the disconnect callback. */
4831 if ((rtsp_server_ptr -> nx_rtsp_server_disconnect_callback) &&
4832 (rtsp_client_ptr -> nx_rtsp_client_state > NX_RTSP_STATE_INIT))
4833 {
4834 rtsp_server_ptr -> nx_rtsp_server_disconnect_callback(rtsp_client_ptr);
4835 }
4836
4837 /* Relisten on this socket. */
4838 nx_tcp_server_socket_relisten(rtsp_server_ptr -> nx_rtsp_server_ip_ptr, rtsp_server_ptr -> nx_rtsp_server_port,
4839 &(rtsp_client_ptr -> nx_rtsp_client_socket));
4840
4841 /* Clear the session ID. */
4842 rtsp_client_ptr -> nx_rtsp_client_session_id = 0;
4843
4844 /* Reset client valid status. */
4845 rtsp_client_ptr -> nx_rtsp_client_valid = NX_FALSE;
4846
4847 /* Reset client state. */
4848 rtsp_client_ptr -> nx_rtsp_client_state = NX_RTSP_STATE_INIT;
4849
4850 /* Update the connected client count. */
4851 rtsp_server_ptr -> nx_rtsp_server_connected_client_count--;
4852 }
4853
4854