1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** NetX Duo Component */
17 /** */
18 /** File Transfer Protocol (FTP) */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define NX_FTP_SOURCE_CODE
24
25
26 /* Force error checking to be disabled in this module */
27
28 #ifndef NX_DISABLE_ERROR_CHECKING
29 #define NX_DISABLE_ERROR_CHECKING
30 #endif
31
32 /* If FileX is not used in your application, define this option. Then define the
33 services declared in filex_stub.h elsewhere.
34 #define NX_FTP_NO_FILEX
35 */
36
37 /* Include necessary system files. */
38
39 #include "nx_api.h"
40 #include "nx_ip.h"
41 #ifdef FEATURE_NX_IPV6
42 #include "nx_ipv6.h"
43 #endif /* FEATURE_NX_IPV6 */
44 #include "nxd_ftp_client.h"
45 #include "stdio.h"
46 #include "string.h"
47
48
49
50 /* Bring in externs for caller checking code. */
51
52 NX_CALLER_CHECKING_EXTERNS
53
54
55 /**************************************************************************/
56 /* */
57 /* FUNCTION RELEASE */
58 /* */
59 /* _nxe_ftp_client_connect PORTABLE C */
60 /* 6.1 */
61 /* AUTHOR */
62 /* */
63 /* Yuxin Zhou, Microsoft Corporation */
64 /* */
65 /* DESCRIPTION */
66 /* */
67 /* This function checks for errors in the FTP client connect call. */
68 /* */
69 /* Note: The string lengths of username and password are limited by */
70 /* the packet payload size. */
71 /* */
72 /* INPUT */
73 /* */
74 /* ftp_client_ptr Pointer to FTP client */
75 /* server_ip FTP server IPv4 address */
76 /* username Pointer to login username */
77 /* password Pointer to login password */
78 /* wait_option Specifies how long to wait */
79 /* */
80 /* OUTPUT */
81 /* */
82 /* status Completion status */
83 /* */
84 /* CALLS */
85 /* */
86 /* _nxe_ftp_client_connect Actual client connect call */
87 /* */
88 /* CALLED BY */
89 /* */
90 /* Application Code */
91 /* */
92 /* RELEASE HISTORY */
93 /* */
94 /* DATE NAME DESCRIPTION */
95 /* */
96 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
97 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
98 /* resulting in version 6.1 */
99 /* */
100 /**************************************************************************/
_nxe_ftp_client_connect(NX_FTP_CLIENT * ftp_client_ptr,ULONG server_ip,CHAR * username,CHAR * password,ULONG wait_option)101 UINT _nxe_ftp_client_connect(NX_FTP_CLIENT *ftp_client_ptr, ULONG server_ip, CHAR *username,
102 CHAR *password, ULONG wait_option)
103 {
104
105 #ifndef NX_DISABLE_IPV4
106 UINT status;
107
108
109 /* Check for invalid input pointers. */
110 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID))
111 return(NX_PTR_ERROR);
112
113 /* Check for an invalid server IP address. */
114 if (server_ip == 0)
115 return(NX_IP_ADDRESS_ERROR);
116
117 /* Check for appropriate caller. */
118 NX_THREADS_ONLY_CALLER_CHECKING
119
120 /* Call actual client connect function. */
121 status = _nx_ftp_client_connect(ftp_client_ptr, server_ip, username, password, wait_option);
122
123 /* Return completion status. */
124 return(status);
125 #else
126 NX_PARAMETER_NOT_USED(ftp_client_ptr);
127 NX_PARAMETER_NOT_USED(server_ip);
128 NX_PARAMETER_NOT_USED(username);
129 NX_PARAMETER_NOT_USED(password);
130 NX_PARAMETER_NOT_USED(wait_option);
131
132 return(NX_NOT_SUPPORTED);
133 #endif /* NX_DISABLE_IPV4 */
134 }
135
136
137 /**************************************************************************/
138 /* */
139 /* FUNCTION RELEASE */
140 /* */
141 /* _nx_ftp_client_connect PORTABLE C */
142 /* 6.1 */
143 /* AUTHOR */
144 /* */
145 /* Yuxin Zhou, Microsoft Corporation */
146 /* */
147 /* DESCRIPTION */
148 /* */
149 /* This function connects a previously created FTP instance with the */
150 /* FTP server at the specified IP address. */
151 /* */
152 /* Note: The string lengths of username and password are limited by */
153 /* the packet payload size. */
154 /* */
155 /* INPUT */
156 /* */
157 /* ftp_client_ptr Pointer to FTP client */
158 /* server_ip FTP server IPv4 address */
159 /* username Pointer to login username */
160 /* password Pointer to login password */
161 /* wait_option Specifies how long to wait */
162 /* */
163 /* OUTPUT */
164 /* */
165 /* status Completion status */
166 /* */
167 /* CALLS */
168 /* */
169 /* _nx_ftp_client_connect_internal Connect to FTP server using */
170 /* IP address */
171 /* */
172 /* CALLED BY */
173 /* */
174 /* Application Code */
175 /* */
176 /* RELEASE HISTORY */
177 /* */
178 /* DATE NAME DESCRIPTION */
179 /* */
180 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
181 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
182 /* resulting in version 6.1 */
183 /* */
184 /**************************************************************************/
_nx_ftp_client_connect(NX_FTP_CLIENT * ftp_client_ptr,ULONG server_ip,CHAR * username,CHAR * password,ULONG wait_option)185 UINT _nx_ftp_client_connect(NX_FTP_CLIENT *ftp_client_ptr, ULONG server_ip, CHAR *username,
186 CHAR *password, ULONG wait_option)
187 {
188
189 #ifndef NX_DISABLE_IPV4
190 NXD_ADDRESS server_ipduo;
191
192 /* Construct an IP address structure, and fill in IPv4 address information. */
193 server_ipduo.nxd_ip_version = NX_IP_VERSION_V4;
194 server_ipduo.nxd_ip_address.v4 = server_ip;
195
196
197 /* Invoke the real connection call. */
198 return (_nx_ftp_client_connect_internal(ftp_client_ptr, &server_ipduo, username, password, wait_option));
199 #else
200 NX_PARAMETER_NOT_USED(ftp_client_ptr);
201 NX_PARAMETER_NOT_USED(server_ip);
202 NX_PARAMETER_NOT_USED(username);
203 NX_PARAMETER_NOT_USED(password);
204 NX_PARAMETER_NOT_USED(wait_option);
205
206 return(NX_NOT_SUPPORTED);
207 #endif /* NX_DISABLE_IPV4 */
208 }
209
210
211 /**************************************************************************/
212 /* */
213 /* FUNCTION RELEASE */
214 /* */
215 /* _nxde_ftp_client_connect PORTABLE C */
216 /* 6.1 */
217 /* AUTHOR */
218 /* */
219 /* Yuxin Zhou, Microsoft Corporation */
220 /* */
221 /* DESCRIPTION */
222 /* */
223 /* This function checks for errors in the FTP client connect call. */
224 /* */
225 /* Note: The string lengths of username and password are limited by */
226 /* the packet payload size. */
227 /* */
228 /* INPUT */
229 /* */
230 /* ftp_client_ptr Pointer to FTP client */
231 /* server_ip FTP server IP address */
232 /* username Pointer to login username */
233 /* password Pointer to login password */
234 /* wait_option Specifies how long to wait */
235 /* */
236 /* OUTPUT */
237 /* */
238 /* status Completion status */
239 /* */
240 /* CALLS */
241 /* */
242 /* _nxe_ftp_client_connect Actual client connect call */
243 /* */
244 /* CALLED BY */
245 /* */
246 /* Application Code */
247 /* */
248 /* RELEASE HISTORY */
249 /* */
250 /* DATE NAME DESCRIPTION */
251 /* */
252 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
253 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
254 /* resulting in version 6.1 */
255 /* */
256 /**************************************************************************/
_nxde_ftp_client_connect(NX_FTP_CLIENT * ftp_client_ptr,NXD_ADDRESS * server_ipduo,CHAR * username,CHAR * password,ULONG wait_option)257 UINT _nxde_ftp_client_connect(NX_FTP_CLIENT *ftp_client_ptr, NXD_ADDRESS *server_ipduo, CHAR *username,
258 CHAR *password, ULONG wait_option)
259 {
260
261 UINT status;
262
263
264 /* Check for invalid input pointers. */
265 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID))
266 return(NX_PTR_ERROR);
267
268 /* Check for an invalid server IP address. */
269 if (!server_ipduo)
270 return(NX_IP_ADDRESS_ERROR);
271
272 /* Check for appropriate caller. */
273 NX_THREADS_ONLY_CALLER_CHECKING
274
275 /* Call actual client connect function. */
276 status = _nxd_ftp_client_connect(ftp_client_ptr, server_ipduo, username, password, wait_option);
277
278 return status;
279 }
280
281
282 /**************************************************************************/
283 /* */
284 /* FUNCTION RELEASE */
285 /* */
286 /* _nxd_ftp_client_connect PORTABLE C */
287 /* 6.1 */
288 /* AUTHOR */
289 /* */
290 /* Yuxin Zhou, Microsoft Corporation */
291 /* */
292 /* DESCRIPTION */
293 /* */
294 /* This function connects a previously created FTP instance with the */
295 /* FTP server at the specified IP address. */
296 /* */
297 /* Note: The string lengths of username and password are limited by */
298 /* the packet payload size. */
299 /* */
300 /* INPUT */
301 /* */
302 /* ftp_client_ptr Pointer to FTP client */
303 /* server_ip FTP server IP duo address */
304 /* username Pointer to login username */
305 /* password Pointer to login password */
306 /* wait_option Specifies how long to wait */
307 /* */
308 /* OUTPUT */
309 /* */
310 /* status Completion status */
311 /* */
312 /* CALLS */
313 /* */
314 /* _nx_ftp_client_connect_internal Acutal connect service */
315 /* */
316 /* CALLED BY */
317 /* */
318 /* Application Code */
319 /* */
320 /* RELEASE HISTORY */
321 /* */
322 /* DATE NAME DESCRIPTION */
323 /* */
324 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
325 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
326 /* resulting in version 6.1 */
327 /* */
328 /**************************************************************************/
_nxd_ftp_client_connect(NX_FTP_CLIENT * ftp_client_ptr,NXD_ADDRESS * server_ipduo,CHAR * username,CHAR * password,ULONG wait_option)329 UINT _nxd_ftp_client_connect(NX_FTP_CLIENT *ftp_client_ptr, NXD_ADDRESS *server_ipduo, CHAR *username,
330 CHAR *password, ULONG wait_option)
331 {
332
333 /* Invoke the real connection call. */
334 return (_nx_ftp_client_connect_internal(ftp_client_ptr, server_ipduo, username, password, wait_option));
335 }
336
337
338 /**************************************************************************/
339 /* */
340 /* FUNCTION RELEASE */
341 /* */
342 /* _nx_ftp_client_connect_internal PORTABLE C */
343 /* 6.1 */
344 /* AUTHOR */
345 /* */
346 /* Yuxin Zhou, Microsoft Corporation */
347 /* */
348 /* DESCRIPTION */
349 /* */
350 /* This function connects a previously created FTP instance with the */
351 /* FTP server at the specified IP address. */
352 /* */
353 /* INPUT */
354 /* */
355 /* ftp_client_ptr Pointer to FTP client */
356 /* server_ip FTP server IP address */
357 /* username Pointer to login username */
358 /* password Pointer to login password */
359 /* wait_option Specifies how long to wait */
360 /* */
361 /* OUTPUT */
362 /* */
363 /* status Completion status */
364 /* */
365 /* CALLS */
366 /* */
367 /* nx_tcp_client_socket_bind Bind client socket to port */
368 /* nxd_tcp_client_socket_connect Connect to FTP server */
369 /* nx_tcp_client_socket_unbind Unbind client socket from port*/
370 /* nx_packet_release Release packet */
371 /* nx_tcp_socket_receive Receive server response */
372 /* nx_tcp_socket_send Send request to server */
373 /* */
374 /* CALLED BY */
375 /* */
376 /* Application Code */
377 /* */
378 /* RELEASE HISTORY */
379 /* */
380 /* DATE NAME DESCRIPTION */
381 /* */
382 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
383 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
384 /* resulting in version 6.1 */
385 /* */
386 /**************************************************************************/
_nx_ftp_client_connect_internal(NX_FTP_CLIENT * ftp_client_ptr,NXD_ADDRESS * server_ip,CHAR * username,CHAR * password,ULONG wait_option)387 UINT _nx_ftp_client_connect_internal(NX_FTP_CLIENT *ftp_client_ptr, NXD_ADDRESS *server_ip, CHAR *username,
388 CHAR *password, ULONG wait_option)
389 {
390
391 NX_PACKET *packet_ptr;
392 UCHAR *buffer_ptr;
393 UINT length;
394 UINT i;
395 UINT status;
396
397
398 /* Determine if the client is still in a not connected state. */
399 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_NOT_CONNECTED)
400 {
401
402 /* Already connected, return an error. */
403 return(NX_FTP_NOT_DISCONNECTED);
404 }
405
406 /* Bind the client control socket. */
407 status = nx_tcp_client_socket_bind(&(ftp_client_ptr -> nx_ftp_client_control_socket), NX_FTP_CLIENT_SOURCE_PORT, wait_option);
408
409 /* Check for an error. */
410 if ((status != NX_SUCCESS) && (status != NX_ALREADY_BOUND))
411 {
412
413 /* Unable to bind socket to port. */
414 return(status);
415 }
416
417 /* Connect the socket to the FTP server. */
418 status = nxd_tcp_client_socket_connect(&(ftp_client_ptr -> nx_ftp_client_control_socket), server_ip, NX_FTP_SERVER_CONTROL_PORT, wait_option);
419
420
421 /* Check for an error. */
422 if (status != NX_SUCCESS)
423 {
424
425 /* Unbind the socket. */
426 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
427
428 /* Unable to connect socket to server FTP control port. */
429 return(status);
430 }
431
432 /* Now wait for the "220 " response from the FTP server to indicate the connection has been
433 established. */
434 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
435
436 /* Check to see if no packet was received. */
437 if (status)
438 {
439
440 /* Close the socket. */
441 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
442
443 /* Unbind the socket. */
444 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
445
446 /* Unable to connect socket to server FTP control port. */
447 return(status);
448 }
449
450 #ifndef NX_DISABLE_PACKET_CHAIN
451 if (packet_ptr -> nx_packet_next)
452 {
453
454 /* Release the packet. */
455 nx_packet_release(packet_ptr);
456
457 /* Close the socket. */
458 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
459
460 /* Unbind the socket. */
461 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
462
463 /* Return. */
464 return(NX_INVALID_PACKET);
465 }
466 #endif /* NX_DISABLE_PACKET_CHAIN */
467
468 /* We have a packet, setup pointer to the buffer area. */
469 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
470 length = packet_ptr -> nx_packet_length;
471
472 /* Check for 220 message. */
473 if ((length < 3) || (buffer_ptr[0] != '2') || (buffer_ptr[1] != '2'))
474 {
475
476 /* Close the socket. */
477 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
478
479 /* Release the packet. */
480 nx_packet_release(packet_ptr);
481
482 /* Unbind the socket. */
483 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
484
485 /* Unable to connect socket to server FTP control port. */
486 return(NX_FTP_EXPECTED_22X_CODE);
487 }
488
489 memset(buffer_ptr, 0, length);
490
491 /* Check if out of boundary. */
492 if (((!username) && ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 11)) ||
493 ((username) && ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 7)))
494 {
495
496 /* Release the packet. */
497 nx_packet_release(packet_ptr);
498
499 /* Close the socket. */
500 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
501
502 /* Unbind the socket. */
503 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
504
505 /* Set the error status. */
506 return(NX_FTP_FAILED);
507 }
508
509 /* Now build the user name message. */
510 buffer_ptr[0] = 'U';
511 buffer_ptr[1] = 'S';
512 buffer_ptr[2] = 'E';
513 buffer_ptr[3] = 'R';
514 buffer_ptr[4] = ' ';
515
516 /* Determine if a user name was supplied. */
517 if (username == NX_NULL)
518 {
519
520 /* No username specified, use "USER". */
521 buffer_ptr[5] = 'U';
522 buffer_ptr[6] = 'S';
523 buffer_ptr[7] = 'E';
524 buffer_ptr[8] = 'R';
525 buffer_ptr[9] = 13;
526 buffer_ptr[10]= 10;
527
528 /* Set the length of the packet. */
529 packet_ptr -> nx_packet_length = 11;
530 }
531 else
532 {
533
534 /* A username was supplied, copy it into the buffer. */
535 for(i = 0; username[i]; i++)
536 {
537
538 /* Check if out of boundary. */
539 if ((i + 7) >= (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr))
540 {
541
542 /* Release the packet. */
543 nx_packet_release(packet_ptr);
544
545 /* Close the socket. */
546 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
547
548 /* Unbind the socket. */
549 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
550
551 /* Set the error status. */
552 return(NX_FTP_FAILED);
553 }
554
555 /* Copy byte of the username. */
556 buffer_ptr[5+i] = (UCHAR)username[i];
557 }
558
559 /* Now insert the CR/LF. */
560 buffer_ptr[5+i] = 13;
561 buffer_ptr[5+i+1] = 10;
562
563 /* Setup the length of the packet. */
564 packet_ptr -> nx_packet_length = i + 7;
565 }
566
567 /* Setup the packet append pointer. */
568 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
569
570 /* Send the username to the FTP server. */
571 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
572
573 /* Check for unsuccessful send. */
574 if (status)
575 {
576
577 /* Release the packet. */
578 nx_packet_release(packet_ptr);
579
580 /* Close the socket. */
581 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
582
583 /* Unbind the socket. */
584 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
585
586 /* Unable to connect socket to server FTP control port. */
587 return(status);
588 }
589
590 /* There may be multiple 220 responses from FTP server after establishing connection.
591 Flush mutiple 220 respones and wait for 331 response from the FTP server. */
592 while(1)
593 {
594
595 /* Wait for response from the FTP server. */
596 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
597
598 /* Determine if a packet was not received. */
599 if (status)
600 {
601
602 /* Close the socket. */
603 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
604
605 /* Unbind the socket. */
606 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
607
608 /* Unable to connect socket to server FTP control port. */
609 return(status);
610 }
611
612 #ifndef NX_DISABLE_PACKET_CHAIN
613 if (packet_ptr -> nx_packet_next)
614 {
615
616 /* Release the packet. */
617 nx_packet_release(packet_ptr);
618
619 /* Close the socket. */
620 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
621
622 /* Unbind the socket. */
623 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
624
625 /* Return. */
626 return(NX_INVALID_PACKET);
627 }
628 #endif /* NX_DISABLE_PACKET_CHAIN */
629
630 /* We have a packet, setup pointer to the buffer area. */
631 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
632
633 /* Check for 220 message. */
634 if ((packet_ptr -> nx_packet_length >= 3) && (buffer_ptr[0] == '2') && (buffer_ptr[1] == '2'))
635 {
636
637 /* Release the packet. */
638 nx_packet_release(packet_ptr);
639 continue;
640 }
641
642 /* Check to make sure the response is proper. */
643
644 /* Check for 331 message. */
645 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '3') || (buffer_ptr[1] != '3'))
646 {
647
648 /* Release the packet. */
649 nx_packet_release(packet_ptr);
650
651 /* Close the socket. */
652 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
653
654 /* Unbind the socket. */
655 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
656
657 /* Unable to connect socket to server FTP control port. */
658 return(NX_FTP_EXPECTED_33X_CODE);
659 }
660 else
661 {
662 break;
663 }
664 }
665
666 memset(buffer_ptr, 0, length);
667
668 /* Check if out of boundary. */
669 if (((!password) && ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 11)) ||
670 ((password) && ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 7)))
671 {
672
673 /* Release the packet. */
674 nx_packet_release(packet_ptr);
675
676 /* Close the socket. */
677 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
678
679 /* Unbind the socket. */
680 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
681
682 /* Set the error status. */
683 return(NX_FTP_FAILED);
684 }
685
686 /* Now build the password message. */
687 buffer_ptr[0] = 'P';
688 buffer_ptr[1] = 'A';
689 buffer_ptr[2] = 'S';
690 buffer_ptr[3] = 'S';
691 buffer_ptr[4] = ' ';
692
693 /* Determine if a password was specified. */
694 if (password == NX_NULL)
695 {
696
697 /* No password was specified, use "PASS". */
698 buffer_ptr[5] = 'P';
699 buffer_ptr[6] = 'A';
700 buffer_ptr[7] = 'S';
701 buffer_ptr[8] = 'S';
702 buffer_ptr[9] = 13;
703 buffer_ptr[10]= 10;
704
705 /* Setup the packet length. */
706 packet_ptr -> nx_packet_length = 11;
707 }
708 else
709 {
710
711 /* Password was specified, copy it into the buffer. */
712 for(i = 0; password[i]; i++)
713 {
714
715 /* Check if out of boundary. */
716 if ((i + 7) >= (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr))
717 {
718
719 /* Release the packet. */
720 nx_packet_release(packet_ptr);
721
722 /* Close the socket. */
723 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
724
725 /* Unbind the socket. */
726 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
727
728 /* Set the error status. */
729 return(NX_FTP_FAILED);
730 }
731
732 /* Copy byte of password. */
733 buffer_ptr[5+i] = (UCHAR)password[i];
734 }
735
736 /* Now insert the CR/LF. */
737 buffer_ptr[5+i] = 13;
738 buffer_ptr[5+i+1] = 10;
739
740 /* Setup the length of the packet. */
741 packet_ptr -> nx_packet_length = i + 7;
742 }
743
744 /* Setup the packet append pointer. */
745 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
746
747 /* Send the password to the FTP server. */
748 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
749
750 /* Check for successful send. */
751 if (status)
752 {
753
754 /* Release the packet. */
755 nx_packet_release(packet_ptr);
756
757 /* Close the socket. */
758 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
759
760 /* Unbind the socket. */
761 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
762
763 /* Unable to connect socket to server FTP control port. */
764 return(status);
765 }
766
767 /* Wait for response from the FTP server. */
768 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
769
770 /* Determine if a packet was not received. */
771 if (status)
772 {
773
774 /* Close the socket. */
775 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
776
777 /* Unbind the socket. */
778 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
779
780 /* Unable to connect socket to server FTP control port. */
781 return(status);
782 }
783
784 /* We have a packet, setup pointer to the buffer area. */
785 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
786
787 /* Check for 230 message, signaling successful login. */
788 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2') || (buffer_ptr[1] != '3'))
789 {
790
791 /* Release the packet. */
792 nx_packet_release(packet_ptr);
793
794 /* Close the socket. */
795 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
796
797 /* Unbind the socket. */
798 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
799
800 /* Unable to connect socket to server FTP control port. */
801 return(NX_FTP_EXPECTED_23X_CODE);
802 }
803
804 /* Release the packet. */
805 nx_packet_release(packet_ptr);
806
807 /* If we get here, we have a successful connect with the FTP server. */
808 ftp_client_ptr -> nx_ftp_client_state = NX_FTP_STATE_CONNECTED;
809
810 ftp_client_ptr -> nx_ftp_client_data_port = ftp_client_ptr -> nx_ftp_client_control_socket.nx_tcp_socket_port;
811
812 /* Return success to caller. */
813 return(NX_SUCCESS);
814 }
815
816
817 /**************************************************************************/
818 /* */
819 /* FUNCTION RELEASE */
820 /* */
821 /* _nxe_ftp_client_create PORTABLE C */
822 /* 6.1 */
823 /* AUTHOR */
824 /* */
825 /* Yuxin Zhou, Microsoft Corporation */
826 /* */
827 /* DESCRIPTION */
828 /* */
829 /* This function checks for errors in the FTP client create call. */
830 /* */
831 /* */
832 /* INPUT */
833 /* */
834 /* ftp_client_ptr Pointer to FTP client */
835 /* ftp_client_name Name of this FTP client */
836 /* ip_ptr Pointer to IP instance */
837 /* window_size Size of TCP receive window */
838 /* pool_ptr Pointer to packet pool */
839 /* */
840 /* OUTPUT */
841 /* */
842 /* status Completion status */
843 /* */
844 /* CALLS */
845 /* */
846 /* _nx_ftp_client_create Actual client create call */
847 /* */
848 /* CALLED BY */
849 /* */
850 /* Application Code */
851 /* */
852 /* RELEASE HISTORY */
853 /* */
854 /* DATE NAME DESCRIPTION */
855 /* */
856 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
857 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
858 /* resulting in version 6.1 */
859 /* */
860 /**************************************************************************/
_nxe_ftp_client_create(NX_FTP_CLIENT * ftp_client_ptr,CHAR * ftp_client_name,NX_IP * ip_ptr,ULONG window_size,NX_PACKET_POOL * pool_ptr)861 UINT _nxe_ftp_client_create(NX_FTP_CLIENT *ftp_client_ptr, CHAR *ftp_client_name, NX_IP *ip_ptr,
862 ULONG window_size, NX_PACKET_POOL *pool_ptr)
863 {
864
865 UINT status;
866
867
868 /* Check for invalid input pointers. */
869 if ((ip_ptr == NX_NULL) || (ip_ptr -> nx_ip_id != NX_IP_ID) ||
870 (ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id == NXD_FTP_CLIENT_ID) ||
871 (pool_ptr == NX_NULL))
872 return(NX_PTR_ERROR);
873
874 /* Call actual client create function. */
875 status = _nx_ftp_client_create(ftp_client_ptr, ftp_client_name, ip_ptr, window_size, pool_ptr);
876
877 /* Return completion status. */
878 return(status);
879 }
880
881
882 /**************************************************************************/
883 /* */
884 /* FUNCTION RELEASE */
885 /* */
886 /* _nx_ftp_client_create PORTABLE C */
887 /* 6.1 */
888 /* AUTHOR */
889 /* */
890 /* Yuxin Zhou, Microsoft Corporation */
891 /* */
892 /* DESCRIPTION */
893 /* */
894 /* This function creates an FTP client instance. */
895 /* */
896 /* */
897 /* INPUT */
898 /* */
899 /* ftp_client_ptr Pointer to FTP client */
900 /* ftp_client_name Name of this FTP client */
901 /* ip_ptr Pointer to IP instance */
902 /* window_size Size of TCP receive window */
903 /* pool_ptr Pointer to packet pool */
904 /* */
905 /* OUTPUT */
906 /* */
907 /* status Completion status */
908 /* */
909 /* CALLS */
910 /* */
911 /* nx_tcp_socket_create Create TCP socket */
912 /* nx_tcp_socket_delete Delete TCP socket */
913 /* */
914 /* CALLED BY */
915 /* */
916 /* Application Code */
917 /* */
918 /* RELEASE HISTORY */
919 /* */
920 /* DATE NAME DESCRIPTION */
921 /* */
922 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
923 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
924 /* resulting in version 6.1 */
925 /* */
926 /**************************************************************************/
_nx_ftp_client_create(NX_FTP_CLIENT * ftp_client_ptr,CHAR * ftp_client_name,NX_IP * ip_ptr,ULONG window_size,NX_PACKET_POOL * pool_ptr)927 UINT _nx_ftp_client_create(NX_FTP_CLIENT *ftp_client_ptr, CHAR *ftp_client_name, NX_IP *ip_ptr,
928 ULONG window_size, NX_PACKET_POOL *pool_ptr)
929 {
930
931 UINT status;
932
933
934 /* Clear the client FTP control block. */
935 memset((void *) ftp_client_ptr, 0, sizeof(NX_FTP_CLIENT));
936
937 /* Create the TCP control socket. */
938 status = nx_tcp_socket_create(ip_ptr, &(ftp_client_ptr -> nx_ftp_client_control_socket), ftp_client_name,
939 NX_FTP_CONTROL_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, window_size,
940 NX_NULL, NX_NULL);
941
942 /* Check for an error. */
943 if (status)
944 {
945
946 /* Return an error. */
947 return(status);
948 }
949
950 /* Create the TCP data socket. */
951 status = nx_tcp_socket_create(ip_ptr, &(ftp_client_ptr -> nx_ftp_client_data_socket), ftp_client_name,
952 NX_FTP_CONTROL_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, window_size,
953 NX_NULL, _nx_ftp_client_data_disconnect);
954
955 /* Check for an error. */
956 if (status)
957 {
958
959 /* Delete the control socket. */
960 nx_tcp_socket_delete(&(ftp_client_ptr -> nx_ftp_client_control_socket));
961
962 /* Return an error. */
963 return(status);
964 }
965
966 /* Save off the remaining information. */
967
968 /* Save the client name. */
969 ftp_client_ptr -> nx_ftp_client_name = ftp_client_name;
970
971 /* Save the IP pointer. */
972 ftp_client_ptr -> nx_ftp_client_ip_ptr = ip_ptr;
973
974 /* Save the packet pool pointer. */
975 ftp_client_ptr -> nx_ftp_client_packet_pool_ptr = pool_ptr;
976
977 /* Set the initial client state. */
978 ftp_client_ptr -> nx_ftp_client_state = NX_FTP_STATE_NOT_CONNECTED;
979
980 /* Set the FTP client id. */
981 ftp_client_ptr -> nx_ftp_client_id = NXD_FTP_CLIENT_ID;
982
983 /* Default to active transfer mode. */
984 ftp_client_ptr -> nx_ftp_client_passive_transfer_enabled = NX_FALSE;
985
986 /* Default to stream mode. */
987 ftp_client_ptr -> nx_ftp_client_transfer_mode = NX_FTP_TRANSFER_MODE_STREAM;
988
989 /* Return success to caller. */
990 return(NX_SUCCESS);
991 }
992
993
994 /**************************************************************************/
995 /* */
996 /* FUNCTION RELEASE */
997 /* */
998 /* _nx_ftp_client_data_disconnect PORTABLE C */
999 /* 6.1 */
1000 /* AUTHOR */
1001 /* */
1002 /* Yuxin Zhou, Microsoft Corporation */
1003 /* */
1004 /* DESCRIPTION */
1005 /* */
1006 /* This function handles the disconnect from the server. */
1007 /* */
1008 /* */
1009 /* INPUT */
1010 /* */
1011 /* data_socket_ptr Pointer to FTP client data */
1012 /* socket */
1013 /* */
1014 /* OUTPUT */
1015 /* */
1016 /* None */
1017 /* */
1018 /* CALLS */
1019 /* */
1020 /* nx_tcp_socket_disconnect Disconnect TCP socket */
1021 /* */
1022 /* CALLED BY */
1023 /* */
1024 /* Application Code */
1025 /* */
1026 /* RELEASE HISTORY */
1027 /* */
1028 /* DATE NAME DESCRIPTION */
1029 /* */
1030 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1031 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1032 /* resulting in version 6.1 */
1033 /* */
1034 /**************************************************************************/
_nx_ftp_client_data_disconnect(NX_TCP_SOCKET * data_socket_ptr)1035 void _nx_ftp_client_data_disconnect(NX_TCP_SOCKET *data_socket_ptr)
1036 {
1037
1038 /* Disconnect FTP client data socket. */
1039 nx_tcp_socket_disconnect(data_socket_ptr, NX_NO_WAIT);
1040 }
1041
1042
1043 /**************************************************************************/
1044 /* */
1045 /* FUNCTION RELEASE */
1046 /* */
1047 /* _nxe_ftp_client_delete PORTABLE C */
1048 /* 6.1 */
1049 /* AUTHOR */
1050 /* */
1051 /* Yuxin Zhou, Microsoft Corporation */
1052 /* */
1053 /* DESCRIPTION */
1054 /* */
1055 /* This function checks for errors in the FTP client delete call. */
1056 /* */
1057 /* */
1058 /* INPUT */
1059 /* */
1060 /* ftp_client_ptr Pointer to FTP client */
1061 /* */
1062 /* OUTPUT */
1063 /* */
1064 /* status Completion status */
1065 /* */
1066 /* CALLS */
1067 /* */
1068 /* _nx_ftp_client_delete Actual client delete call */
1069 /* */
1070 /* CALLED BY */
1071 /* */
1072 /* Application Code */
1073 /* */
1074 /* RELEASE HISTORY */
1075 /* */
1076 /* DATE NAME DESCRIPTION */
1077 /* */
1078 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1079 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1080 /* resulting in version 6.1 */
1081 /* */
1082 /**************************************************************************/
_nxe_ftp_client_delete(NX_FTP_CLIENT * ftp_client_ptr)1083 UINT _nxe_ftp_client_delete(NX_FTP_CLIENT *ftp_client_ptr)
1084 {
1085
1086 UINT status;
1087
1088
1089 /* Check for invalid input pointers. */
1090 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID))
1091 return(NX_PTR_ERROR);
1092
1093 /* Check for appropriate caller. */
1094 NX_THREADS_ONLY_CALLER_CHECKING
1095
1096 /* Call actual client delete function. */
1097 status = _nx_ftp_client_delete(ftp_client_ptr);
1098
1099 /* Return completion status. */
1100 return(status);
1101 }
1102
1103
1104 /**************************************************************************/
1105 /* */
1106 /* FUNCTION RELEASE */
1107 /* */
1108 /* _nx_ftp_client_delete PORTABLE C */
1109 /* 6.2.1 */
1110 /* AUTHOR */
1111 /* */
1112 /* Yuxin Zhou, Microsoft Corporation */
1113 /* */
1114 /* DESCRIPTION */
1115 /* */
1116 /* This function deletes a previously created FTP client instance. */
1117 /* */
1118 /* */
1119 /* INPUT */
1120 /* */
1121 /* ftp_client_ptr Pointer to FTP client */
1122 /* */
1123 /* OUTPUT */
1124 /* */
1125 /* status Completion status */
1126 /* */
1127 /* CALLS */
1128 /* */
1129 /* nx_tcp_socket_create Create TCP socket */
1130 /* nx_tcp_socket_delete Delete TCP socket */
1131 /* */
1132 /* CALLED BY */
1133 /* */
1134 /* Application Code */
1135 /* */
1136 /* RELEASE HISTORY */
1137 /* */
1138 /* DATE NAME DESCRIPTION */
1139 /* */
1140 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1141 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1142 /* resulting in version 6.1 */
1143 /* 03-08-2023 Wenhui Xie Modified comment(s), */
1144 /* cleared the client ID, */
1145 /* resulting in version 6.2.1 */
1146 /* */
1147 /**************************************************************************/
_nx_ftp_client_delete(NX_FTP_CLIENT * ftp_client_ptr)1148 UINT _nx_ftp_client_delete(NX_FTP_CLIENT *ftp_client_ptr)
1149 {
1150
1151 /* Determine if the client is still in a not connected state. */
1152 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_NOT_CONNECTED)
1153 {
1154
1155 /* Already connected, return an error. */
1156 return(NX_FTP_NOT_DISCONNECTED);
1157 }
1158
1159 /* Clear the client ID . */
1160 ftp_client_ptr -> nx_ftp_client_id = 0;
1161
1162 /* Delete the control and data sockets. */
1163 nx_tcp_socket_delete(&(ftp_client_ptr -> nx_ftp_client_control_socket));
1164 nx_tcp_socket_delete(&(ftp_client_ptr -> nx_ftp_client_data_socket));
1165
1166 /* Return success to caller. */
1167 return(NX_SUCCESS);
1168 }
1169
1170 /**************************************************************************/
1171 /* */
1172 /* FUNCTION RELEASE */
1173 /* */
1174 /* _nxe_ftp_client_directory_create PORTABLE C */
1175 /* 6.1 */
1176 /* AUTHOR */
1177 /* */
1178 /* Yuxin Zhou, Microsoft Corporation */
1179 /* */
1180 /* DESCRIPTION */
1181 /* */
1182 /* This function checks for errors in the FTP client directory */
1183 /* create call. */
1184 /* */
1185 /* Note: The string length of directory_name is limited by the packet */
1186 /* payload size. */
1187 /* */
1188 /* INPUT */
1189 /* */
1190 /* ftp_client_ptr Pointer to FTP client */
1191 /* directory_name New directory name */
1192 /* wait_option Specifies how long to wait */
1193 /* */
1194 /* OUTPUT */
1195 /* */
1196 /* status Completion status */
1197 /* */
1198 /* CALLS */
1199 /* */
1200 /* _nx_ftp_client_directory_create Actual client directory */
1201 /* create call */
1202 /* */
1203 /* CALLED BY */
1204 /* */
1205 /* Application Code */
1206 /* */
1207 /* RELEASE HISTORY */
1208 /* */
1209 /* DATE NAME DESCRIPTION */
1210 /* */
1211 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1212 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1213 /* resulting in version 6.1 */
1214 /* */
1215 /**************************************************************************/
_nxe_ftp_client_directory_create(NX_FTP_CLIENT * ftp_client_ptr,CHAR * directory_name,ULONG wait_option)1216 UINT _nxe_ftp_client_directory_create(NX_FTP_CLIENT *ftp_client_ptr, CHAR *directory_name, ULONG wait_option)
1217 {
1218
1219 UINT status;
1220
1221
1222 /* Check for invalid input pointers. */
1223 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID) || (directory_name == NX_NULL))
1224 return(NX_PTR_ERROR);
1225
1226 /* Check for appropriate caller. */
1227 NX_THREADS_ONLY_CALLER_CHECKING
1228
1229 /* Call actual client directory create function. */
1230 status = _nx_ftp_client_directory_create(ftp_client_ptr, directory_name, wait_option);
1231
1232 /* Return completion status. */
1233 return(status);
1234 }
1235
1236
1237 /**************************************************************************/
1238 /* */
1239 /* FUNCTION RELEASE */
1240 /* */
1241 /* _nx_ftp_client_directory_create PORTABLE C */
1242 /* 6.1 */
1243 /* AUTHOR */
1244 /* */
1245 /* Yuxin Zhou, Microsoft Corporation */
1246 /* */
1247 /* DESCRIPTION */
1248 /* */
1249 /* This function creates the specified directory name on the FTP */
1250 /* server. */
1251 /* */
1252 /* Note: The string length of directory_name is limited by the packet */
1253 /* payload size. */
1254 /* */
1255 /* INPUT */
1256 /* */
1257 /* ftp_client_ptr Pointer to FTP client */
1258 /* directory_name New directory name */
1259 /* wait_option Specifies how long to wait */
1260 /* */
1261 /* OUTPUT */
1262 /* */
1263 /* status Completion status */
1264 /* */
1265 /* CALLS */
1266 /* */
1267 /* nx_packet_allocate Allocate packet */
1268 /* nx_packet_release Release packet */
1269 /* nx_tcp_socket_receive Receive packet from server */
1270 /* nx_tcp_socket_send Send data packet to server */
1271 /* */
1272 /* CALLED BY */
1273 /* */
1274 /* Application Code */
1275 /* */
1276 /* RELEASE HISTORY */
1277 /* */
1278 /* DATE NAME DESCRIPTION */
1279 /* */
1280 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1281 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1282 /* resulting in version 6.1 */
1283 /* */
1284 /**************************************************************************/
_nx_ftp_client_directory_create(NX_FTP_CLIENT * ftp_client_ptr,CHAR * directory_name,ULONG wait_option)1285 UINT _nx_ftp_client_directory_create(NX_FTP_CLIENT *ftp_client_ptr, CHAR *directory_name, ULONG wait_option)
1286 {
1287
1288 UINT i;
1289 UCHAR *buffer_ptr;
1290 NX_PACKET *packet_ptr;
1291 UINT status;
1292
1293 /* Ensure the client is the proper state for directory create request. */
1294 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_CONNECTED)
1295 return(NX_FTP_NOT_CONNECTED);
1296
1297 /* Allocate a packet for sending the directory create command. */
1298 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
1299
1300 /* Determine if the packet allocation was successful. */
1301 if (status)
1302 {
1303
1304 /* Return error. */
1305 return(status);
1306 }
1307
1308 /* Check if out of boundary. */
1309 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 6)
1310 {
1311
1312 /* Release the packet. */
1313 nx_packet_release(packet_ptr);
1314
1315 /* Set the error status. */
1316 return(NX_FTP_FAILED);
1317 }
1318
1319 /* We have a packet, setup pointer to the buffer area. */
1320 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
1321
1322 /* Now build "MKD" message to indicate directory create. */
1323 buffer_ptr[0] = 'M';
1324 buffer_ptr[1] = 'K';
1325 buffer_ptr[2] = 'D';
1326 buffer_ptr[3] = ' ';
1327
1328 /* Copy the new directory name into the message. */
1329 for(i = 0; directory_name[i]; i++)
1330 {
1331
1332 /* Check if out of boundary. */
1333 if ((i + 6) >= (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr))
1334 {
1335
1336 /* Release the packet. */
1337 nx_packet_release(packet_ptr);
1338
1339 /* Set the error status. */
1340 return(NX_FTP_FAILED);
1341 }
1342
1343 /* Copy character of the directory name. */
1344 buffer_ptr[4+i] = (UCHAR)directory_name[i];
1345 }
1346
1347 /* Set the CR/LF. */
1348 buffer_ptr[i+4] = 13;
1349 buffer_ptr[i+5] = 10;
1350
1351 /* Set the packet length. */
1352 packet_ptr -> nx_packet_length = i+6;
1353
1354 /* Setup the packet append pointer. */
1355 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
1356
1357 /* Send the MKD message. */
1358 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
1359
1360 /* Determine if the send was unsuccessful. */
1361 if (status)
1362 {
1363
1364 /* Release the packet. */
1365 nx_packet_release(packet_ptr);
1366
1367 /* Return error. */
1368 return(status);
1369 }
1370
1371 /* Wait for response from the FTP server. */
1372 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
1373
1374 /* Determine if a packet was not received. */
1375 if (status)
1376 {
1377
1378 /* MKD error. */
1379 return(status);
1380 }
1381
1382 /* We have a packet, setup pointer to the buffer area. */
1383 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
1384
1385 /* Check for 2xx message, signaling the "MKD" was processed successfully. */
1386 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2'))
1387 {
1388
1389 /* Release the packet. */
1390 nx_packet_release(packet_ptr);
1391
1392 /* Create directory error. */
1393 return(NX_FTP_EXPECTED_2XX_CODE);
1394 }
1395
1396 /* Yes, the directory was created. */
1397
1398 /* Release the packet. */
1399 nx_packet_release(packet_ptr);
1400
1401 /* Return success to caller. */
1402 return(NX_SUCCESS);
1403 }
1404
1405
1406 /**************************************************************************/
1407 /* */
1408 /* FUNCTION RELEASE */
1409 /* */
1410 /* _nxe_ftp_client_directory_default_set PORTABLE C */
1411 /* 6.1 */
1412 /* AUTHOR */
1413 /* */
1414 /* Yuxin Zhou, Microsoft Corporation */
1415 /* */
1416 /* DESCRIPTION */
1417 /* */
1418 /* This function checks for errors in the FTP client directory */
1419 /* default set. */
1420 /* */
1421 /* Note: The string length of directory_path is limited by the packet */
1422 /* payload size. */
1423 /* */
1424 /* INPUT */
1425 /* */
1426 /* ftp_client_ptr Pointer to FTP client */
1427 /* directory_path New default directory path */
1428 /* wait_option Specifies how long to wait */
1429 /* */
1430 /* OUTPUT */
1431 /* */
1432 /* status Completion status */
1433 /* */
1434 /* CALLS */
1435 /* */
1436 /* _nx_ftp_client_directory_default_set Actual client directory */
1437 /* default set call */
1438 /* */
1439 /* CALLED BY */
1440 /* */
1441 /* Application Code */
1442 /* */
1443 /* RELEASE HISTORY */
1444 /* */
1445 /* DATE NAME DESCRIPTION */
1446 /* */
1447 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1448 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1449 /* resulting in version 6.1 */
1450 /* */
1451 /**************************************************************************/
_nxe_ftp_client_directory_default_set(NX_FTP_CLIENT * ftp_client_ptr,CHAR * directory_path,ULONG wait_option)1452 UINT _nxe_ftp_client_directory_default_set(NX_FTP_CLIENT *ftp_client_ptr, CHAR *directory_path, ULONG wait_option)
1453 {
1454
1455 UINT status;
1456
1457
1458 /* Check for invalid input pointers. */
1459 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID))
1460 return(NX_PTR_ERROR);
1461
1462 /* Check for appropriate caller. */
1463 NX_THREADS_ONLY_CALLER_CHECKING
1464
1465 /* Call actual client directory default set function. */
1466 status = _nx_ftp_client_directory_default_set(ftp_client_ptr, directory_path, wait_option);
1467
1468 /* Return completion status. */
1469 return(status);
1470 }
1471
1472
1473 /**************************************************************************/
1474 /* */
1475 /* FUNCTION RELEASE */
1476 /* */
1477 /* _nx_ftp_client_directory_default_set PORTABLE C */
1478 /* 6.1 */
1479 /* AUTHOR */
1480 /* */
1481 /* Yuxin Zhou, Microsoft Corporation */
1482 /* */
1483 /* DESCRIPTION */
1484 /* */
1485 /* This function changes the default working directory on the FTP */
1486 /* server. */
1487 /* */
1488 /* Note: The string length of directory_path is limited by the packet */
1489 /* payload size. */
1490 /* */
1491 /* INPUT */
1492 /* */
1493 /* ftp_client_ptr Pointer to FTP client */
1494 /* directory_path New default directory path */
1495 /* wait_option Specifies how long to wait */
1496 /* */
1497 /* OUTPUT */
1498 /* */
1499 /* status Completion status */
1500 /* */
1501 /* CALLS */
1502 /* */
1503 /* nx_packet_allocate Allocate packet */
1504 /* nx_packet_release Release packet */
1505 /* nx_tcp_socket_receive Receive packet from server */
1506 /* nx_tcp_socket_send Send data packet to server */
1507 /* */
1508 /* CALLED BY */
1509 /* */
1510 /* Application Code */
1511 /* */
1512 /* RELEASE HISTORY */
1513 /* */
1514 /* DATE NAME DESCRIPTION */
1515 /* */
1516 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1517 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1518 /* resulting in version 6.1 */
1519 /* */
1520 /**************************************************************************/
_nx_ftp_client_directory_default_set(NX_FTP_CLIENT * ftp_client_ptr,CHAR * directory_path,ULONG wait_option)1521 UINT _nx_ftp_client_directory_default_set(NX_FTP_CLIENT *ftp_client_ptr, CHAR *directory_path, ULONG wait_option)
1522 {
1523
1524 UINT i;
1525 UCHAR *buffer_ptr;
1526 NX_PACKET *packet_ptr;
1527 UINT status;
1528
1529
1530 /* Ensure the client is the proper state for a default directory request. */
1531 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_CONNECTED)
1532 return(NX_FTP_NOT_CONNECTED);
1533
1534 /* Allocate a packet for sending the change directory command. */
1535 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
1536
1537 /* Determine if the packet allocation was successful. */
1538 if (status)
1539 {
1540
1541 /* Return error. */
1542 return(status);
1543 }
1544
1545 /* Check if out of boundary. */
1546 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 6)
1547 {
1548
1549 /* Release the packet. */
1550 nx_packet_release(packet_ptr);
1551
1552 /* Set the error status. */
1553 return(NX_FTP_FAILED);
1554 }
1555
1556 /* We have a packet, setup pointer to the buffer area. */
1557 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
1558
1559 /* Now build "CWD" message to indicate default directory change. */
1560 buffer_ptr[0] = 'C';
1561 buffer_ptr[1] = 'W';
1562 buffer_ptr[2] = 'D';
1563 buffer_ptr[3] = ' ';
1564
1565 /* Copy the new default directory into the message. */
1566 for(i = 0; directory_path[i]; i++)
1567 {
1568
1569 /* Check if out of boundary. */
1570 if ((i + 6) >= (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr))
1571 {
1572
1573 /* Release the packet. */
1574 nx_packet_release(packet_ptr);
1575
1576 /* Set the error status. */
1577 return(NX_FTP_FAILED);
1578 }
1579
1580 /* Copy character of the directory path. */
1581 buffer_ptr[4+i] = (UCHAR)directory_path[i];
1582 }
1583
1584 /* Set the CR/LF. */
1585 buffer_ptr[i+4] = 13;
1586 buffer_ptr[i+5] = 10;
1587
1588 /* Set the packet length. */
1589 packet_ptr -> nx_packet_length = i+6;
1590
1591 /* Setup the packet append pointer. */
1592 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
1593
1594 /* Send the CWD message. */
1595 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
1596
1597 /* Determine if the send was unsuccessful. */
1598 if (status)
1599 {
1600
1601 /* Release the packet. */
1602 nx_packet_release(packet_ptr);
1603
1604 /* Return error. */
1605 return(status);
1606 }
1607
1608 /* Wait for response from the FTP server. */
1609 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
1610
1611 /* Determine if a packet was not received. */
1612 if (status)
1613 {
1614
1615 /* RNFR file error. */
1616 return(status);
1617 }
1618
1619 /* We have a packet, setup pointer to the buffer area. */
1620 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
1621
1622 /* Check for 2xx message, signaling the "CWD" was processed successfully. */
1623 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2'))
1624 {
1625
1626 /* Release the packet. */
1627 nx_packet_release(packet_ptr);
1628
1629 /* Change directory error. */
1630 return(NX_FTP_EXPECTED_2XX_CODE);
1631 }
1632
1633 /* Yes, the default directory was changed. */
1634
1635 /* Release the packet. */
1636 nx_packet_release(packet_ptr);
1637
1638 /* Return success to caller. */
1639 return(NX_SUCCESS);
1640 }
1641
1642
1643 /**************************************************************************/
1644 /* */
1645 /* FUNCTION RELEASE */
1646 /* */
1647 /* _nxe_ftp_client_directory_delete PORTABLE C */
1648 /* 6.1 */
1649 /* AUTHOR */
1650 /* */
1651 /* Yuxin Zhou, Microsoft Corporation */
1652 /* */
1653 /* DESCRIPTION */
1654 /* */
1655 /* This function checks for errors in the FTP client directory */
1656 /* delete. */
1657 /* */
1658 /* Note: The string length of directory_name is limited by the packet */
1659 /* payload size. */
1660 /* */
1661 /* INPUT */
1662 /* */
1663 /* ftp_client_ptr Pointer to FTP client */
1664 /* directory_name Directory name to delete */
1665 /* wait_option Specifies how long to wait */
1666 /* */
1667 /* OUTPUT */
1668 /* */
1669 /* status Completion status */
1670 /* */
1671 /* CALLS */
1672 /* */
1673 /* _nx_ftp_client_directory_delete Actual client directory */
1674 /* delete call */
1675 /* */
1676 /* CALLED BY */
1677 /* */
1678 /* Application Code */
1679 /* */
1680 /* RELEASE HISTORY */
1681 /* */
1682 /* DATE NAME DESCRIPTION */
1683 /* */
1684 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1685 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1686 /* resulting in version 6.1 */
1687 /* */
1688 /**************************************************************************/
_nxe_ftp_client_directory_delete(NX_FTP_CLIENT * ftp_client_ptr,CHAR * directory_name,ULONG wait_option)1689 UINT _nxe_ftp_client_directory_delete(NX_FTP_CLIENT *ftp_client_ptr, CHAR *directory_name, ULONG wait_option)
1690 {
1691
1692 UINT status;
1693
1694
1695 /* Check for invalid input pointers. */
1696 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID))
1697 return(NX_PTR_ERROR);
1698
1699 /* Check for appropriate caller. */
1700 NX_THREADS_ONLY_CALLER_CHECKING
1701
1702 /* Call actual client directory delete function. */
1703 status = _nx_ftp_client_directory_delete(ftp_client_ptr, directory_name, wait_option);
1704
1705 /* Return completion status. */
1706 return(status);
1707 }
1708
1709
1710 /**************************************************************************/
1711 /* */
1712 /* FUNCTION RELEASE */
1713 /* */
1714 /* _nx_ftp_client_directory_delete PORTABLE C */
1715 /* 6.1 */
1716 /* AUTHOR */
1717 /* */
1718 /* Yuxin Zhou, Microsoft Corporation */
1719 /* */
1720 /* DESCRIPTION */
1721 /* */
1722 /* This function deletes the specified directory on the FTP */
1723 /* server. */
1724 /* */
1725 /* Note: The string length of directory_name is limited by the packet */
1726 /* payload size. */
1727 /* */
1728 /* INPUT */
1729 /* */
1730 /* ftp_client_ptr Pointer to FTP client */
1731 /* directory_name Directory name to delete */
1732 /* wait_option Specifies how long to wait */
1733 /* */
1734 /* OUTPUT */
1735 /* */
1736 /* status Completion status */
1737 /* */
1738 /* CALLS */
1739 /* */
1740 /* nx_packet_allocate Allocate packet */
1741 /* nx_packet_release Release packet */
1742 /* nx_tcp_socket_receive Receive packet from server */
1743 /* nx_tcp_socket_send Send data packet to server */
1744 /* */
1745 /* CALLED BY */
1746 /* */
1747 /* Application Code */
1748 /* */
1749 /* RELEASE HISTORY */
1750 /* */
1751 /* DATE NAME DESCRIPTION */
1752 /* */
1753 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1754 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1755 /* resulting in version 6.1 */
1756 /* */
1757 /**************************************************************************/
_nx_ftp_client_directory_delete(NX_FTP_CLIENT * ftp_client_ptr,CHAR * directory_name,ULONG wait_option)1758 UINT _nx_ftp_client_directory_delete(NX_FTP_CLIENT *ftp_client_ptr, CHAR *directory_name, ULONG wait_option)
1759 {
1760
1761 UINT i;
1762 UCHAR *buffer_ptr;
1763 NX_PACKET *packet_ptr;
1764 UINT status;
1765
1766
1767 /* Ensure the client is the proper state for directory delete request. */
1768 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_CONNECTED)
1769 return(NX_FTP_NOT_CONNECTED);
1770
1771 /* Allocate a packet for sending the directory delete command. */
1772 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
1773
1774 /* Determine if the packet allocation was successful. */
1775 if (status)
1776 {
1777
1778 /* Return error. */
1779 return(status);
1780 }
1781
1782 /* Check if out of boundary. */
1783 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 6)
1784 {
1785
1786 /* Release the packet. */
1787 nx_packet_release(packet_ptr);
1788
1789 /* Set the error status. */
1790 return(NX_FTP_FAILED);
1791 }
1792
1793 /* We have a packet, setup pointer to the buffer area. */
1794 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
1795
1796 /* Now build "RMD" message to indicate directory delete. */
1797 buffer_ptr[0] = 'R';
1798 buffer_ptr[1] = 'M';
1799 buffer_ptr[2] = 'D';
1800 buffer_ptr[3] = ' ';
1801
1802 /* Copy the directory name into the message. */
1803 for(i = 0; directory_name[i]; i++)
1804 {
1805
1806 /* Check if out of boundary. */
1807 if ((i + 6) >= (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr))
1808 {
1809
1810 /* Release the packet. */
1811 nx_packet_release(packet_ptr);
1812
1813 /* Set the error status. */
1814 return(NX_FTP_FAILED);
1815 }
1816
1817 /* Copy character of the directory name. */
1818 buffer_ptr[4+i] = (UCHAR)directory_name[i];
1819 }
1820
1821 /* Set the CR/LF. */
1822 buffer_ptr[i+4] = 13;
1823 buffer_ptr[i+5] = 10;
1824
1825 /* Set the packet length. */
1826 packet_ptr -> nx_packet_length = i+6;
1827
1828 /* Setup the packet append pointer. */
1829 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
1830
1831 /* Send the RMD message. */
1832 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
1833
1834 /* Determine if the send was unsuccessful. */
1835 if (status)
1836 {
1837
1838 /* Release the packet. */
1839 nx_packet_release(packet_ptr);
1840
1841 /* Return error. */
1842 return(status);
1843 }
1844
1845 /* Wait for response from the FTP server. */
1846 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
1847
1848 /* Determine if a packet was not received. */
1849 if (status)
1850 {
1851
1852 /* DELE error. */
1853 return(status);
1854 }
1855
1856 /* We have a packet, setup pointer to the buffer area. */
1857 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
1858
1859 /* Check for 2xx message, signaling the "RMD" was processed successfully. */
1860 if ((packet_ptr -> nx_packet_length < 3) ||(buffer_ptr[0] != '2'))
1861 {
1862
1863 /* Release the packet. */
1864 nx_packet_release(packet_ptr);
1865
1866 /* Delete directory error. */
1867 return(NX_FTP_EXPECTED_2XX_CODE);
1868 }
1869
1870 /* Yes, the directory was deleted. */
1871
1872 /* Release the packet. */
1873 nx_packet_release(packet_ptr);
1874
1875 /* Return success to caller. */
1876 return(NX_SUCCESS);
1877 }
1878
1879 /**************************************************************************/
1880 /* */
1881 /* FUNCTION RELEASE */
1882 /* */
1883 /* _nxe_ftp_client_directory_listing_get PORTABLE C */
1884 /* 6.1 */
1885 /* AUTHOR */
1886 /* */
1887 /* Yuxin Zhou, Microsoft Corporation */
1888 /* */
1889 /* DESCRIPTION */
1890 /* */
1891 /* This function checks for errors in the FTP client directory */
1892 /* listing get. */
1893 /* */
1894 /* Note: The string length of directory_path is limited by the packet */
1895 /* payload size. */
1896 /* */
1897 /* INPUT */
1898 /* */
1899 /* ftp_client_ptr Pointer to FTP client */
1900 /* directory_path Directory to get listing for */
1901 /* packet_ptr Destination of for the */
1902 /* received packet pointer */
1903 /* that contains the listing */
1904 /* wait_option Specifies how long to wait */
1905 /* */
1906 /* OUTPUT */
1907 /* */
1908 /* status Completion status */
1909 /* */
1910 /* CALLS */
1911 /* */
1912 /* _nx_ftp_client_directory_listing_get Actual client directory */
1913 /* listing get call */
1914 /* */
1915 /* CALLED BY */
1916 /* */
1917 /* Application Code */
1918 /* */
1919 /* RELEASE HISTORY */
1920 /* */
1921 /* DATE NAME DESCRIPTION */
1922 /* */
1923 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1924 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1925 /* resulting in version 6.1 */
1926 /* */
1927 /**************************************************************************/
_nxe_ftp_client_directory_listing_get(NX_FTP_CLIENT * ftp_client_ptr,CHAR * directory_path,NX_PACKET ** packet_ptr,ULONG wait_option)1928 UINT _nxe_ftp_client_directory_listing_get(NX_FTP_CLIENT *ftp_client_ptr, CHAR *directory_path,
1929 NX_PACKET **packet_ptr, ULONG wait_option)
1930 {
1931
1932 UINT status;
1933
1934
1935 /* Check for invalid input pointers. */
1936 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID) || (packet_ptr == NX_NULL))
1937 return(NX_PTR_ERROR);
1938
1939 /* Check for appropriate caller. */
1940 NX_THREADS_ONLY_CALLER_CHECKING
1941
1942 /* Call actual client directory listing get function. */
1943 status = _nx_ftp_client_directory_listing_get(ftp_client_ptr, directory_path, packet_ptr, wait_option);
1944
1945 /* Return completion status. */
1946 return(status);
1947 }
1948
1949
1950 /**************************************************************************/
1951 /* */
1952 /* FUNCTION RELEASE */
1953 /* */
1954 /* _nx_ftp_client_directory_listing_get PORTABLE C */
1955 /* 6.1 */
1956 /* AUTHOR */
1957 /* */
1958 /* Yuxin Zhou, Microsoft Corporation */
1959 /* */
1960 /* DESCRIPTION */
1961 /* */
1962 /* This function gets a listing for the specified directory on the */
1963 /* FTP server. */
1964 /* */
1965 /* Note: The string length of directory_path is limited by the packet */
1966 /* payload size. */
1967 /* */
1968 /* INPUT */
1969 /* */
1970 /* ftp_client_ptr Pointer to FTP client */
1971 /* directory_path Directory to get listing for */
1972 /* packet_ptr Destination of for the */
1973 /* received packet pointer */
1974 /* that contains the listing */
1975 /* wait_option Specifies how long to wait */
1976 /* */
1977 /* OUTPUT */
1978 /* */
1979 /* status Completion status */
1980 /* */
1981 /* CALLS */
1982 /* */
1983 /* _nx_ftp_client_packet_allocate Allocate packet */
1984 /* _nx_ftp_client_active_transfer_setup Setup active transfer */
1985 /* _nx_ftp_client_passive_transfer_setup Setup passive transfer */
1986 /* _nx_ftp_client_block_mode_send Send block mode command */
1987 /* _nx_ftp_client_data_socket_cleanup Cleanup data socket */
1988 /* nx_packet_release Release packet */
1989 /* nx_tcp_server_socket_accept Connect data socket to server */
1990 /* nx_tcp_socket_receive Receive response from server */
1991 /* nx_tcp_socket_send Send request to server */
1992 /* */
1993 /* CALLED BY */
1994 /* */
1995 /* Application Code */
1996 /* */
1997 /* RELEASE HISTORY */
1998 /* */
1999 /* DATE NAME DESCRIPTION */
2000 /* */
2001 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2002 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2003 /* resulting in version 6.1 */
2004 /* */
2005 /**************************************************************************/
_nx_ftp_client_directory_listing_get(NX_FTP_CLIENT * ftp_client_ptr,CHAR * directory_path,NX_PACKET ** packet_ptr,ULONG wait_option)2006 UINT _nx_ftp_client_directory_listing_get(NX_FTP_CLIENT *ftp_client_ptr, CHAR *directory_path,
2007 NX_PACKET **packet_ptr, ULONG wait_option)
2008 {
2009
2010 UINT i;
2011 UCHAR *buffer_ptr;
2012 NX_PACKET *new_packet_ptr;
2013 UINT status;
2014
2015
2016 /* Set packet pointer to NULL. */
2017 *packet_ptr = NX_NULL;
2018
2019 /* Ensure the client is the proper state for directory listing request. */
2020 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_CONNECTED)
2021 return(NX_FTP_NOT_CONNECTED);
2022
2023 /* Divert to passive mode operation if passive mode is enabled. */
2024 if (ftp_client_ptr -> nx_ftp_client_passive_transfer_enabled)
2025 {
2026
2027 /* Transfer the data in passive transfer mode. */
2028 status = _nx_ftp_client_passive_transfer_setup(ftp_client_ptr, wait_option);
2029 }
2030 else
2031 {
2032
2033 /* Transfer the data in active transfer mode. */
2034 status = _nx_ftp_client_active_transfer_setup(ftp_client_ptr, wait_option);
2035 }
2036
2037 /* Determine if set up successful. */
2038 if (status)
2039 {
2040 return(status);
2041 }
2042
2043 /* Check if enable block mode. */
2044 if (ftp_client_ptr -> nx_ftp_client_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
2045 {
2046
2047 /* Send MODE B command to FTP server. */
2048 status = _nx_ftp_client_block_mode_send(ftp_client_ptr, wait_option);
2049
2050 /* Determine if the send was unsuccessful. */
2051 if (status != NX_SUCCESS)
2052 {
2053
2054 /* Cleanup data socket. */
2055 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2056 return(status);
2057 }
2058 }
2059
2060 /* Allocate a packet for sending the NLST command. */
2061 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &new_packet_ptr, wait_option);
2062
2063 /* Determine if the packet allocation was successful. */
2064 if (status != NX_SUCCESS)
2065 {
2066
2067 /* Cleanup data socket. */
2068 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2069
2070 /* Return error. */
2071 return(status);
2072 }
2073
2074 /* Check if out of boundary. */
2075 if ((UINT)(new_packet_ptr -> nx_packet_data_end - new_packet_ptr -> nx_packet_prepend_ptr) < 7)
2076 {
2077
2078 /* Cleanup data socket. */
2079 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2080
2081 /* Release the packet. */
2082 nx_packet_release(new_packet_ptr);
2083
2084 /* Set the error status. */
2085 return(NX_FTP_FAILED);
2086 }
2087
2088 /* We have a packet, setup pointer to the buffer area. */
2089 buffer_ptr = new_packet_ptr -> nx_packet_prepend_ptr;
2090
2091 /* Now build the actual NLST request. */
2092 buffer_ptr[0] = 'N';
2093 buffer_ptr[1] = 'L';
2094 buffer_ptr[2] = 'S';
2095 buffer_ptr[3] = 'T';
2096 buffer_ptr[4] = ' ';
2097
2098 /* Copy the directory path into the buffer. */
2099 for(i = 0; directory_path[i]; i++)
2100 {
2101
2102 /* Check if out of boundary. */
2103 if ((i + 7) >= (UINT)(new_packet_ptr -> nx_packet_data_end - new_packet_ptr -> nx_packet_prepend_ptr))
2104 {
2105
2106 /* Cleanup data socket. */
2107 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2108
2109 /* Release the packet. */
2110 nx_packet_release(new_packet_ptr);
2111
2112 /* Set the error status. */
2113 return(NX_FTP_FAILED);
2114 }
2115
2116 /* Copy character of directory path. */
2117 buffer_ptr[5+i] = (UCHAR)directory_path[i];
2118 }
2119
2120 /* Insert the CR/LF. */
2121 buffer_ptr[5+i] = 13;
2122 buffer_ptr[5+i+1] = 10;
2123
2124 /* Setup the length of the packet. */
2125 new_packet_ptr -> nx_packet_length = i + 7;
2126
2127 /* Setup the packet append pointer. */
2128 new_packet_ptr -> nx_packet_append_ptr = new_packet_ptr -> nx_packet_prepend_ptr + new_packet_ptr -> nx_packet_length;
2129
2130 /* Send the NLST message. */
2131 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), new_packet_ptr, wait_option);
2132
2133 /* Determine if the send was unsuccessful. */
2134 if (status)
2135 {
2136
2137 /* Cleanup data socket. */
2138 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2139
2140 /* Release the packet. */
2141 nx_packet_release(new_packet_ptr);
2142
2143 /* Return error. */
2144 return(status);
2145 }
2146
2147 /* Check if enable passive mode. */
2148 if (ftp_client_ptr -> nx_ftp_client_passive_transfer_enabled == NX_FALSE)
2149 {
2150
2151 /* Now wait for the data connection to connect. */
2152 status = nx_tcp_server_socket_accept(&(ftp_client_ptr -> nx_ftp_client_data_socket), wait_option);
2153
2154 /* Determine if the accept was unsuccessful. */
2155 if (status)
2156 {
2157
2158 /* Cleanup data socket. */
2159 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2160
2161 /* Return error. */
2162 return(status);
2163 }
2164 }
2165
2166 /* Now wait for response from the FTP server control port. */
2167 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &new_packet_ptr, wait_option);
2168
2169 /* Determine if a packet was not received. */
2170 if (status)
2171 {
2172
2173 /* Cleanup data socket. */
2174 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2175
2176 /* Error in NLST request to FTP server. */
2177 return(status);
2178 }
2179
2180 /* We have a packet, setup pointer to the buffer area. */
2181 buffer_ptr = new_packet_ptr -> nx_packet_prepend_ptr;
2182
2183 /* Check for 1xx message, signaling the data port was connected properly and ready for
2184 transfer. */
2185 if ((new_packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '1'))
2186 {
2187
2188 /* Cleanup data socket. */
2189 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2190
2191 /* Release the packet. */
2192 nx_packet_release(new_packet_ptr);
2193
2194 /* Error in NLST request to FTP server. */
2195 return(NX_FTP_EXPECTED_1XX_CODE);
2196 }
2197
2198 /* Release the last packet. */
2199 nx_packet_release(new_packet_ptr);
2200
2201 /* Now read a listing packet from the data socket. */
2202 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_data_socket), packet_ptr, wait_option);
2203
2204 /* Determine if an error occurred. */
2205 if (status)
2206 {
2207
2208 /* Cleanup data socket. */
2209 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2210
2211 /* Map all unsuccessful status to error. */
2212 return(status);
2213 }
2214
2215 /* Determine if the block mode is enabled. */
2216 if (ftp_client_ptr -> nx_ftp_client_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
2217 {
2218
2219 /* Retrieve the block header. */
2220 status = _nx_ftp_client_block_header_retrieve(ftp_client_ptr, (*packet_ptr));
2221
2222 /* Determine if an error occurred. */
2223 if (status)
2224 {
2225
2226 /* Cleanup data socket. */
2227 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2228 }
2229 }
2230
2231 /* Return staus to caller. */
2232 return(status);
2233 }
2234
2235
2236 /**************************************************************************/
2237 /* */
2238 /* FUNCTION RELEASE */
2239 /* */
2240 /* _nxe_ftp_client_directory_listing_continue PORTABLE C */
2241 /* 6.1 */
2242 /* AUTHOR */
2243 /* */
2244 /* Yuxin Zhou, Microsoft Corporation */
2245 /* */
2246 /* DESCRIPTION */
2247 /* */
2248 /* This function checks for errors in the FTP client directory */
2249 /* listing continue. */
2250 /* */
2251 /* */
2252 /* INPUT */
2253 /* */
2254 /* ftp_client_ptr Pointer to FTP client */
2255 /* packet_ptr Destination of for the */
2256 /* received packet pointer */
2257 /* that contains the listing */
2258 /* wait_option Specifies how long to wait */
2259 /* */
2260 /* OUTPUT */
2261 /* */
2262 /* status Completion status */
2263 /* */
2264 /* CALLS */
2265 /* */
2266 /* _nx_ftp_client_directory_listing_continue Actual client directory */
2267 /* listing continue call */
2268 /* */
2269 /* CALLED BY */
2270 /* */
2271 /* Application Code */
2272 /* */
2273 /* RELEASE HISTORY */
2274 /* */
2275 /* DATE NAME DESCRIPTION */
2276 /* */
2277 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2278 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2279 /* resulting in version 6.1 */
2280 /* */
2281 /**************************************************************************/
_nxe_ftp_client_directory_listing_continue(NX_FTP_CLIENT * ftp_client_ptr,NX_PACKET ** packet_ptr,ULONG wait_option)2282 UINT _nxe_ftp_client_directory_listing_continue(NX_FTP_CLIENT *ftp_client_ptr, NX_PACKET **packet_ptr, ULONG wait_option)
2283 {
2284
2285 UINT status;
2286
2287
2288 /* Check for invalid input pointers. */
2289 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID) || (packet_ptr == NX_NULL))
2290 return(NX_PTR_ERROR);
2291
2292 /* Check for appropriate caller. */
2293 NX_THREADS_ONLY_CALLER_CHECKING
2294
2295 /* Call actual client directory listing continue function. */
2296 status = _nx_ftp_client_directory_listing_continue(ftp_client_ptr, packet_ptr, wait_option);
2297
2298 /* Return completion status. */
2299 return(status);
2300 }
2301
2302
2303 /**************************************************************************/
2304 /* */
2305 /* FUNCTION RELEASE */
2306 /* */
2307 /* _nx_ftp_client_directory_listing_continue PORTABLE C */
2308 /* 6.1 */
2309 /* AUTHOR */
2310 /* */
2311 /* Yuxin Zhou, Microsoft Corporation */
2312 /* */
2313 /* DESCRIPTION */
2314 /* */
2315 /* This function gets the next listing buffer. It is assumed that */
2316 /* a successful _nx_ftp_client_directory_listing_get immediately */
2317 /* preceded this call. */
2318 /* */
2319 /* */
2320 /* INPUT */
2321 /* */
2322 /* ftp_client_ptr Pointer to FTP client */
2323 /* packet_ptr Destination of for the */
2324 /* received packet pointer */
2325 /* that contains the listing */
2326 /* wait_option Specifies how long to wait */
2327 /* */
2328 /* OUTPUT */
2329 /* */
2330 /* status Completion status */
2331 /* */
2332 /* CALLS */
2333 /* */
2334 /* _nx_ftp_client_data_socket_cleanup Cleanup data socket */
2335 /* nx_tcp_server_socket_unaccept Unaccept server connection */
2336 /* nx_tcp_server_socket_unlisten Unlisten on server port */
2337 /* nx_tcp_socket_receive Receive packet from server */
2338 /* */
2339 /* CALLED BY */
2340 /* */
2341 /* Application Code */
2342 /* */
2343 /* RELEASE HISTORY */
2344 /* */
2345 /* DATE NAME DESCRIPTION */
2346 /* */
2347 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2348 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2349 /* resulting in version 6.1 */
2350 /* */
2351 /**************************************************************************/
_nx_ftp_client_directory_listing_continue(NX_FTP_CLIENT * ftp_client_ptr,NX_PACKET ** packet_ptr,ULONG wait_option)2352 UINT _nx_ftp_client_directory_listing_continue(NX_FTP_CLIENT *ftp_client_ptr, NX_PACKET **packet_ptr, ULONG wait_option)
2353 {
2354
2355 UINT status;
2356 NX_PACKET *response_ptr;
2357 UCHAR *buffer_ptr;
2358
2359
2360 /* Set packet pointer to NULL. */
2361 *packet_ptr = NX_NULL;
2362
2363 /* Ensure the client is the proper state for directory listing request. */
2364 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_CONNECTED)
2365 return(NX_FTP_NOT_CONNECTED);
2366
2367 /* Now read a listing packet from the data socket. */
2368 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_data_socket), packet_ptr, wait_option);
2369
2370 /* Determine if the block mode is enabled. */
2371 if ((status == NX_SUCCESS) &&
2372 (ftp_client_ptr -> nx_ftp_client_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK))
2373 {
2374
2375 /* Retrieve the block header. */
2376 status = _nx_ftp_client_block_header_retrieve(ftp_client_ptr, (*packet_ptr));
2377 }
2378
2379 /* Determine if an error occurred. */
2380 if (status)
2381 {
2382
2383 /* Cleanup data socket. */
2384 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2385
2386 /* Wait for response from the FTP server on the control socket. */
2387 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &response_ptr, wait_option);
2388
2389 /* Determine if a packet was not received. */
2390 if (status)
2391 {
2392
2393 /* Directory listing error. */
2394 return(status);
2395 }
2396
2397 /* We have a packet, setup pointer to the buffer area. */
2398 buffer_ptr = response_ptr -> nx_packet_prepend_ptr;
2399
2400 /* Check for 2xx message, signaling the "NLST" was processed successfully. */
2401 if ((response_ptr -> nx_packet_length >= 3) && (buffer_ptr[0] == '2'))
2402 {
2403
2404 /* Release the packet. */
2405 nx_packet_release(response_ptr);
2406
2407 /* Appropriate end of listing error. */
2408 return(NX_FTP_END_OF_LISTING);
2409 }
2410 else
2411 {
2412
2413 /* Release the packet. */
2414 nx_packet_release(response_ptr);
2415
2416 /* Map all other unsuccessful status to error. */
2417 return(NX_FTP_EXPECTED_2XX_CODE);
2418 }
2419 }
2420
2421 /* Return success to caller. */
2422 return(status);
2423 }
2424
2425
2426 /**************************************************************************/
2427 /* */
2428 /* FUNCTION RELEASE */
2429 /* */
2430 /* _nxe_ftp_client_disconnect PORTABLE C */
2431 /* 6.1 */
2432 /* AUTHOR */
2433 /* */
2434 /* Yuxin Zhou, Microsoft Corporation */
2435 /* */
2436 /* DESCRIPTION */
2437 /* */
2438 /* This function checks for errors in the FTP client disconnect. */
2439 /* */
2440 /* */
2441 /* INPUT */
2442 /* */
2443 /* ftp_client_ptr Pointer to FTP client */
2444 /* wait_option Specifies how long to wait */
2445 /* */
2446 /* OUTPUT */
2447 /* */
2448 /* status Completion status */
2449 /* */
2450 /* CALLS */
2451 /* */
2452 /* _nx_ftp_client_disconnect Actual client disconnect call */
2453 /* */
2454 /* CALLED BY */
2455 /* */
2456 /* Application Code */
2457 /* */
2458 /* RELEASE HISTORY */
2459 /* */
2460 /* DATE NAME DESCRIPTION */
2461 /* */
2462 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2463 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2464 /* resulting in version 6.1 */
2465 /* */
2466 /**************************************************************************/
_nxe_ftp_client_disconnect(NX_FTP_CLIENT * ftp_client_ptr,ULONG wait_option)2467 UINT _nxe_ftp_client_disconnect(NX_FTP_CLIENT *ftp_client_ptr, ULONG wait_option)
2468 {
2469
2470 UINT status;
2471
2472
2473 /* Check for invalid input pointers. */
2474 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID))
2475 return(NX_PTR_ERROR);
2476
2477 /* Check for appropriate caller. */
2478 NX_THREADS_ONLY_CALLER_CHECKING
2479
2480 /* Call actual client disconnect function. */
2481 status = _nx_ftp_client_disconnect(ftp_client_ptr, wait_option);
2482
2483 /* Return completion status. */
2484 return(status);
2485 }
2486
2487
2488 /**************************************************************************/
2489 /* */
2490 /* FUNCTION RELEASE */
2491 /* */
2492 /* _nx_ftp_client_disconnect PORTABLE C */
2493 /* 6.1 */
2494 /* AUTHOR */
2495 /* */
2496 /* Yuxin Zhou, Microsoft Corporation */
2497 /* */
2498 /* DESCRIPTION */
2499 /* */
2500 /* This function disconnects a previously established FTP connection. */
2501 /* */
2502 /* */
2503 /* INPUT */
2504 /* */
2505 /* ftp_client_ptr Pointer to FTP client */
2506 /* wait_option Specifies how long to wait */
2507 /* */
2508 /* OUTPUT */
2509 /* */
2510 /* status Completion status */
2511 /* */
2512 /* CALLS */
2513 /* */
2514 /* nx_packet_allocate Allocate packet */
2515 /* nx_packet_release Release packet */
2516 /* nx_tcp_client_socket_unbind Unbind a socket */
2517 /* nx_tcp_socket_disconnect Disconnect a socket */
2518 /* nx_tcp_socket_receive Receive response from server */
2519 /* nx_tcp_socket_send Send request to server */
2520 /* */
2521 /* CALLED BY */
2522 /* */
2523 /* Application Code */
2524 /* */
2525 /* RELEASE HISTORY */
2526 /* */
2527 /* DATE NAME DESCRIPTION */
2528 /* */
2529 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2530 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2531 /* resulting in version 6.1 */
2532 /* */
2533 /**************************************************************************/
_nx_ftp_client_disconnect(NX_FTP_CLIENT * ftp_client_ptr,ULONG wait_option)2534 UINT _nx_ftp_client_disconnect(NX_FTP_CLIENT *ftp_client_ptr, ULONG wait_option)
2535 {
2536
2537 NX_PACKET *packet_ptr;
2538 UCHAR *buffer_ptr;
2539 UINT status;
2540
2541
2542 /* Determine if the client is in a not connected state. */
2543 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_CONNECTED)
2544 {
2545
2546 /* Already connected, return an error. */
2547 return(NX_FTP_NOT_CONNECTED);
2548 }
2549
2550 /* Enter the not connected state. */
2551 ftp_client_ptr -> nx_ftp_client_state = NX_FTP_STATE_NOT_CONNECTED;
2552
2553 /* Allocate a packet for sending the port and IP address. */
2554 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
2555
2556 /* Determine if the packet allocation was successful. */
2557 if (status)
2558 {
2559
2560 /* Clean up connection socket. */
2561 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
2562 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
2563
2564 /* Return error. */
2565 return(status);
2566 }
2567
2568 /* Check if out of boundary. */
2569 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 6)
2570 {
2571
2572 /* Clean up connection socket. */
2573 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
2574 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
2575
2576 /* Release the packet. */
2577 nx_packet_release(packet_ptr);
2578
2579 /* Set the error status. */
2580 return(NX_FTP_FAILED);
2581 }
2582
2583 /* We have a packet, setup pointer to the buffer area. */
2584 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
2585
2586 /* Build QUIT message to end the FTP connection. */
2587 buffer_ptr[0] = 'Q';
2588 buffer_ptr[1] = 'U';
2589 buffer_ptr[2] = 'I';
2590 buffer_ptr[3] = 'T';
2591 buffer_ptr[4] = 13;
2592 buffer_ptr[5] = 10;
2593
2594 /* Set the packet length. */
2595 packet_ptr -> nx_packet_length = 6;
2596
2597 /* Setup the packet append pointer. */
2598 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
2599
2600 /* Send the QUIT message. */
2601 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
2602
2603 /* Determine if the send was unsuccessful. */
2604 if (status)
2605 {
2606
2607 /* Clean up connection socket. */
2608 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
2609 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
2610
2611 /* Release the packet. */
2612 nx_packet_release(packet_ptr);
2613
2614 /* Return error. */
2615 return(status);
2616 }
2617
2618 /* Wait for response from the FTP server. */
2619 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
2620
2621 /* Determine if a packet was not received. */
2622 if (status)
2623 {
2624
2625 /* Clean up connection socket. */
2626 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
2627 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
2628
2629 /* Unable to connect socket to server FTP control port. */
2630 return(status);
2631 }
2632
2633 /* We have a packet, setup pointer to the buffer area. */
2634 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
2635
2636 /* Check for 2xx message, signaling the disconnect was processed properly. */
2637 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2'))
2638 {
2639
2640 /* Clean up connection socket. */
2641 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
2642 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
2643
2644 /* Release the packet. */
2645 nx_packet_release(packet_ptr);
2646
2647 /* Return error. */
2648 return(NX_FTP_EXPECTED_2XX_CODE);
2649 }
2650
2651 /* Success. Disconnect and unbind the control socket. */
2652 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_control_socket), wait_option);
2653 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_control_socket));
2654
2655 /* Release the packet. */
2656 nx_packet_release(packet_ptr);
2657
2658 /* Return success to caller. */
2659 return(NX_SUCCESS);
2660 }
2661
2662
2663 /**************************************************************************/
2664 /* */
2665 /* FUNCTION RELEASE */
2666 /* */
2667 /* _nxe_ftp_client_file_close PORTABLE C */
2668 /* 6.1 */
2669 /* AUTHOR */
2670 /* */
2671 /* Yuxin Zhou, Microsoft Corporation */
2672 /* */
2673 /* DESCRIPTION */
2674 /* */
2675 /* This function checks for errors in the FTP client file close. */
2676 /* */
2677 /* */
2678 /* INPUT */
2679 /* */
2680 /* ftp_client_ptr Pointer to FTP client */
2681 /* wait_option Specifies how long to wait */
2682 /* */
2683 /* OUTPUT */
2684 /* */
2685 /* status Completion status */
2686 /* */
2687 /* CALLS */
2688 /* */
2689 /* _nx_ftp_client_file_close Actual client file close call */
2690 /* */
2691 /* CALLED BY */
2692 /* */
2693 /* Application Code */
2694 /* */
2695 /* RELEASE HISTORY */
2696 /* */
2697 /* DATE NAME DESCRIPTION */
2698 /* */
2699 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2700 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2701 /* resulting in version 6.1 */
2702 /* */
2703 /**************************************************************************/
_nxe_ftp_client_file_close(NX_FTP_CLIENT * ftp_client_ptr,ULONG wait_option)2704 UINT _nxe_ftp_client_file_close(NX_FTP_CLIENT *ftp_client_ptr, ULONG wait_option)
2705 {
2706
2707 UINT status;
2708
2709
2710 /* Check for invalid input pointers. */
2711 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID))
2712 return(NX_PTR_ERROR);
2713
2714
2715 /* Check for appropriate caller. */
2716 NX_THREADS_ONLY_CALLER_CHECKING
2717
2718 /* Call actual client file close function. */
2719 status = _nx_ftp_client_file_close(ftp_client_ptr, wait_option);
2720
2721 /* Return completion status. */
2722 return(status);
2723 }
2724
2725
2726 /**************************************************************************/
2727 /* */
2728 /* FUNCTION RELEASE */
2729 /* */
2730 /* _nx_ftp_client_file_close PORTABLE C */
2731 /* 6.1 */
2732 /* AUTHOR */
2733 /* */
2734 /* Yuxin Zhou, Microsoft Corporation */
2735 /* */
2736 /* DESCRIPTION */
2737 /* */
2738 /* This function closes a previously open client FTP file. */
2739 /* */
2740 /* */
2741 /* INPUT */
2742 /* */
2743 /* ftp_client_ptr Pointer to FTP client */
2744 /* wait_option Specifies how long to wait */
2745 /* */
2746 /* OUTPUT */
2747 /* */
2748 /* status Completion status */
2749 /* */
2750 /* CALLS */
2751 /* */
2752 /* _nx_ftp_client_data_socket_cleanup Cleanup data socket */
2753 /* nx_packet_release Release packet */
2754 /* nx_tcp_server_socket_unaccept Unaccept server connection */
2755 /* nx_tcp_server_socket_unlisten Unlisten on server socket */
2756 /* nx_tcp_socket_disconnect Disconnect a socket */
2757 /* nx_tcp_socket_receive Receive response from server */
2758 /* */
2759 /* CALLED BY */
2760 /* */
2761 /* Application Code */
2762 /* */
2763 /* RELEASE HISTORY */
2764 /* */
2765 /* DATE NAME DESCRIPTION */
2766 /* */
2767 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2768 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2769 /* resulting in version 6.1 */
2770 /* */
2771 /**************************************************************************/
_nx_ftp_client_file_close(NX_FTP_CLIENT * ftp_client_ptr,ULONG wait_option)2772 UINT _nx_ftp_client_file_close(NX_FTP_CLIENT *ftp_client_ptr, ULONG wait_option)
2773 {
2774
2775 NX_PACKET *packet_ptr;
2776 UCHAR *buffer_ptr;
2777 UINT status;
2778
2779
2780 /* Ensure the client is in the proper state for closing the socket. */
2781 if (ftp_client_ptr -> nx_ftp_client_state == NX_FTP_STATE_NOT_CONNECTED)
2782 return(NX_FTP_NOT_CONNECTED);
2783 else if ((ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_OPEN) &&
2784 (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_WRITE_OPEN))
2785 return(NX_FTP_NOT_OPEN);
2786
2787 /* Cleanup data socket. */
2788 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
2789
2790 /* Set the state to connected. */
2791 ftp_client_ptr -> nx_ftp_client_state = NX_FTP_STATE_CONNECTED;
2792
2793 /* Wait for response from the FTP server. */
2794 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
2795
2796 /* Determine if a packet was not received. */
2797 if (status)
2798 {
2799
2800 /* Unable to connect socket to server FTP control port. */
2801 return(status);
2802 }
2803
2804 /* We have a packet, setup pointer to the packet payload area. */
2805 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
2806
2807 /* Check for 2xx message, signaling the close was processed properly. */
2808 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2'))
2809 {
2810
2811 /* Release the packet. */
2812 nx_packet_release(packet_ptr);
2813
2814 /* Return error. */
2815 return(NX_FTP_EXPECTED_2XX_CODE);
2816 }
2817
2818 /* Release the packet. */
2819 nx_packet_release(packet_ptr);
2820
2821 /* Return success to caller. */
2822 return(NX_SUCCESS);
2823 }
2824
2825
2826 /**************************************************************************/
2827 /* */
2828 /* FUNCTION RELEASE */
2829 /* */
2830 /* _nxe_ftp_client_file_delete PORTABLE C */
2831 /* 6.1 */
2832 /* AUTHOR */
2833 /* */
2834 /* Yuxin Zhou, Microsoft Corporation */
2835 /* */
2836 /* DESCRIPTION */
2837 /* */
2838 /* This function checks for errors in the FTP client file delete. */
2839 /* */
2840 /* Note: The string length of file_name is limited by the packet */
2841 /* payload size. */
2842 /* */
2843 /* INPUT */
2844 /* */
2845 /* ftp_client_ptr Pointer to FTP client */
2846 /* file_name File name to delete */
2847 /* wait_option Specifies how long to wait */
2848 /* */
2849 /* OUTPUT */
2850 /* */
2851 /* status Completion status */
2852 /* */
2853 /* CALLS */
2854 /* */
2855 /* _nx_ftp_client_file_delete Actual client file delete call*/
2856 /* */
2857 /* CALLED BY */
2858 /* */
2859 /* Application Code */
2860 /* */
2861 /* RELEASE HISTORY */
2862 /* */
2863 /* DATE NAME DESCRIPTION */
2864 /* */
2865 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2866 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2867 /* resulting in version 6.1 */
2868 /* */
2869 /**************************************************************************/
_nxe_ftp_client_file_delete(NX_FTP_CLIENT * ftp_client_ptr,CHAR * file_name,ULONG wait_option)2870 UINT _nxe_ftp_client_file_delete(NX_FTP_CLIENT *ftp_client_ptr, CHAR *file_name, ULONG wait_option)
2871 {
2872
2873 UINT status;
2874
2875
2876 /* Check for invalid input pointers. */
2877 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID) || (file_name == NX_NULL))
2878 return(NX_PTR_ERROR);
2879
2880 /* Check for appropriate caller. */
2881 NX_THREADS_ONLY_CALLER_CHECKING
2882
2883 /* Call actual client file delete function. */
2884 status = _nx_ftp_client_file_delete(ftp_client_ptr, file_name, wait_option);
2885
2886 /* Return completion status. */
2887 return(status);
2888 }
2889
2890
2891 /**************************************************************************/
2892 /* */
2893 /* FUNCTION RELEASE */
2894 /* */
2895 /* _nx_ftp_client_file_delete PORTABLE C */
2896 /* 6.1 */
2897 /* AUTHOR */
2898 /* */
2899 /* Yuxin Zhou, Microsoft Corporation */
2900 /* */
2901 /* DESCRIPTION */
2902 /* */
2903 /* This function deletes the specified file on the FTP */
2904 /* server. */
2905 /* */
2906 /* Note: The string length of file_name is limited by the packet */
2907 /* payload size. */
2908 /* */
2909 /* INPUT */
2910 /* */
2911 /* ftp_client_ptr Pointer to FTP client */
2912 /* file_name File name to delete */
2913 /* wait_option Specifies how long to wait */
2914 /* */
2915 /* OUTPUT */
2916 /* */
2917 /* status Completion status */
2918 /* */
2919 /* CALLS */
2920 /* */
2921 /* nx_packet_allocate Allocate packet */
2922 /* nx_packet_release Release packet */
2923 /* nx_tcp_socket_receive Receive packet from server */
2924 /* nx_tcp_socket_send Send data packet to server */
2925 /* */
2926 /* CALLED BY */
2927 /* */
2928 /* Application Code */
2929 /* */
2930 /* RELEASE HISTORY */
2931 /* */
2932 /* DATE NAME DESCRIPTION */
2933 /* */
2934 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2935 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2936 /* resulting in version 6.1 */
2937 /* */
2938 /**************************************************************************/
_nx_ftp_client_file_delete(NX_FTP_CLIENT * ftp_client_ptr,CHAR * file_name,ULONG wait_option)2939 UINT _nx_ftp_client_file_delete(NX_FTP_CLIENT *ftp_client_ptr, CHAR *file_name, ULONG wait_option)
2940 {
2941
2942 UINT i;
2943 UCHAR *buffer_ptr;
2944 NX_PACKET *packet_ptr;
2945 UINT status;
2946
2947
2948 /* Ensure the client is the proper state for file delete request. */
2949 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_CONNECTED)
2950 return(NX_FTP_NOT_CONNECTED);
2951
2952 /* Allocate a packet for sending the file delete command. */
2953 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
2954
2955 /* Determine if the packet allocation was successful. */
2956 if (status)
2957 {
2958
2959 /* Return error. */
2960 return(status);
2961 }
2962
2963 /* Check if out of boundary. */
2964 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 7)
2965 {
2966
2967 /* Release the packet. */
2968 nx_packet_release(packet_ptr);
2969
2970 /* Set the error status. */
2971 return(NX_FTP_FAILED);
2972 }
2973
2974 /* We have a packet, setup pointer to the buffer area. */
2975 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
2976
2977 /* Now build "DELE" message to indicate file delete. */
2978 buffer_ptr[0] = 'D';
2979 buffer_ptr[1] = 'E';
2980 buffer_ptr[2] = 'L';
2981 buffer_ptr[3] = 'E';
2982 buffer_ptr[4] = ' ';
2983
2984 /* Copy the file name into the message. */
2985 for(i = 0; file_name[i]; i++)
2986 {
2987
2988 /* Check if out of boundary. */
2989 if ((i + 7) >= (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr))
2990 {
2991
2992 /* Release the packet. */
2993 nx_packet_release(packet_ptr);
2994
2995 /* Set the error status. */
2996 return(NX_FTP_FAILED);
2997 }
2998
2999 /* Copy character of the file name. */
3000 buffer_ptr[5+i] = (UCHAR)file_name[i];
3001 }
3002
3003 /* Set the CR/LF. */
3004 buffer_ptr[i+5] = 13;
3005 buffer_ptr[i+6] = 10;
3006
3007 /* Set the packet length. */
3008 packet_ptr -> nx_packet_length = i+7;
3009
3010 /* Setup the packet append pointer. */
3011 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
3012
3013 /* Send the DELE message. */
3014 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
3015
3016 /* Determine if the send was unsuccessful. */
3017 if (status)
3018 {
3019
3020 /* Release the packet. */
3021 nx_packet_release(packet_ptr);
3022
3023 /* Return error. */
3024 return(status);
3025 }
3026
3027 /* Wait for response from the FTP server. */
3028 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
3029
3030 /* Determine if a packet was not received. */
3031 if (status)
3032 {
3033
3034 /* DELE error. */
3035 return(status);
3036 }
3037
3038 /* We have a packet, setup pointer to the buffer area. */
3039 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
3040
3041 /* Check for 2xx message, signaling the "DELE" was processed successfully. */
3042 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2'))
3043 {
3044
3045 /* Release the packet. */
3046 nx_packet_release(packet_ptr);
3047
3048 /* File delete error. */
3049 return(NX_FTP_EXPECTED_2XX_CODE);
3050 }
3051
3052 /* Yes, the file was deleted. */
3053
3054 /* Release the packet. */
3055 nx_packet_release(packet_ptr);
3056
3057 /* Return success to caller. */
3058 return(NX_SUCCESS);
3059 }
3060
3061 /**************************************************************************/
3062 /* */
3063 /* FUNCTION RELEASE */
3064 /* */
3065 /* _nxe_ftp_client_passive_mode_set PORTABLE C */
3066 /* 6.1 */
3067 /* AUTHOR */
3068 /* */
3069 /* Yuxin Zhou, Microsoft Corporation */
3070 /* */
3071 /* DESCRIPTION */
3072 /* */
3073 /* This function sets the request to passive mode. Once this is set */
3074 /* the Client will send a PASV command preceding any FTP Client command*/
3075 /* involving transferring data on the data socket. */
3076 /* */
3077 /* INPUT */
3078 /* */
3079 /* ftp_client_ptr Pointer to FTP client */
3080 /* passive_mode_enabled True to enable */
3081 /* False to disable */
3082 /* */
3083 /* OUTPUT */
3084 /* */
3085 /* NX_PTR_ERROR Invalid pointer input */
3086 /* NX_INVALID_PARAMETERS Invalid non pointer input */
3087 /* status Completion status */
3088 /* */
3089 /* CALLS */
3090 /* None */
3091 /* */
3092 /* CALLED BY */
3093 /* */
3094 /* Application Code */
3095 /* */
3096 /* RELEASE HISTORY */
3097 /* */
3098 /* DATE NAME DESCRIPTION */
3099 /* */
3100 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3101 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3102 /* resulting in version 6.1 */
3103 /* */
3104 /**************************************************************************/
_nxe_ftp_client_passive_mode_set(NX_FTP_CLIENT * ftp_client_ptr,UINT passive_mode_enabled)3105 UINT _nxe_ftp_client_passive_mode_set(NX_FTP_CLIENT *ftp_client_ptr, UINT passive_mode_enabled)
3106 {
3107
3108 UINT status;
3109
3110 if (ftp_client_ptr == NX_NULL)
3111 {
3112 return NX_PTR_ERROR;
3113 }
3114
3115 if ((passive_mode_enabled != NX_TRUE) && (passive_mode_enabled != NX_FALSE))
3116 {
3117 return NX_INVALID_PARAMETERS;
3118 }
3119
3120 status = _nx_ftp_client_passive_mode_set(ftp_client_ptr, passive_mode_enabled);
3121
3122 return status;
3123
3124 }
3125
3126
3127 /**************************************************************************/
3128 /* */
3129 /* FUNCTION RELEASE */
3130 /* */
3131 /* _nx_ftp_client_passive_mode_set PORTABLE C */
3132 /* 6.1 */
3133 /* AUTHOR */
3134 /* */
3135 /* Yuxin Zhou, Microsoft Corporation */
3136 /* */
3137 /* DESCRIPTION */
3138 /* */
3139 /* This function sets the request to passive mode. Once this is set */
3140 /* the Client will send a PASV command preceding any FTP Client command*/
3141 /* for accessing a server data port. If passive mode is not set, */
3142 /* the FTP Client will send and receive data via active transfer mode. */
3143 /* */
3144 /* INPUT */
3145 /* */
3146 /* ftp_client_ptr Pointer to FTP client */
3147 /* passive_mode_enabled True to enable passive mode */
3148 /* False to disable passive mode */
3149 /* */
3150 /* OUTPUT */
3151 /* */
3152 /* NX_SUCCESS Successful completion status */
3153 /* */
3154 /* CALLS */
3155 /* None */
3156 /* */
3157 /* CALLED BY */
3158 /* */
3159 /* Application Code */
3160 /* */
3161 /* RELEASE HISTORY */
3162 /* */
3163 /* DATE NAME DESCRIPTION */
3164 /* */
3165 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3166 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3167 /* resulting in version 6.1 */
3168 /* */
3169 /**************************************************************************/
_nx_ftp_client_passive_mode_set(NX_FTP_CLIENT * ftp_client_ptr,UINT passive_mode_enabled)3170 UINT _nx_ftp_client_passive_mode_set(NX_FTP_CLIENT *ftp_client_ptr, UINT passive_mode_enabled)
3171 {
3172
3173 /* Set the transfer status according to the passive mode enabled input. */
3174 ftp_client_ptr -> nx_ftp_client_passive_transfer_enabled = passive_mode_enabled;
3175
3176 return(NX_SUCCESS);
3177 }
3178
3179
3180 /**************************************************************************/
3181 /* */
3182 /* FUNCTION RELEASE */
3183 /* */
3184 /* _nxe_ftp_client_transfer_mode_set PORTABLE C */
3185 /* 6.1 */
3186 /* AUTHOR */
3187 /* */
3188 /* Yuxin Zhou, Microsoft Corporation */
3189 /* */
3190 /* DESCRIPTION */
3191 /* */
3192 /* This function checks for errors in the FTP transfer mode set. */
3193 /* */
3194 /* INPUT */
3195 /* */
3196 /* ftp_client_ptr Pointer to FTP client */
3197 /* transfer_mode Transfer mode */
3198 /* */
3199 /* OUTPUT */
3200 /* */
3201 /* NX_PTR_ERROR Invalid pointer input */
3202 /* status Completion status */
3203 /* */
3204 /* CALLS */
3205 /* */
3206 /* _nx_ftp_client_transfer_mode_set Actual transfer mode set */
3207 /* */
3208 /* CALLED BY */
3209 /* */
3210 /* Application Code */
3211 /* */
3212 /* RELEASE HISTORY */
3213 /* */
3214 /* DATE NAME DESCRIPTION */
3215 /* */
3216 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3217 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3218 /* resulting in version 6.1 */
3219 /* */
3220 /**************************************************************************/
_nxe_ftp_client_transfer_mode_set(NX_FTP_CLIENT * ftp_client_ptr,UINT transfer_mode)3221 UINT _nxe_ftp_client_transfer_mode_set(NX_FTP_CLIENT *ftp_client_ptr, UINT transfer_mode)
3222 {
3223
3224 UINT status;
3225
3226 /* Check for valid pointer. */
3227 if (ftp_client_ptr == NX_NULL)
3228 {
3229 return(NX_PTR_ERROR);
3230 }
3231
3232 /* Check for appropriate caller. */
3233 NX_THREADS_ONLY_CALLER_CHECKING
3234
3235 /* Call actual transfer mode set function. */
3236 status = _nx_ftp_client_transfer_mode_set(ftp_client_ptr, transfer_mode);
3237
3238 return(status);
3239 }
3240
3241
3242 /**************************************************************************/
3243 /* */
3244 /* FUNCTION RELEASE */
3245 /* */
3246 /* _nx_ftp_client_transfer_mode_set PORTABLE C */
3247 /* 6.1 */
3248 /* AUTHOR */
3249 /* */
3250 /* Yuxin Zhou, Microsoft Corporation */
3251 /* */
3252 /* DESCRIPTION */
3253 /* */
3254 /* This function sets the transfer mode. */
3255 /* Note: just support stream mode and block mode yet. */
3256 /* */
3257 /* INPUT */
3258 /* */
3259 /* ftp_client_ptr Pointer to FTP client */
3260 /* transfer_mode Transfer mode */
3261 /* */
3262 /* OUTPUT */
3263 /* */
3264 /* NX_SUCCESS Successful completion status */
3265 /* NX_INVALID_PARAMETERS Invalid non pointer input */
3266 /* */
3267 /* CALLS */
3268 /* */
3269 /* None */
3270 /* */
3271 /* CALLED BY */
3272 /* */
3273 /* Application Code */
3274 /* */
3275 /* RELEASE HISTORY */
3276 /* */
3277 /* DATE NAME DESCRIPTION */
3278 /* */
3279 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3280 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3281 /* resulting in version 6.1 */
3282 /* */
3283 /**************************************************************************/
_nx_ftp_client_transfer_mode_set(NX_FTP_CLIENT * ftp_client_ptr,UINT transfer_mode)3284 UINT _nx_ftp_client_transfer_mode_set(NX_FTP_CLIENT *ftp_client_ptr, UINT transfer_mode)
3285 {
3286
3287 /* Check for transfer mode. */
3288 if ((transfer_mode != NX_FTP_TRANSFER_MODE_STREAM) &&
3289 (transfer_mode != NX_FTP_TRANSFER_MODE_BLOCK))
3290 {
3291 return(NX_INVALID_PARAMETERS);
3292 }
3293
3294 /* Set the transfer mode. */
3295 ftp_client_ptr -> nx_ftp_client_transfer_mode = transfer_mode;
3296
3297 return(NX_SUCCESS);
3298 }
3299
3300
3301 /**************************************************************************/
3302 /* */
3303 /* FUNCTION RELEASE */
3304 /* */
3305 /* _nxe_ftp_client_file_open PORTABLE C */
3306 /* 6.1 */
3307 /* AUTHOR */
3308 /* */
3309 /* Yuxin Zhou, Microsoft Corporation */
3310 /* */
3311 /* DESCRIPTION */
3312 /* */
3313 /* This function checks for errors in the FTP client file open. */
3314 /* */
3315 /* Note: The string length of file_name is limited by the packet */
3316 /* payload size. */
3317 /* */
3318 /* INPUT */
3319 /* */
3320 /* ftp_client_ptr Pointer to FTP client */
3321 /* file_name Client file name */
3322 /* open_type Open for read or open for */
3323 /* write */
3324 /* wait_option Specifies how long to wait */
3325 /* */
3326 /* OUTPUT */
3327 /* */
3328 /* status Completion status */
3329 /* */
3330 /* CALLS */
3331 /* */
3332 /* _nx_ftp_client_file_open Actual client file open call */
3333 /* */
3334 /* CALLED BY */
3335 /* */
3336 /* Application Code */
3337 /* */
3338 /* RELEASE HISTORY */
3339 /* */
3340 /* DATE NAME DESCRIPTION */
3341 /* */
3342 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3343 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3344 /* resulting in version 6.1 */
3345 /* */
3346 /**************************************************************************/
_nxe_ftp_client_file_open(NX_FTP_CLIENT * ftp_client_ptr,CHAR * file_name,UINT open_type,ULONG wait_option)3347 UINT _nxe_ftp_client_file_open(NX_FTP_CLIENT *ftp_client_ptr, CHAR *file_name, UINT open_type, ULONG wait_option)
3348 {
3349
3350 UINT status;
3351
3352
3353 /* Check for invalid input pointers. */
3354 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID) || (file_name == NX_NULL))
3355 return(NX_PTR_ERROR);
3356
3357 /* Check for illegal open option type. */
3358 if ((open_type != NX_FTP_OPEN_FOR_READ) && (open_type != NX_FTP_OPEN_FOR_WRITE))
3359 return(NX_OPTION_ERROR);
3360
3361 /* Check for appropriate caller. */
3362 NX_THREADS_ONLY_CALLER_CHECKING
3363
3364 /* Call actual client file open function. */
3365 status = _nx_ftp_client_file_open(ftp_client_ptr, file_name, open_type, wait_option);
3366
3367 /* Return completion status. */
3368 return(status);
3369 }
3370
3371
3372 /**************************************************************************/
3373 /* */
3374 /* FUNCTION RELEASE */
3375 /* */
3376 /* _nx_ftp_client_file_open PORTABLE C */
3377 /* 6.1 */
3378 /* AUTHOR */
3379 /* */
3380 /* Yuxin Zhou, Microsoft Corporation */
3381 /* */
3382 /* DESCRIPTION */
3383 /* */
3384 /* This function opens a client FTP file. */
3385 /* */
3386 /* Note: The string length of file_name is limited by the packet */
3387 /* payload size. */
3388 /* */
3389 /* INPUT */
3390 /* */
3391 /* ftp_client_ptr Pointer to FTP client */
3392 /* file_name Client file name */
3393 /* open_type Open for read or open for */
3394 /* write */
3395 /* wait_option Specifies how long to wait */
3396 /* */
3397 /* OUTPUT */
3398 /* */
3399 /* status Completion status */
3400 /* */
3401 /* CALLS */
3402 /* */
3403 /* _nx_ftp_client_packet_allocate Allocate packet */
3404 /* _nx_ftp_client_active_transfer_setup Setup active transfer */
3405 /* _nx_ftp_client_passive_transfer_setup Setup passive transfer */
3406 /* _nx_ftp_client_block_mode_send Send block mode command */
3407 /* _nx_ftp_client_data_socket_cleanup Cleanup data socket */
3408 /* nx_packet_release Release packet */
3409 /* nx_tcp_server_socket_accept Connect data socket to server */
3410 /* nx_tcp_socket_receive Receive response from server */
3411 /* nx_tcp_socket_send Send request to server */
3412 /* */
3413 /* CALLED BY */
3414 /* */
3415 /* Application Code */
3416 /* */
3417 /* RELEASE HISTORY */
3418 /* */
3419 /* DATE NAME DESCRIPTION */
3420 /* */
3421 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3422 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3423 /* resulting in version 6.1 */
3424 /* */
3425 /**************************************************************************/
_nx_ftp_client_file_open(NX_FTP_CLIENT * ftp_client_ptr,CHAR * file_name,UINT open_type,ULONG wait_option)3426 UINT _nx_ftp_client_file_open(NX_FTP_CLIENT *ftp_client_ptr, CHAR *file_name, UINT open_type, ULONG wait_option)
3427 {
3428
3429 UINT i;
3430 UCHAR *buffer_ptr;
3431 NX_PACKET *packet_ptr;
3432 UINT status;
3433
3434
3435 /* Ensure the client is the proper state for an open request. */
3436 if (ftp_client_ptr -> nx_ftp_client_state == NX_FTP_STATE_NOT_CONNECTED)
3437 return(NX_FTP_NOT_CONNECTED);
3438 else if (ftp_client_ptr -> nx_ftp_client_state == NX_FTP_STATE_OPEN)
3439 return(NX_FTP_NOT_CLOSED);
3440 else if (ftp_client_ptr -> nx_ftp_client_state == NX_FTP_STATE_WRITE_OPEN)
3441 return(NX_FTP_NOT_CLOSED);
3442
3443 /* Flush the control socket queue for any old messages before starting a new file open request. */
3444 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, 1);
3445
3446 /* Determine if a packet was received. */
3447 if (status == NX_SUCCESS)
3448 {
3449
3450 /* Just discard it. */
3451 nx_packet_release(packet_ptr);
3452 }
3453
3454 /* Allocate a packet for sending the TYPE command. */
3455 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
3456
3457 /* Determine if the packet allocation was successful. */
3458 if (status != NX_SUCCESS)
3459 {
3460
3461 /* Return error. */
3462 return(status);
3463 }
3464
3465 /* Check if out of boundary. */
3466 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 8)
3467 {
3468
3469 /* Release the packet. */
3470 nx_packet_release(packet_ptr);
3471
3472 /* Set the error status. */
3473 return(NX_INVALID_PACKET);
3474 }
3475
3476 /* We have a packet, setup pointer to the buffer area. */
3477 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
3478
3479 /* Now build "TYPE I" message to indicate binary file transfer. */
3480 buffer_ptr[0] = 'T';
3481 buffer_ptr[1] = 'Y';
3482 buffer_ptr[2] = 'P';
3483 buffer_ptr[3] = 'E';
3484 buffer_ptr[4] = ' ';
3485 buffer_ptr[5] = 'I';
3486
3487 /* Set the CR/LF. */
3488 buffer_ptr[6] = 13;
3489 buffer_ptr[7] = 10;
3490
3491 /* Set the packet length. */
3492 packet_ptr -> nx_packet_length = 8;
3493
3494 /* Setup the packet append pointer. */
3495 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
3496
3497 /* Send the TYPE message. */
3498 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
3499
3500 /* Determine if the send was unsuccessful. */
3501 if (status != NX_SUCCESS)
3502 {
3503
3504 /* Release the packet. */
3505 nx_packet_release(packet_ptr);
3506
3507 /* Return error. */
3508 return(status);
3509 }
3510
3511 /* Wait for response from the FTP server. */
3512 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
3513
3514 /* Determine if a packet was not received. */
3515 if (status != NX_SUCCESS)
3516 {
3517
3518 /* Unable to open file with FTP server. */
3519 return(status);
3520 }
3521
3522 #ifndef NX_DISABLE_PACKET_CHAIN
3523 if (packet_ptr -> nx_packet_next)
3524 {
3525
3526 /* Release the packet. */
3527 nx_packet_release(packet_ptr);
3528
3529 /* Return. */
3530 return(NX_INVALID_PACKET);
3531 }
3532 #endif /* NX_DISABLE_PACKET_CHAIN */
3533
3534 /* We have a packet, setup pointer to the buffer area. */
3535 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
3536
3537 /* Check for 2xx message, signaling the "TYPE I" was received properly. */
3538 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2'))
3539 {
3540
3541 /* Release the packet. */
3542 nx_packet_release(packet_ptr);
3543
3544 /* Unable to open file with FTP server. */
3545 return(NX_FTP_EXPECTED_2XX_CODE);
3546 }
3547
3548 /* Release the packet. */
3549 nx_packet_release(packet_ptr);
3550
3551 /* Divert to passive mode operation if passive mode is enabled. */
3552 if (ftp_client_ptr -> nx_ftp_client_passive_transfer_enabled)
3553 {
3554
3555 /* Set up the passive transfer mode:
3556 Send PASV request,
3557 Get server IP and port to connect to,
3558 Open data socket based on server info in PASV response. */
3559 status = _nx_ftp_client_passive_transfer_setup(ftp_client_ptr, wait_option);
3560 }
3561 else
3562 {
3563
3564 /* Open in active transfer mode. */
3565 status = _nx_ftp_client_active_transfer_setup(ftp_client_ptr, wait_option);
3566 }
3567
3568 /* Determine if set up successful. */
3569 if (status)
3570 {
3571 return(status);
3572 }
3573
3574 /* Check if enable block mode. */
3575 if (ftp_client_ptr -> nx_ftp_client_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
3576 {
3577
3578 /* Send MODE B command to FTP server. */
3579 status = _nx_ftp_client_block_mode_send(ftp_client_ptr, wait_option);
3580
3581 /* Determine if the send was unsuccessful. */
3582 if (status != NX_SUCCESS)
3583 {
3584
3585 /* Cleanup data socket. */
3586 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
3587 return(status);
3588 }
3589 }
3590
3591 /* Allocate a packet for sending the TYPE command. */
3592 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
3593
3594 /* Determine if the packet allocation was successful. */
3595 if (status != NX_SUCCESS)
3596 {
3597
3598 /* Cleanup data socket. */
3599 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
3600
3601 /* Return error. */
3602 return(status);
3603 }
3604
3605 /* We have a packet, setup pointer to the buffer area. */
3606 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
3607
3608 /* Now build the actual open request. */
3609 if (open_type == NX_FTP_OPEN_FOR_WRITE)
3610 {
3611
3612 /* File write request, STOR is the command for writing a file. */
3613 buffer_ptr[0] = 'S';
3614 buffer_ptr[1] = 'T';
3615 buffer_ptr[2] = 'O';
3616 buffer_ptr[3] = 'R';
3617 buffer_ptr[4] = ' ';
3618 }
3619 else
3620 {
3621
3622 /* File read request, RETR is the command for reading a file. */
3623 buffer_ptr[0] = 'R';
3624 buffer_ptr[1] = 'E';
3625 buffer_ptr[2] = 'T';
3626 buffer_ptr[3] = 'R';
3627 buffer_ptr[4] = ' ';
3628 }
3629
3630 /* Copy the file name into the buffer. */
3631 for(i = 0; file_name[i]; i++)
3632 {
3633
3634 /* Check if out of boundary. */
3635 if ((i + 7) >= (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr))
3636 {
3637
3638 /* Cleanup data socket. */
3639 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
3640
3641 /* Release the packet. */
3642 nx_packet_release(packet_ptr);
3643
3644 /* Set the error status. */
3645 return(NX_FTP_FAILED);
3646 }
3647
3648 /* Copy character of file name. */
3649 buffer_ptr[5+i] = (UCHAR)file_name[i];
3650 }
3651
3652 /* Insert the CR/LF. */
3653 buffer_ptr[5+i] = 13;
3654 buffer_ptr[5+i+1] = 10;
3655
3656 /* Setup the length of the packet. */
3657 packet_ptr -> nx_packet_length = i + 7;
3658
3659 /* Setup the packet append pointer. */
3660 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
3661
3662 /* Send the STOR/RETR message. */
3663 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
3664
3665 /* Determine if the send was unsuccessful. */
3666 if (status != NX_SUCCESS)
3667 {
3668
3669 /* Cleanup data socket. */
3670 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
3671
3672 /* Release the packet. */
3673 nx_packet_release(packet_ptr);
3674
3675 /* Return error. */
3676 return(status);
3677 }
3678
3679 /* Check if enable passive mode. */
3680 if (ftp_client_ptr -> nx_ftp_client_passive_transfer_enabled == NX_FALSE)
3681 {
3682
3683 /* Active mode. Now wait for the data connection to connect. */
3684 status = nx_tcp_server_socket_accept(&(ftp_client_ptr -> nx_ftp_client_data_socket), wait_option);
3685
3686 /* Determine if the accept was unsuccessful. */
3687 if (status != NX_SUCCESS)
3688 {
3689
3690 /* Cleanup data socket. */
3691 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
3692
3693 /* Return error. */
3694 return(status);
3695 }
3696 }
3697
3698 /* Now wait for response from the FTP server control port. */
3699 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
3700
3701 /* Determine if a packet was not received. */
3702 if (status != NX_SUCCESS)
3703 {
3704
3705 /* Cleanup data socket. */
3706 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
3707
3708 /* Unable to open file with FTP server. */
3709 return(status);
3710 }
3711
3712 /* We have a packet, setup pointer to the buffer area. */
3713 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
3714
3715 /* Check for 1xx message, signaling the data port was connected properly and ready for transfer. */
3716 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '1'))
3717 {
3718
3719 /* Cleanup data socket. */
3720 _nx_ftp_client_data_socket_cleanup(ftp_client_ptr, wait_option);
3721
3722 /* Release the packet. */
3723 nx_packet_release(packet_ptr);
3724
3725 /* Unable to open file with FTP server. */
3726 return(NX_FTP_EXPECTED_1XX_CODE);
3727 }
3728
3729 /* Release the last packet. */
3730 nx_packet_release(packet_ptr);
3731
3732 /* At this point, the client has successfully opened a FTP connection. */
3733 if (open_type == NX_FTP_OPEN_FOR_WRITE)
3734 {
3735
3736 /* Set the client state to open for write. */
3737 ftp_client_ptr -> nx_ftp_client_state = NX_FTP_STATE_WRITE_OPEN;
3738 }
3739 else
3740 {
3741
3742 /* Set the client state to open for read. */
3743 ftp_client_ptr -> nx_ftp_client_state = NX_FTP_STATE_OPEN;
3744 }
3745
3746 /* Return success to caller. */
3747 return(NX_SUCCESS);
3748 }
3749
3750
3751 /**************************************************************************/
3752 /* */
3753 /* FUNCTION RELEASE */
3754 /* */
3755 /* _nxe_ftp_client_file_read PORTABLE C */
3756 /* 6.1 */
3757 /* AUTHOR */
3758 /* */
3759 /* Yuxin Zhou, Microsoft Corporation */
3760 /* */
3761 /* DESCRIPTION */
3762 /* */
3763 /* This function checks for errors in the FTP client file read. */
3764 /* */
3765 /* */
3766 /* INPUT */
3767 /* */
3768 /* ftp_client_ptr Pointer to FTP client */
3769 /* packet_ptr Destination of for the */
3770 /* received packet pointer */
3771 /* wait_option Specifies how long to wait */
3772 /* */
3773 /* OUTPUT */
3774 /* */
3775 /* status Completion status */
3776 /* */
3777 /* CALLS */
3778 /* */
3779 /* _nx_ftp_client_file_read Actual client file read call */
3780 /* */
3781 /* CALLED BY */
3782 /* */
3783 /* Application Code */
3784 /* */
3785 /* RELEASE HISTORY */
3786 /* */
3787 /* DATE NAME DESCRIPTION */
3788 /* */
3789 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3790 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3791 /* resulting in version 6.1 */
3792 /* */
3793 /**************************************************************************/
_nxe_ftp_client_file_read(NX_FTP_CLIENT * ftp_client_ptr,NX_PACKET ** packet_ptr,ULONG wait_option)3794 UINT _nxe_ftp_client_file_read(NX_FTP_CLIENT *ftp_client_ptr, NX_PACKET **packet_ptr, ULONG wait_option)
3795 {
3796
3797 UINT status;
3798
3799
3800 /* Check for invalid input pointers. */
3801 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID) || (packet_ptr == NX_NULL))
3802 return(NX_PTR_ERROR);
3803
3804 /* Check for appropriate caller. */
3805 NX_THREADS_ONLY_CALLER_CHECKING
3806
3807 /* Call actual client file read function. */
3808 status = _nx_ftp_client_file_read(ftp_client_ptr, packet_ptr, wait_option);
3809
3810 /* Return completion status. */
3811 return(status);
3812 }
3813
3814
3815 /**************************************************************************/
3816 /* */
3817 /* FUNCTION RELEASE */
3818 /* */
3819 /* _nx_ftp_client_file_read PORTABLE C */
3820 /* 6.1 */
3821 /* AUTHOR */
3822 /* */
3823 /* Yuxin Zhou, Microsoft Corporation */
3824 /* */
3825 /* DESCRIPTION */
3826 /* */
3827 /* This function reads a packet of the file from the data connection */
3828 /* with the FTP server. */
3829 /* */
3830 /* */
3831 /* INPUT */
3832 /* */
3833 /* ftp_client_ptr Pointer to FTP client */
3834 /* packet_ptr Destination of for the */
3835 /* received packet pointer */
3836 /* wait_option Specifies how long to wait */
3837 /* */
3838 /* OUTPUT */
3839 /* */
3840 /* status Completion status */
3841 /* */
3842 /* CALLS */
3843 /* */
3844 /* nx_tcp_socket_receive Receive response from server */
3845 /* */
3846 /* CALLED BY */
3847 /* */
3848 /* Application Code */
3849 /* */
3850 /* RELEASE HISTORY */
3851 /* */
3852 /* DATE NAME DESCRIPTION */
3853 /* */
3854 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3855 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3856 /* resulting in version 6.1 */
3857 /* */
3858 /**************************************************************************/
_nx_ftp_client_file_read(NX_FTP_CLIENT * ftp_client_ptr,NX_PACKET ** packet_ptr,ULONG wait_option)3859 UINT _nx_ftp_client_file_read(NX_FTP_CLIENT *ftp_client_ptr, NX_PACKET **packet_ptr, ULONG wait_option)
3860 {
3861
3862 UINT status;
3863
3864
3865 /* Determine if the file is open for writing. */
3866 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_OPEN)
3867 return(NX_FTP_NOT_OPEN);
3868
3869 /* Default the packet pointer to NULL. */
3870 *packet_ptr = NX_NULL;
3871
3872 /* Read the packet from the data connection. */
3873 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_data_socket), packet_ptr, wait_option);
3874
3875 /* Determine if an error occurred. */
3876 if (status == NX_NOT_CONNECTED)
3877 {
3878
3879 /* Map not-connected status to end of file. */
3880 status = NX_FTP_END_OF_FILE;
3881 }
3882
3883 /* Determine if the block mode is enabled. */
3884 if ((status == NX_SUCCESS) &&
3885 (ftp_client_ptr -> nx_ftp_client_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK))
3886 {
3887
3888 /* Retrieve the block header. */
3889 status = _nx_ftp_client_block_header_retrieve(ftp_client_ptr, (*packet_ptr));
3890 }
3891
3892 /* Return status to caller. */
3893 return(status);
3894 }
3895
3896
3897 /**************************************************************************/
3898 /* */
3899 /* FUNCTION RELEASE */
3900 /* */
3901 /* _nxe_ftp_client_file_rename PORTABLE C */
3902 /* 6.1 */
3903 /* AUTHOR */
3904 /* */
3905 /* Yuxin Zhou, Microsoft Corporation */
3906 /* */
3907 /* DESCRIPTION */
3908 /* */
3909 /* This function checks for errors in the FTP client file rename. */
3910 /* */
3911 /* Note: The string lengths of filename and new_filename are limited */
3912 /* by the packet payload size. */
3913 /* */
3914 /* INPUT */
3915 /* */
3916 /* ftp_client_ptr Pointer to FTP client */
3917 /* filename Current file name */
3918 /* new_filename New file name */
3919 /* wait_option Specifies how long to wait */
3920 /* */
3921 /* OUTPUT */
3922 /* */
3923 /* status Completion status */
3924 /* */
3925 /* CALLS */
3926 /* */
3927 /* _nxe_ftp_client_file_rename Actual client file rename call*/
3928 /* */
3929 /* CALLED BY */
3930 /* */
3931 /* Application Code */
3932 /* */
3933 /* RELEASE HISTORY */
3934 /* */
3935 /* DATE NAME DESCRIPTION */
3936 /* */
3937 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3938 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3939 /* resulting in version 6.1 */
3940 /* */
3941 /**************************************************************************/
_nxe_ftp_client_file_rename(NX_FTP_CLIENT * ftp_client_ptr,CHAR * filename,CHAR * new_filename,ULONG wait_option)3942 UINT _nxe_ftp_client_file_rename(NX_FTP_CLIENT *ftp_client_ptr, CHAR *filename, CHAR *new_filename, ULONG wait_option)
3943 {
3944
3945 UINT status;
3946
3947
3948 /* Check for invalid input pointers. */
3949 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID) ||
3950 (filename == NX_NULL) || (new_filename == NX_NULL))
3951 return(NX_PTR_ERROR);
3952
3953 /* Check for appropriate caller. */
3954 NX_THREADS_ONLY_CALLER_CHECKING
3955
3956 /* Call actual client file rename function. */
3957 status = _nx_ftp_client_file_rename(ftp_client_ptr, filename, new_filename, wait_option);
3958
3959 /* Return completion status. */
3960 return(status);
3961 }
3962
3963
3964 /**************************************************************************/
3965 /* */
3966 /* FUNCTION RELEASE */
3967 /* */
3968 /* _nx_ftp_client_file_rename PORTABLE C */
3969 /* 6.1 */
3970 /* AUTHOR */
3971 /* */
3972 /* Yuxin Zhou, Microsoft Corporation */
3973 /* */
3974 /* DESCRIPTION */
3975 /* */
3976 /* This function renames the specified file with the supplied */
3977 /* filename. */
3978 /* */
3979 /* Note: The string lengths of filename and new_filename are limited */
3980 /* by the packet payload size. */
3981 /* */
3982 /* INPUT */
3983 /* */
3984 /* ftp_client_ptr Pointer to FTP client */
3985 /* filename Current file name */
3986 /* new_filename New file name */
3987 /* wait_option Specifies how long to wait */
3988 /* */
3989 /* OUTPUT */
3990 /* */
3991 /* status Completion status */
3992 /* */
3993 /* CALLS */
3994 /* */
3995 /* nx_packet_allocate Allocate packet */
3996 /* nx_packet_release Release packet */
3997 /* nx_tcp_socket_receive Receive packet from server */
3998 /* nx_tcp_socket_send Send data packet to server */
3999 /* */
4000 /* CALLED BY */
4001 /* */
4002 /* Application Code */
4003 /* */
4004 /* RELEASE HISTORY */
4005 /* */
4006 /* DATE NAME DESCRIPTION */
4007 /* */
4008 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4009 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4010 /* resulting in version 6.1 */
4011 /* */
4012 /**************************************************************************/
_nx_ftp_client_file_rename(NX_FTP_CLIENT * ftp_client_ptr,CHAR * filename,CHAR * new_filename,ULONG wait_option)4013 UINT _nx_ftp_client_file_rename(NX_FTP_CLIENT *ftp_client_ptr, CHAR *filename, CHAR *new_filename, ULONG wait_option)
4014 {
4015
4016 UINT i;
4017 UCHAR *buffer_ptr;
4018 NX_PACKET *packet_ptr;
4019 UINT status;
4020
4021
4022 /* Ensure the client is the proper state for a rename file request. */
4023 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_CONNECTED)
4024 return(NX_FTP_NOT_CONNECTED);
4025
4026 /* Allocate a packet for sending the file rename command. */
4027 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
4028
4029 /* Determine if the packet allocation was successful. */
4030 if (status)
4031 {
4032
4033 /* Return error. */
4034 return(status);
4035 }
4036
4037 /* Check if out of boundary. */
4038 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 7)
4039 {
4040
4041 /* Release the packet. */
4042 nx_packet_release(packet_ptr);
4043
4044 /* Set the error status. */
4045 return(NX_FTP_FAILED);
4046 }
4047
4048 /* We have a packet, setup pointer to the buffer area. */
4049 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
4050
4051 /* Now build "RNFR" message to indicate file rename request. */
4052 buffer_ptr[0] = 'R';
4053 buffer_ptr[1] = 'N';
4054 buffer_ptr[2] = 'F';
4055 buffer_ptr[3] = 'R';
4056 buffer_ptr[4] = ' ';
4057
4058 /* Copy the old file name into the message. */
4059 for(i = 0; filename[i]; i++)
4060 {
4061
4062 /* Check if out of boundary. */
4063 if ((i + 7) >= (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr))
4064 {
4065
4066 /* Release the packet. */
4067 nx_packet_release(packet_ptr);
4068
4069 /* Set the error status. */
4070 return(NX_FTP_FAILED);
4071 }
4072
4073 /* Copy character of the file name. */
4074 buffer_ptr[5+i] = (UCHAR)filename[i];
4075 }
4076
4077 /* Set the CR/LF. */
4078 buffer_ptr[i+5] = 13;
4079 buffer_ptr[i+6] = 10;
4080
4081 /* Set the packet length. */
4082 packet_ptr -> nx_packet_length = i+7;
4083
4084 /* Setup the packet append pointer. */
4085 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
4086
4087 /* Send the RNFR message. */
4088 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
4089
4090 /* Determine if the send was unsuccessful. */
4091 if (status)
4092 {
4093
4094 /* Release the packet. */
4095 nx_packet_release(packet_ptr);
4096
4097 /* Return error. */
4098 return(status);
4099 }
4100
4101 /* Wait for response from the FTP server. */
4102 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
4103
4104 /* Determine if a packet was not received. */
4105 if (status)
4106 {
4107
4108 /* RNFR file error. */
4109 return(status);
4110 }
4111
4112 #ifndef NX_DISABLE_PACKET_CHAIN
4113 if (packet_ptr -> nx_packet_next)
4114 {
4115
4116 /* Release the packet. */
4117 nx_packet_release(packet_ptr);
4118
4119 /* Return. */
4120 return(NX_INVALID_PACKET);
4121 }
4122 #endif /* NX_DISABLE_PACKET_CHAIN */
4123
4124 /* We have a packet, setup pointer to the buffer area. */
4125 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
4126
4127 /* Check for 3xx message, signaling the "RNFR" was received properly. */
4128 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '3'))
4129 {
4130
4131 /* Release the packet. */
4132 nx_packet_release(packet_ptr);
4133
4134 /* Unable to rename file with FTP server. */
4135 return(NX_FTP_EXPECTED_3XX_CODE);
4136 }
4137
4138 /* Check if out of boundary. */
4139 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 7)
4140 {
4141
4142 /* Release the packet. */
4143 nx_packet_release(packet_ptr);
4144
4145 /* Set the error status. */
4146 return(NX_FTP_FAILED);
4147 }
4148
4149 /* Now build "RNTO" message to specify new file name. */
4150 buffer_ptr[0] = 'R';
4151 buffer_ptr[1] = 'N';
4152 buffer_ptr[2] = 'T';
4153 buffer_ptr[3] = 'O';
4154 buffer_ptr[4] = ' ';
4155
4156 /* Copy the old file name into the message. */
4157 for(i = 0; new_filename[i]; i++)
4158 {
4159
4160 /* Check if out of boundary. */
4161 if ((i + 7) >= (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr))
4162 {
4163
4164 /* Release the packet. */
4165 nx_packet_release(packet_ptr);
4166
4167 /* Set the error status. */
4168 return(NX_FTP_FAILED);
4169 }
4170
4171 /* Copy character of the new file name. */
4172 buffer_ptr[5+i] = (UCHAR)new_filename[i];
4173 }
4174
4175 /* Set the CR/LF. */
4176 buffer_ptr[i+5] = 13;
4177 buffer_ptr[i+6] = 10;
4178
4179 /* Set the packet length. */
4180 packet_ptr -> nx_packet_length = i+7;
4181
4182 /* Setup the packet append pointer. */
4183 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
4184
4185 /* Send the RNTO message. */
4186 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
4187
4188 /* Determine if the send was unsuccessful. */
4189 if (status)
4190 {
4191
4192 /* Release the packet. */
4193 nx_packet_release(packet_ptr);
4194
4195 /* Return error. */
4196 return(status);
4197 }
4198
4199 /* Wait for response from the FTP server. */
4200 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
4201
4202 /* Determine if a packet was not received. */
4203 if (status)
4204 {
4205
4206 /* RNTO file error. */
4207 return(status);
4208 }
4209
4210 /* We have a packet, setup pointer to the buffer area. */
4211 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
4212
4213 /* Check for 2xx message, signaling the "RNTO" was processed properly. */
4214 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2'))
4215 {
4216
4217 /* Release the packet. */
4218 nx_packet_release(packet_ptr);
4219
4220 /* Unable to rename with FTP server. */
4221 return(NX_FTP_EXPECTED_2XX_CODE);
4222 }
4223
4224 /* Release packet. */
4225 nx_packet_release(packet_ptr);
4226
4227 /* Return success to caller. */
4228 return(NX_SUCCESS);
4229 }
4230
4231
4232 /**************************************************************************/
4233 /* */
4234 /* FUNCTION RELEASE */
4235 /* */
4236 /* _nxe_ftp_client_file_size_set PORTABLE C */
4237 /* 6.1 */
4238 /* AUTHOR */
4239 /* */
4240 /* Yuxin Zhou, Microsoft Corporation */
4241 /* */
4242 /* DESCRIPTION */
4243 /* */
4244 /* This function checks for errors in the FTP client file size set. */
4245 /* */
4246 /* */
4247 /* INPUT */
4248 /* */
4249 /* ftp_client_ptr Pointer to FTP client */
4250 /* file_size The total size of file */
4251 /* */
4252 /* OUTPUT */
4253 /* */
4254 /* status Completion status */
4255 /* */
4256 /* CALLS */
4257 /* */
4258 /* _nx_ftp_client_file_size_set Actual file size set call */
4259 /* */
4260 /* CALLED BY */
4261 /* */
4262 /* Application Code */
4263 /* */
4264 /* RELEASE HISTORY */
4265 /* */
4266 /* DATE NAME DESCRIPTION */
4267 /* */
4268 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4269 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4270 /* resulting in version 6.1 */
4271 /* */
4272 /**************************************************************************/
_nxe_ftp_client_file_size_set(NX_FTP_CLIENT * ftp_client_ptr,ULONG file_size)4273 UINT _nxe_ftp_client_file_size_set(NX_FTP_CLIENT *ftp_client_ptr, ULONG file_size)
4274 {
4275
4276 UINT status;
4277
4278
4279 /* Check for invalid input pointers. */
4280 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID))
4281 return(NX_PTR_ERROR);
4282
4283 /* Check for appropriate caller. */
4284 NX_THREADS_ONLY_CALLER_CHECKING
4285
4286 /* Call actual client file size set function. */
4287 status = _nx_ftp_client_file_size_set(ftp_client_ptr, file_size);
4288
4289 /* Return completion status. */
4290 return(status);
4291 }
4292
4293
4294 /**************************************************************************/
4295 /* */
4296 /* FUNCTION RELEASE */
4297 /* */
4298 /* _nx_ftp_client_file_size_set PORTABLE C */
4299 /* 6.1 */
4300 /* AUTHOR */
4301 /* */
4302 /* Yuxin Zhou, Microsoft Corporation */
4303 /* */
4304 /* DESCRIPTION */
4305 /* */
4306 /* This function sets the file size for block mode before send packets */
4307 /* to the file on the data connection with the FTP server. */
4308 /* */
4309 /* Note:a. This API is only used for block mode, */
4310 /* b. Must call this API before call nx_ftp_client_file_write. */
4311 /* */
4312 /* INPUT */
4313 /* */
4314 /* ftp_client_ptr Pointer to FTP client */
4315 /* file_size The total size of file */
4316 /* */
4317 /* OUTPUT */
4318 /* */
4319 /* status Completion status */
4320 /* */
4321 /* CALLS */
4322 /* */
4323 /* nx_packet_release Release packet */
4324 /* nx_tcp_socket_send Send data packet to server */
4325 /* */
4326 /* CALLED BY */
4327 /* */
4328 /* Application Code */
4329 /* */
4330 /* RELEASE HISTORY */
4331 /* */
4332 /* DATE NAME DESCRIPTION */
4333 /* */
4334 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4335 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4336 /* resulting in version 6.1 */
4337 /* */
4338 /**************************************************************************/
_nx_ftp_client_file_size_set(NX_FTP_CLIENT * ftp_client_ptr,ULONG file_size)4339 UINT _nx_ftp_client_file_size_set(NX_FTP_CLIENT *ftp_client_ptr, ULONG file_size)
4340 {
4341
4342 UINT status;
4343
4344
4345 /* Check for invalid file size. */
4346 if (file_size == 0)
4347 return(NX_FTP_CLIENT_INVALID_SIZE);
4348
4349 /* Check if already set the file size. */
4350 if (ftp_client_ptr -> nx_ftp_client_block_total_size != 0)
4351 return(NX_FTP_CLIENT_FILE_SIZE_ALREADY_SET);
4352
4353 /* Determine if the block mode is enabled. */
4354 if (ftp_client_ptr -> nx_ftp_client_transfer_mode != NX_FTP_TRANSFER_MODE_BLOCK)
4355 return(NX_FTP_CLIENT_NOT_BLOCK_MODE);
4356
4357 /* Determine if the file is open for writing. */
4358 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_WRITE_OPEN)
4359 return(NX_FTP_NOT_OPEN);
4360
4361 /* Send start block header for file size. */
4362 status = _nx_ftp_client_block_header_send(ftp_client_ptr, file_size);
4363
4364 /* Determine if the send was unsuccessful. */
4365 if (status)
4366 {
4367
4368 /* Return error. */
4369 return(status);
4370 }
4371
4372 /* Store the file size for writing. */
4373 ftp_client_ptr -> nx_ftp_client_block_total_size = file_size;
4374 ftp_client_ptr -> nx_ftp_client_block_remaining_size = file_size;
4375
4376 /* Return success to caller. */
4377 return(NX_SUCCESS);
4378 }
4379
4380
4381 /**************************************************************************/
4382 /* */
4383 /* FUNCTION RELEASE */
4384 /* */
4385 /* _nxe_ftp_client_file_write PORTABLE C */
4386 /* 6.1 */
4387 /* AUTHOR */
4388 /* */
4389 /* Yuxin Zhou, Microsoft Corporation */
4390 /* */
4391 /* DESCRIPTION */
4392 /* */
4393 /* This function checks for errors in the FTP client file write. */
4394 /* */
4395 /* */
4396 /* INPUT */
4397 /* */
4398 /* ftp_client_ptr Pointer to FTP client */
4399 /* packet_ptr Pointer to packet to write */
4400 /* wait_option Specifies how long to wait */
4401 /* */
4402 /* OUTPUT */
4403 /* */
4404 /* status Completion status */
4405 /* */
4406 /* CALLS */
4407 /* */
4408 /* _nx_ftp_client_file_write Actual client file write call */
4409 /* */
4410 /* CALLED BY */
4411 /* */
4412 /* Application Code */
4413 /* */
4414 /* RELEASE HISTORY */
4415 /* */
4416 /* DATE NAME DESCRIPTION */
4417 /* */
4418 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4419 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4420 /* resulting in version 6.1 */
4421 /* */
4422 /**************************************************************************/
_nxe_ftp_client_file_write(NX_FTP_CLIENT * ftp_client_ptr,NX_PACKET * packet_ptr,ULONG wait_option)4423 UINT _nxe_ftp_client_file_write(NX_FTP_CLIENT *ftp_client_ptr, NX_PACKET *packet_ptr, ULONG wait_option)
4424 {
4425
4426 UINT status;
4427
4428
4429 /* Check for invalid input pointers. */
4430 if ((ftp_client_ptr == NX_NULL) || (ftp_client_ptr -> nx_ftp_client_id != NXD_FTP_CLIENT_ID) ||
4431 (packet_ptr == NX_NULL))
4432 return(NX_PTR_ERROR);
4433
4434 /* Check for appropriate caller. */
4435 NX_THREADS_ONLY_CALLER_CHECKING
4436
4437 /* Call actual client file write function. */
4438 status = _nx_ftp_client_file_write(ftp_client_ptr, packet_ptr, wait_option);
4439
4440 /* Return completion status. */
4441 return(status);
4442 }
4443
4444
4445 /**************************************************************************/
4446 /* */
4447 /* FUNCTION RELEASE */
4448 /* */
4449 /* _nx_ftp_client_file_write PORTABLE C */
4450 /* 6.1 */
4451 /* AUTHOR */
4452 /* */
4453 /* Yuxin Zhou, Microsoft Corporation */
4454 /* */
4455 /* DESCRIPTION */
4456 /* */
4457 /* This function writes a packet to the file on the data connection */
4458 /* with the FTP server. */
4459 /* */
4460 /* */
4461 /* INPUT */
4462 /* */
4463 /* ftp_client_ptr Pointer to FTP client */
4464 /* packet_ptr Pointer to packet to write */
4465 /* wait_option Specifies how long to wait */
4466 /* */
4467 /* OUTPUT */
4468 /* */
4469 /* status Completion status */
4470 /* */
4471 /* CALLS */
4472 /* */
4473 /* nx_packet_release Release packet */
4474 /* nx_tcp_socket_send Send data packet to server */
4475 /* */
4476 /* CALLED BY */
4477 /* */
4478 /* Application Code */
4479 /* */
4480 /* RELEASE HISTORY */
4481 /* */
4482 /* DATE NAME DESCRIPTION */
4483 /* */
4484 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4485 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4486 /* resulting in version 6.1 */
4487 /* */
4488 /**************************************************************************/
_nx_ftp_client_file_write(NX_FTP_CLIENT * ftp_client_ptr,NX_PACKET * packet_ptr,ULONG wait_option)4489 UINT _nx_ftp_client_file_write(NX_FTP_CLIENT *ftp_client_ptr, NX_PACKET *packet_ptr, ULONG wait_option)
4490 {
4491
4492 UINT status;
4493 ULONG file_size = 0;
4494
4495
4496 /* Determine if the file is open for writing. */
4497 if (ftp_client_ptr -> nx_ftp_client_state != NX_FTP_STATE_WRITE_OPEN)
4498 return(NX_FTP_NOT_OPEN);
4499
4500 /* Determine if the block mode is enabled. */
4501 if (ftp_client_ptr -> nx_ftp_client_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
4502 {
4503
4504 /* Record the file size. */
4505 file_size = packet_ptr -> nx_packet_length;
4506
4507 /* Check the file size. */
4508 if (ftp_client_ptr -> nx_ftp_client_block_remaining_size < packet_ptr -> nx_packet_length)
4509 return(NX_FTP_CLIENT_INVALID_SIZE);
4510 }
4511
4512 /* Write packet payload to the file. */
4513 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_data_socket), packet_ptr, wait_option);
4514
4515 /* Determine if the send was unsuccessful. */
4516 if (status)
4517 {
4518
4519 /* Release the packet. */
4520 nx_packet_release(packet_ptr);
4521
4522 /* Return error. */
4523 return(status);
4524 }
4525
4526 /* Determine if the block mode is enabled. */
4527 if (ftp_client_ptr -> nx_ftp_client_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK)
4528 {
4529
4530 /* Update the file size. */
4531 ftp_client_ptr -> nx_ftp_client_block_remaining_size -= file_size;
4532
4533 /* Check if the file is already sent. */
4534 if (ftp_client_ptr -> nx_ftp_client_block_remaining_size == 0)
4535 {
4536
4537 /* Send end block header for file size. */
4538 status = _nx_ftp_client_block_header_send(ftp_client_ptr, 0);
4539 }
4540 }
4541
4542 /* Return success to caller. */
4543 return(status);
4544 }
4545
4546
4547 #ifdef FEATURE_NX_IPV6
4548 /**************************************************************************/
4549 /* */
4550 /* FUNCTION RELEASE */
4551 /* */
4552 /* _nx_ftp_utility_convert_IPv6_to_ascii PORTABLE C */
4553 /* 6.1 */
4554 /* AUTHOR */
4555 /* */
4556 /* Yuxin Zhou, Microsoft Corporation */
4557 /* */
4558 /* DESCRIPTION */
4559 /* */
4560 /* This function converts an IP address to ascii e.g. for insertion */
4561 /* into FTP EPRT or PORT command. */
4562 /* */
4563 /* INPUT */
4564 /* */
4565 /* ftp_client_ptr Pointer to FTP client */
4566 /* buffer Pointer to ascii port number string*/
4567 /* buffer_length Size of buffer */
4568 /* size IPv6 address string size */
4569 /* */
4570 /* OUTPUT */
4571 /* */
4572 /* NX_SUCCESS Successful conversion */
4573 /* */
4574 /* CALLS */
4575 /* */
4576 /* _nx_ftp_utility_convert_number_ascii */
4577 /* Converts a single number to ascii */
4578 /* */
4579 /* CALLED BY */
4580 /* */
4581 /* _nx_ftp_client_file_open FTP Client file open service */
4582 /* */
4583 /* RELEASE HISTORY */
4584 /* */
4585 /* DATE NAME DESCRIPTION */
4586 /* */
4587 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4588 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
4589 /* verified memcpy use cases, */
4590 /* resulting in version 6.1 */
4591 /* */
4592 /**************************************************************************/
4593
_nx_ftp_utility_convert_IPv6_to_ascii(NX_TCP_SOCKET * socket_ptr,CHAR * buffer,UINT buffer_length,UINT * size)4594 UINT _nx_ftp_utility_convert_IPv6_to_ascii(NX_TCP_SOCKET *socket_ptr, CHAR *buffer, UINT buffer_length, UINT *size)
4595 {
4596
4597
4598 CHAR *temp;
4599 CHAR number_buf[10]; /* 0x20010000 -> "2001:0000:" */
4600
4601
4602 /* Set a pointer to the start of the buffer. */
4603 temp = buffer;
4604
4605 /* Clear the buffer. */
4606 memset(temp, 0, buffer_length);
4607
4608 /* Clear the scratch buffer. */
4609 memset(number_buf, 0, 10);
4610
4611 _nx_ftp_utility_convert_number_ascii(socket_ptr -> nx_tcp_socket_ipv6_addr -> nxd_ipv6_address[0], number_buf);
4612
4613 /* Append to string buffer. */
4614 memcpy(temp, number_buf, 10); /* Use case of memcpy is verified. */
4615
4616 /* Move the pointer past this number. */
4617 temp += 10;
4618
4619 /* Clear the scratch buffer. */
4620 memset(number_buf, 0, 10);
4621
4622 _nx_ftp_utility_convert_number_ascii(socket_ptr -> nx_tcp_socket_ipv6_addr -> nxd_ipv6_address[1], number_buf);
4623
4624 /* Append to string buffer. */
4625 memcpy(temp, number_buf, 10); /* Use case of memcpy is verified. */
4626
4627 /* Move the pointer past this number. */
4628 temp += 10;
4629
4630 /* Clear the scratch buffer. */
4631 memset(number_buf, 0, 10);
4632
4633 _nx_ftp_utility_convert_number_ascii(socket_ptr -> nx_tcp_socket_ipv6_addr -> nxd_ipv6_address[2], number_buf);
4634
4635 /* Append to string buffer. */
4636 memcpy(temp, number_buf, 10); /* Use case of memcpy is verified. */
4637
4638 /* Move the pointer past this number. */
4639 temp += 10;
4640
4641 /* Clear the scratch buffer. */
4642 memset(number_buf, 0, 10);
4643
4644 _nx_ftp_utility_convert_number_ascii(socket_ptr -> nx_tcp_socket_ipv6_addr -> nxd_ipv6_address[3], number_buf);
4645
4646 /* Append to string buffer. */
4647 memcpy(temp, number_buf, 10); /* Use case of memcpy is verified. */
4648
4649 /* Move the pointer past this number. */
4650 temp += 10;
4651
4652 /* Remove the trailing ':'. */
4653 *(temp - 1) = 0x0;
4654 *size = 39;
4655
4656 return NX_SUCCESS;
4657 }
4658
4659
4660 /**************************************************************************/
4661 /* */
4662 /* FUNCTION RELEASE */
4663 /* */
4664 /* _nx_ftp_utility_convert_number_ascii PORTABLE C */
4665 /* 6.1 */
4666 /* AUTHOR */
4667 /* */
4668 /* Yuxin Zhou, Microsoft Corporation */
4669 /* */
4670 /* DESCRIPTION */
4671 /* */
4672 /* This function converts a number to ascii text for inserting IP */
4673 /* address and port numbers into FTP EPRT and PORT commands. It is up */
4674 /* to the caller to provide a buffer large enough to hold the ascii */
4675 /* conversion of the input number. */
4676 /* */
4677 /* INPUT */
4678 /* */
4679 /* number Number to convert to ASCII */
4680 /* numstring Pointer to ascii string */
4681 /* */
4682 /* OUTPUT */
4683 /* NX_SUCCESS Successful completion */
4684 /* */
4685 /* CALLS */
4686 /* None */
4687 /* */
4688 /* CALLED BY */
4689 /* _nx_ftp_utility_convert_IPv6_to_ascii */
4690 /* Convert IPv6 address to ASCII */
4691 /* */
4692 /* RELEASE HISTORY */
4693 /* */
4694 /* DATE NAME DESCRIPTION */
4695 /* */
4696 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4697 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4698 /* resulting in version 6.1 */
4699 /* */
4700 /**************************************************************************/
4701
_nx_ftp_utility_convert_number_ascii(ULONG number,CHAR * numstring)4702 UINT _nx_ftp_utility_convert_number_ascii(ULONG number, CHAR *numstring)
4703 {
4704
4705 UINT j;
4706 UCHAR c;
4707
4708 /* Go through each bit of the ULONG to convert. */
4709 for (j = 0; j <=7 ; j++)
4710 {
4711
4712 /* Save the bit off the most significant end. */
4713 c = (UCHAR)((number & 0xF0000000) >> 28);
4714
4715 /* Make it the most significant byte. */
4716 number = number << 4;
4717
4718 /* Convert the digit to an ascii character. */
4719 if (c < 10)
4720 {
4721 *numstring = (CHAR)('0' + c);
4722 }
4723 else /* Handle HEX digits... */
4724 {
4725 *numstring = (CHAR)('A' + (c - 10));
4726 }
4727
4728 /* Move past the digit. */
4729 numstring++;
4730
4731 /* Determine if we need to add a colon. */
4732 if (j == 3 || j == 7)
4733 {
4734 /* Yes, append the colon and move the pointer past it. */
4735 *numstring = ':';
4736 numstring++;
4737 }
4738 }
4739
4740 return NX_SUCCESS;
4741 }
4742
4743
4744 /**************************************************************************/
4745 /* */
4746 /* FUNCTION RELEASE */
4747 /* */
4748 /* _nx_ftp_utility_convert_portnumber_ascii PORTABLE C */
4749 /* 6.1 */
4750 /* AUTHOR */
4751 /* */
4752 /* Yuxin Zhou, Microsoft Corporation */
4753 /* */
4754 /* DESCRIPTION */
4755 /* */
4756 /* This function converts a number to ascii text e.g. used by */
4757 /* _nx_nat_utility_convert_portnumber_ULONG_to_ascii for inserting */
4758 /* changed port numbers back into FTP PORT command . */
4759 /* */
4760 /* INPUT */
4761 /* */
4762 /* number Port number to convert to ASCII */
4763 /* numstring Pointer to ascii portnumber string */
4764 /* numstring_length Portnumber string length */
4765 /* */
4766 /* OUTPUT */
4767 /* */
4768 /* NX_FTP_ERROR Unable to convert e.g. overflow error*/
4769 /* NX_SUCCESS Successful conversion */
4770 /* */
4771 /* CALLS */
4772 /* */
4773 /* None */
4774 /* */
4775 /* CALLED BY */
4776 /* */
4777 /* _nx_ftp_client_file_open Processes the FTP file open service */
4778 /* */
4779 /* */
4780 /* RELEASE HISTORY */
4781 /* */
4782 /* DATE NAME DESCRIPTION */
4783 /* */
4784 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4785 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4786 /* resulting in version 6.1 */
4787 /* */
4788 /**************************************************************************/
4789
_nx_ftp_utility_convert_portnumber_ascii(UINT number,CHAR * numstring,UINT * numstring_length)4790 UINT _nx_ftp_utility_convert_portnumber_ascii(UINT number, CHAR *numstring, UINT *numstring_length)
4791 {
4792
4793 UINT j;
4794 UINT digit;
4795
4796
4797 /* Initialize counters. */
4798 (*numstring_length) = 0;
4799
4800 /* Loop to convert the number to ASCII. */
4801 while ((*numstring_length) < 10)
4802 {
4803
4804 /* Shift the current digits over one. */
4805 for (j = (*numstring_length); j != 0; j--)
4806 {
4807
4808 /* Move each digit over one place. */
4809 numstring[j] = numstring[j-1];
4810 }
4811
4812 /* Compute the next decimal digit. */
4813 digit = number % 10;
4814
4815 /* Update the input number. */
4816 number = number / 10;
4817
4818 /* Store the new digit in ASCII form. */
4819 numstring[0] = (CHAR) (digit + 0x30);
4820
4821 /* Increment the size. */
4822 (*numstring_length)++;
4823
4824 /* Determine if the number is now zero. */
4825 if (number == 0)
4826 break;
4827 }
4828
4829 /* Make the string NULL terminated. */
4830 numstring[(*numstring_length)] = (CHAR) NX_NULL;
4831
4832 /* Determine if there is an overflow error. */
4833 if (number)
4834 {
4835
4836 /* Error, return bad values to user. */
4837 (*numstring_length) = 0;
4838 numstring[0] = '0';
4839 return NX_FTP_INVALID_NUMBER;
4840 }
4841
4842 /* Return size to caller. */
4843 return NX_SUCCESS;
4844 }
4845 #endif
4846
4847
4848 /**************************************************************************/
4849 /* */
4850 /* FUNCTION RELEASE */
4851 /* */
4852 /* _nx_ftp_client_packet_allocate PORTABLE C */
4853 /* 6.1 */
4854 /* AUTHOR */
4855 /* */
4856 /* Yuxin Zhou, Microsoft Corporation */
4857 /* */
4858 /* DESCRIPTION */
4859 /* */
4860 /* This function determines which IP TCP packet to allocate based on */
4861 /* the FTP connection address IP type and then allocates the packet. */
4862 /* */
4863 /* */
4864 /* INPUT */
4865 /* */
4866 /* ftp_client_ptr Pointer to FTP client */
4867 /* packet_ptr Allocated packet to return */
4868 /* wait_option Packet allocate wait option */
4869 /* */
4870 /* OUTPUT */
4871 /* */
4872 /* status Completion status */
4873 /* NX_NOT_ENABLED IPv6 not enabled */
4874 /* */
4875 /* CALLS */
4876 /* */
4877 /* nx_packet_allocate Allocate packet */
4878 /* */
4879 /* CALLED BY */
4880 /* */
4881 /* Application Code */
4882 /* */
4883 /* RELEASE HISTORY */
4884 /* */
4885 /* DATE NAME DESCRIPTION */
4886 /* */
4887 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4888 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4889 /* resulting in version 6.1 */
4890 /* */
4891 /**************************************************************************/
_nx_ftp_client_packet_allocate(NX_FTP_CLIENT * ftp_client_ptr,NX_PACKET ** packet_ptr,ULONG wait_option)4892 UINT _nx_ftp_client_packet_allocate(NX_FTP_CLIENT *ftp_client_ptr, NX_PACKET **packet_ptr, ULONG wait_option)
4893 {
4894
4895 UINT packet_type;
4896 UINT status;
4897
4898
4899 /* Default to IPv4 TCP packet to allocate. */
4900 packet_type = NX_IPv4_TCP_PACKET;
4901
4902 /* Determine IP version by FTP connection type. */
4903 if (ftp_client_ptr -> nx_ftp_client_control_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
4904 {
4905
4906 #ifndef FEATURE_NX_IPV6
4907
4908 return NX_NOT_ENABLED;
4909 #else
4910
4911 /* Allocate a TCP IPv6 packet. */
4912 packet_type = NX_IPv6_TCP_PACKET;
4913 #endif
4914 }
4915
4916
4917 /* Allocate the actual packet. */
4918 status = nx_packet_allocate(ftp_client_ptr -> nx_ftp_client_packet_pool_ptr, packet_ptr, packet_type, wait_option);
4919
4920 /* Return completion status. */
4921 return status;
4922 }
4923
4924
4925 /**************************************************************************/
4926 /* */
4927 /* FUNCTION RELEASE */
4928 /* */
4929 /* _nx_ftp_client_active_transfer_setup PORTABLE C */
4930 /* 6.1 */
4931 /* AUTHOR */
4932 /* */
4933 /* Yuxin Zhou, Microsoft Corporation */
4934 /* */
4935 /* DESCRIPTION */
4936 /* */
4937 /* This function sets up the Client data socket for active transfer */
4938 /* where the Client data socket is the TCP client. */
4939 /* */
4940 /* Find free port and listen on it, sends the PORT/EPRT command to */
4941 /* server, then wait for a connection from server. */
4942 /* */
4943 /* INPUT */
4944 /* */
4945 /* ftp_client_ptr Pointer to FTP client */
4946 /* wait_option Specifies how long to wait */
4947 /* */
4948 /* OUTPUT */
4949 /* */
4950 /* status Completion status */
4951 /* */
4952 /* CALLS */
4953 /* */
4954 /* _nx_ftp_client_packet_allocate Allocate packet */
4955 /* _nx_ftp_utility_convert_IPv6_to_ascii Convert IPv6 address to ASCII */
4956 /* _nx_ftp_utility_convert_portnumber_ascii Convert port to ASCII */
4957 /* nx_packet_release Release packet */
4958 /* nx_tcp_free_port_find Find a free port */
4959 /* nx_tcp_server_socket_listen Listen for TCP data socket */
4960 /* connection from server */
4961 /* nx_tcp_server_socket_unlisten Unlisten on server socket */
4962 /* nx_tcp_socket_receive Receive response from server */
4963 /* nx_tcp_socket_send Send request to server */
4964 /* */
4965 /* CALLED BY */
4966 /* */
4967 /* _nx_ftp_client_file_open Open a file for read or write */
4968 /* _nx_ftp_client_directory_listing_get Get directory list */
4969 /* */
4970 /* RELEASE HISTORY */
4971 /* */
4972 /* DATE NAME DESCRIPTION */
4973 /* */
4974 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4975 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
4976 /* verified memcpy use cases, */
4977 /* fixed packet leak, */
4978 /* resulting in version 6.1 */
4979 /* */
4980 /**************************************************************************/
_nx_ftp_client_active_transfer_setup(NX_FTP_CLIENT * ftp_client_ptr,ULONG wait_option)4981 UINT _nx_ftp_client_active_transfer_setup(NX_FTP_CLIENT *ftp_client_ptr, ULONG wait_option)
4982 {
4983
4984 UINT status;
4985 UINT data_port;
4986 #ifndef NX_DISABLE_IPV4
4987 ULONG ip_address;
4988 #endif /* NX_DISABLE_IPV4 */
4989 UCHAR *buffer_ptr;
4990 NX_PACKET *packet_ptr;
4991 #ifdef FEATURE_NX_IPV6
4992 UINT ipduo_size;
4993 #endif
4994
4995
4996 /* Pickup the next free port for the data socket. */
4997 status = nx_tcp_free_port_find(ftp_client_ptr -> nx_ftp_client_ip_ptr,
4998 ftp_client_ptr -> nx_ftp_client_data_port + 1, &data_port);
4999
5000 /* Determine if the port find was successful. */
5001 if (status != NX_SUCCESS)
5002 {
5003 return(status);
5004 }
5005
5006 /* Save the data port to the client record. */
5007 ftp_client_ptr -> nx_ftp_client_data_port = data_port;
5008
5009 /* Start listening on the data port. */
5010 status = nx_tcp_server_socket_listen(ftp_client_ptr -> nx_ftp_client_ip_ptr, data_port, &(ftp_client_ptr -> nx_ftp_client_data_socket), 5, NX_NULL);
5011
5012 /* Determine if the listen is successful. */
5013 if (status != NX_SUCCESS)
5014 {
5015
5016 /* Return error. */
5017 return(status);
5018 }
5019
5020 /* Allocate a packet for sending the PORT/EPRT command. */
5021 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
5022
5023 /* Determine if the packet allocation was successful. */
5024 if (status != NX_SUCCESS)
5025 {
5026
5027 /* Stop listening on the data port. */
5028 nx_tcp_server_socket_unlisten(ftp_client_ptr -> nx_ftp_client_ip_ptr, data_port);
5029
5030 /* Return error. */
5031 return(status);
5032 }
5033
5034 /* We have a packet, setup pointer to the buffer area. */
5035 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
5036
5037 /* Now build the IP and port number FTP message. */
5038 if (ftp_client_ptr -> nx_ftp_client_control_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
5039 {
5040 #ifndef FEATURE_NX_IPV6
5041 return NX_NOT_ENABLED;
5042 #else
5043 CHAR ipduo_buffer[NX_FTP_IPV6_ADDRESS_BUFSIZE];
5044 UINT index;
5045
5046 /* EPRT command: EPRT |2|1080::8:800:200C:417A|5282|
5047 RFC2428, Section2, Page3. */
5048
5049 /* Check if out of boundary.
5050 Max EPRT command sring: 8 ("EPRT |2|") + 39 (IPv6 address string) + 1 ('|') + 5 (Max port string) + 1 ('|') + 2 ("\r\n") = 56. */
5051 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 56)
5052 {
5053
5054 /* Stop listening on the data port. */
5055 nx_tcp_server_socket_unlisten(ftp_client_ptr -> nx_ftp_client_ip_ptr, data_port);
5056
5057 /* Release the packet. */
5058 nx_packet_release(packet_ptr);
5059
5060 /* Set the error status. */
5061 return(NX_INVALID_PACKET);
5062 }
5063
5064 buffer_ptr[0] = 'E';
5065 buffer_ptr[1] = 'P';
5066 buffer_ptr[2] = 'R';
5067 buffer_ptr[3] = 'T';
5068 buffer_ptr[4] = ' ';
5069 buffer_ptr[5] = '|';
5070 buffer_ptr[6] = '2';
5071 buffer_ptr[7] = '|';
5072
5073 /* Convert the PORT command ipv6 address and port number format to ascii text. */
5074
5075 /* Clear our scratch buffer. */
5076 memset(&ipduo_buffer[0], 0, NX_FTP_IPV6_ADDRESS_BUFSIZE);
5077
5078 /* Convert the IPv6 address to text. */
5079 status = _nx_ftp_utility_convert_IPv6_to_ascii(&(ftp_client_ptr -> nx_ftp_client_control_socket),
5080 &ipduo_buffer[0], NX_FTP_IPV6_ADDRESS_BUFSIZE, &ipduo_size);
5081
5082 /* Append to the packet buffer . */
5083 memcpy(buffer_ptr + 8, ipduo_buffer, ipduo_size); /* Use case of memcpy is verified. */
5084
5085 /* Update the index past the IPv6 address. */
5086 index = 8 + ipduo_size;
5087
5088 /* Add the required space character. */
5089 buffer_ptr[index++] = '|';
5090
5091 /* Clear the scratch buffer again. */
5092 memset(&ipduo_buffer[0], 0, NX_FTP_IPV6_ADDRESS_BUFSIZE);
5093
5094 /* Convert the preferred port to ascii. */
5095 status = _nx_ftp_utility_convert_portnumber_ascii(data_port, &ipduo_buffer[0], &ipduo_size);
5096
5097 /* Append to the packet buffer. */
5098 memcpy(buffer_ptr + index, ipduo_buffer, ipduo_size); /* Use case of memcpy is verified. */
5099
5100 /* Update the index past the port. */
5101 index += ipduo_size;
5102
5103 /* Add the required space character. */
5104 buffer_ptr[index++] = '|';
5105
5106 /* Set the CR/LF. */
5107 buffer_ptr[index++] = 13;
5108 buffer_ptr[index++] = 10;
5109
5110 /* Set the packet length. */
5111 packet_ptr -> nx_packet_length = index;
5112 #endif /* FEATURE_NX_IPV6 */
5113 }
5114 else
5115 {
5116 /* IPv4 FTP connection */
5117 #ifdef NX_DISABLE_IPV4
5118 return NX_NOT_ENABLED;
5119 #else
5120
5121 /* Check if out of boundary. */
5122 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 30)
5123 {
5124
5125 /* Stop listening on the data port. */
5126 nx_tcp_server_socket_unlisten(ftp_client_ptr -> nx_ftp_client_ip_ptr, data_port);
5127
5128 /* Release the packet. */
5129 nx_packet_release(packet_ptr);
5130
5131 /* Set the error status. */
5132 return(NX_INVALID_PACKET);
5133 }
5134
5135 /* Pickup the IPv4 address of this IP instance. */
5136 ip_address = ftp_client_ptr -> nx_ftp_client_control_socket.nx_tcp_socket_connect_interface -> nx_interface_ip_address ;
5137
5138 /* Now build the IP and port number FTP message. */
5139 buffer_ptr[0] = 'P';
5140 buffer_ptr[1] = 'O';
5141 buffer_ptr[2] = 'R';
5142 buffer_ptr[3] = 'T';
5143 buffer_ptr[4] = ' ';
5144
5145 buffer_ptr[5] = (UCHAR)('0' + (ip_address >> 24)/100);
5146 buffer_ptr[6] = (UCHAR)('0' + ((ip_address >> 24)/10)%10);
5147 buffer_ptr[7] = (UCHAR)('0' + (ip_address >> 24)%10);
5148 buffer_ptr[8] = ',';
5149
5150 buffer_ptr[9] = (UCHAR)('0' + ((ip_address >> 16) & 0xFF)/100);
5151 buffer_ptr[10] = (UCHAR)('0' + (((ip_address >> 16) & 0xFF)/10)%10);
5152 buffer_ptr[11] = (UCHAR)('0' + ((ip_address >> 16) & 0xFF)%10);
5153 buffer_ptr[12] = ',';
5154
5155 buffer_ptr[13] = (UCHAR)('0' + ((ip_address >> 8) & 0xFF)/100);
5156 buffer_ptr[14] = (UCHAR)('0' + (((ip_address >> 8) & 0xFF)/10)%10);
5157 buffer_ptr[15] = (UCHAR)('0' + ((ip_address >> 8) & 0xFF)%10);
5158 buffer_ptr[16] = ',';
5159
5160 buffer_ptr[17] = (UCHAR)('0' + (ip_address & 0xFF)/100);
5161 buffer_ptr[18] = (UCHAR)('0' + ((ip_address & 0xFF)/10)%10);
5162 buffer_ptr[19] = (UCHAR)('0' + (ip_address & 0xFF)%10);
5163 buffer_ptr[20] = ',';
5164
5165 buffer_ptr[21] = (UCHAR)('0' + (data_port >> 8)/100);
5166 buffer_ptr[22] = (UCHAR)('0' + ((data_port >> 8)/10)%10);
5167 buffer_ptr[23] = (UCHAR)('0' + ((data_port >> 8)%10));
5168 buffer_ptr[24] = ',';
5169
5170 buffer_ptr[25] = (UCHAR)('0' + (data_port & 255)/100);
5171 buffer_ptr[26] = (UCHAR)('0' + ((data_port & 255)/10)%10);
5172 buffer_ptr[27] = (UCHAR)('0' + ((data_port & 255)%10));
5173
5174 /* Set the CR/LF. */
5175 buffer_ptr[28] = 13;
5176 buffer_ptr[29] = 10;
5177
5178 /* Set the packet length. */
5179 packet_ptr -> nx_packet_length = 30;
5180 #endif /* NX_DISABLE_IPV4 */
5181 }
5182
5183 /* Setup the packet append pointer. */
5184 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
5185
5186 /* Send the PORT/EPRT message. */
5187 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
5188
5189 /* Determine if the send was unsuccessful. */
5190 if (status != NX_SUCCESS)
5191 {
5192
5193 /* Stop listening on the data port. */
5194 nx_tcp_server_socket_unlisten(ftp_client_ptr -> nx_ftp_client_ip_ptr, data_port);
5195
5196 /* Release the packet. */
5197 nx_packet_release(packet_ptr);
5198
5199 /* Return error. */
5200 return(status);
5201 }
5202
5203 /* Wait for response from the FTP server. */
5204 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
5205
5206 /* Determine if a packet was not received. */
5207 if (status != NX_SUCCESS)
5208 {
5209
5210 /* Stop listening on the data port. */
5211 nx_tcp_server_socket_unlisten(ftp_client_ptr -> nx_ftp_client_ip_ptr, data_port);
5212
5213 /* Unable to open file with FTP server. */
5214 return(status);
5215 }
5216
5217 /* We have a packet, setup pointer to the buffer area. */
5218 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
5219
5220 /* Check for 2xx message, signaling the IP/port was received properly. */
5221 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2'))
5222 {
5223
5224 /* Stop listening on the data port. */
5225 nx_tcp_server_socket_unlisten(ftp_client_ptr -> nx_ftp_client_ip_ptr, data_port);
5226
5227 /* Release the packet. */
5228 nx_packet_release(packet_ptr);
5229
5230 /* Unable to open file with FTP server. */
5231 return(NX_FTP_EXPECTED_2XX_CODE);
5232 }
5233
5234 /* Release the packet. */
5235 nx_packet_release(packet_ptr);
5236
5237 return(NX_SUCCESS);
5238 }
5239
5240
5241 /**************************************************************************/
5242 /* */
5243 /* FUNCTION RELEASE */
5244 /* */
5245 /* _nx_ftp_client_passive_transfer_setup PORTABLE C */
5246 /* 6.1 */
5247 /* AUTHOR */
5248 /* */
5249 /* Yuxin Zhou, Microsoft Corporation */
5250 /* */
5251 /* DESCRIPTION */
5252 /* */
5253 /* This function sets up the Client data socket for passive transfer */
5254 /* where the Client data socket is the TCP client. */
5255 /* */
5256 /* It sends the PASV command and if the server sends an OK status, it */
5257 /* extracts the server connection info from the server response and */
5258 /* opens a connection on the data socket. */
5259 /* */
5260 /* INPUT */
5261 /* */
5262 /* ftp_client_ptr Pointer to FTP client */
5263 /* wait_option Specifies how long to wait */
5264 /* */
5265 /* OUTPUT */
5266 /* */
5267 /* status Completion status */
5268 /* */
5269 /* CALLS */
5270 /* */
5271 /* _nx_ftp_client_packet_allocate Allocate packet */
5272 /* nx_packet_release Release packet */
5273 /* nx_tcp_client_socket_bind Bind the data socket to a port*/
5274 /* nxd_tcp_client_socket_connect Connect to server data socket */
5275 /* nx_tcp_socket_receive Receive response from server */
5276 /* nx_tcp_socket_send Send request to server */
5277 /* */
5278 /* CALLED BY */
5279 /* */
5280 /* _nx_ftp_client_file_open Open a file for read or write */
5281 /* _nx_ftp_client_directory_listing_get Get directory list */
5282 /* */
5283 /* RELEASE HISTORY */
5284 /* */
5285 /* DATE NAME DESCRIPTION */
5286 /* */
5287 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5288 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5289 /* resulting in version 6.1 */
5290 /* */
5291 /**************************************************************************/
_nx_ftp_client_passive_transfer_setup(NX_FTP_CLIENT * ftp_client_ptr,ULONG wait_option)5292 UINT _nx_ftp_client_passive_transfer_setup(NX_FTP_CLIENT *ftp_client_ptr, ULONG wait_option)
5293 {
5294
5295 UCHAR *buffer_ptr;
5296 NX_PACKET *packet_ptr;
5297 UINT status;
5298 UINT i;
5299 UINT data_port;
5300 #ifndef NX_DISABLE_IPV4
5301 UINT commas = 0;
5302 ULONG ip_address = 0;
5303 ULONG temp = 0;
5304 #endif /* NX_DISABLE_IPV4 */
5305
5306
5307 /* Send the PASV command to switch to passive mode. */
5308
5309 /* Allocate a packet for sending the TYPE command. */
5310 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, wait_option);
5311
5312 /* Determine if the packet allocation was successful. */
5313 if (status != NX_SUCCESS)
5314 {
5315
5316 /* Return error. */
5317 return(status);
5318 }
5319
5320 /* Check if out of boundary. */
5321 if ((UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 6)
5322 {
5323
5324 /* Release the packet. */
5325 nx_packet_release(packet_ptr);
5326
5327 /* Set the error status. */
5328 return(NX_FTP_FAILED);
5329 }
5330
5331 /* We have a packet, setup pointer to the buffer area. */
5332 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
5333
5334 if (ftp_client_ptr -> nx_ftp_client_control_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
5335 {
5336 #ifndef FEATURE_NX_IPV6
5337 return(NX_NOT_ENABLED);
5338 #else
5339
5340 /* Now build "EPSV" message. RFC2428. */
5341 buffer_ptr[0] = 'E';
5342 buffer_ptr[1] = 'P';
5343 buffer_ptr[2] = 'S';
5344 buffer_ptr[3] = 'V';
5345 #endif /* FEATURE_NX_IPV6 */
5346 }
5347 else
5348 {
5349 #ifdef NX_DISABLE_IPV4
5350 return(NX_NOT_ENABLED);
5351 #else
5352
5353 /* Now build "PASV" message . */
5354 buffer_ptr[0] = 'P';
5355 buffer_ptr[1] = 'A';
5356 buffer_ptr[2] = 'S';
5357 buffer_ptr[3] = 'V';
5358 #endif /* NX_DISABLE_IPV4 */
5359 }
5360
5361 /* Set the CR/LF. */
5362 buffer_ptr[4] = 13;
5363 buffer_ptr[5] = 10;
5364
5365 /* Set the packet length. */
5366 packet_ptr -> nx_packet_length = 6;
5367
5368 /* Setup the packet append pointer. */
5369 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
5370
5371 /* Send the PASV or EPSV message. */
5372 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
5373
5374 /* Determine if the send was unsuccessful. */
5375 if (status != NX_SUCCESS)
5376 {
5377
5378 /* Release the packet. */
5379 nx_packet_release(packet_ptr);
5380
5381 /* Return error. */
5382 return(status);
5383 }
5384
5385 /* Wait for response from the FTP server. */
5386 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
5387
5388 /* Determine if a packet was not received. */
5389 if (status != NX_SUCCESS)
5390 {
5391
5392 /* Unable to open file with FTP server. */
5393 return(status);
5394 }
5395
5396 /* Setup pointer to the buffer area. */
5397 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
5398
5399 if (ftp_client_ptr -> nx_ftp_client_control_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
5400 {
5401 #ifndef FEATURE_NX_IPV6
5402 return(NX_NOT_ENABLED);
5403 #else
5404
5405 /* EPSV command, RFC2428. */
5406
5407 /* Check for 2xx message, signaling the "EPSV" was received properly. */
5408 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2') || (buffer_ptr[1] != '2') || (buffer_ptr[2] != '9'))
5409 {
5410
5411 /* Release the packet. */
5412 nx_packet_release(packet_ptr);
5413
5414 /* Unable to open file with FTP server. */
5415 return(NX_FTP_EXPECTED_2XX_CODE);
5416 }
5417
5418 /* The text returned in response to the EPSV command MUST be:
5419 <text indicating server is entering extended passive mode> \
5420 (<d><d><d><tcp-port><d>) */
5421
5422 /* The netowrk address used to establish the data connnection will be the same
5423 network address used for the control connection.
5424 An example response string follows:
5425 Entering Extended Passive Mode (|||6446|) */
5426
5427 /* Check the length. command + <sp> + passive key word "(|||"*/
5428 if (packet_ptr -> nx_packet_length < 8)
5429 {
5430
5431 /* Release the packet. */
5432 nx_packet_release(packet_ptr);
5433 return(NX_FTP_INVALID_COMMAND);
5434 }
5435
5436 /* Set the index. */
5437 i = 7;
5438
5439 /* Skip the text to locate the key word "(|||". */
5440 while (i < packet_ptr -> nx_packet_length)
5441 {
5442
5443 /* Check if match the key word. */
5444 if ((buffer_ptr[i - 3] == '(') &&
5445 (buffer_ptr[i - 2] == '|') &&
5446 (buffer_ptr[i - 1] == '|') &&
5447 (buffer_ptr[i] == '|'))
5448 {
5449 break;
5450 }
5451
5452 /* Move to next character. */
5453 i++;
5454 }
5455
5456 /* Check for properly formated address command from server. */
5457 if (i >= packet_ptr -> nx_packet_length)
5458 {
5459
5460 /* Release the packet. */
5461 nx_packet_release(packet_ptr);
5462 return(NX_FTP_INVALID_COMMAND);
5463 }
5464
5465 /* Update the index to pickup the port number. */
5466 data_port = 0;
5467 i++;
5468 while ((i < packet_ptr -> nx_packet_length) && (buffer_ptr[i] != '|'))
5469 {
5470
5471 /* Is a numeric character present? */
5472 if ((buffer_ptr[i] < '0') || (buffer_ptr[i] > '9'))
5473 {
5474
5475 /* Invalid port number. */
5476 break;
5477 }
5478
5479 /* Yes, numeric character is present. Update the IP port. */
5480 data_port = (data_port * 10) + (UINT) (buffer_ptr[i] - '0');
5481
5482 /* Move to next character. */
5483 i++;
5484 }
5485
5486 /* At this point we are done with the packet. */
5487 nx_packet_release(packet_ptr);
5488
5489 /* Determine if an error occurred. */
5490 if ((buffer_ptr[i] != '|') || (data_port == 0))
5491 {
5492
5493 /* Set the error status. */
5494 return(NX_FTP_INVALID_COMMAND);
5495 }
5496
5497 /* Save the passive IP address and data port. */
5498 COPY_NXD_ADDRESS(&(ftp_client_ptr -> nx_ftp_client_control_socket.nx_tcp_socket_connect_ip), &(ftp_client_ptr -> nx_ftp_client_data_socket.nx_tcp_socket_connect_ip));
5499 ftp_client_ptr -> nx_ftp_client_data_socket.nx_tcp_socket_connect_port = data_port;
5500 #endif /* FEATURE_NX_IPV6 */
5501 }
5502 else
5503 {
5504 #ifdef NX_DISABLE_IPV4
5505 return(NX_NOT_ENABLED);
5506 #else
5507
5508 /* Check for 2xx message, signaling the "PASV" was received properly. */
5509 if ((packet_ptr -> nx_packet_length < 3) || (buffer_ptr[0] != '2') || (buffer_ptr[1] != '2') || (buffer_ptr[2] != '7'))
5510 {
5511
5512 /* Release the packet. */
5513 nx_packet_release(packet_ptr);
5514
5515 /* Unable to open file with FTP server. */
5516 return(NX_FTP_EXPECTED_2XX_CODE);
5517 }
5518
5519 /* Now parse the address and port for the Client to connect to on the data socket.
5520 IP address and port are comma delimited and port number is the last two numbers,
5521 PASV port = (p1 * 256) + p2. */
5522
5523 /* Skip non numeric text and whitespace. */
5524 i = 3;
5525 while (((buffer_ptr[i] > '9') || (buffer_ptr[i] < '0')) && (i < packet_ptr -> nx_packet_length))
5526 {
5527 i++;
5528 }
5529
5530 /* Check for properly formated command from server. */
5531 if (i >= packet_ptr -> nx_packet_length)
5532 {
5533
5534 /* Release the packet. */
5535 nx_packet_release(packet_ptr);
5536 return NX_FTP_INVALID_COMMAND;
5537 }
5538
5539 /* First, pickup the IP address. */
5540 commas = 0;
5541 ip_address = 0;
5542 temp = 0;
5543 status = NX_SUCCESS;
5544
5545 while (i < packet_ptr -> nx_packet_length)
5546 {
5547
5548 /* Is a numeric character present? */
5549 if ((buffer_ptr[i] >= '0') && (buffer_ptr[i] <= '9'))
5550 {
5551
5552 /* Yes, numeric character is present. Update the IP address. */
5553 temp = (temp*10) + (ULONG) (buffer_ptr[i] - '0');
5554 }
5555
5556 /* Determine if a CR/LF is present. */
5557 if ((buffer_ptr[i] == 0x0D) || (buffer_ptr[i] == 0x0A) || (buffer_ptr[i] == 0))
5558 {
5559 status = NX_FTP_INVALID_COMMAND;
5560 break;
5561 }
5562
5563 /* Determine if a comma is present. */
5564 if (buffer_ptr[i] == ',')
5565 {
5566
5567 /* Increment the comma count. */
5568 commas++;
5569
5570 /* Setup next byte of IP address. */
5571 ip_address = (ip_address << 8) & 0xFFFFFFFF;
5572 ip_address = ip_address | (temp & 0xFF);
5573 temp = 0;
5574
5575 /* Have we finished with the IP address? */
5576 if (commas == 4)
5577 {
5578
5579 /* Finished with IP address. */
5580 i++;
5581 break;
5582 }
5583 }
5584
5585 /* Move to next character. */
5586 i++;
5587 }
5588
5589 /* Now pickup the port number. */
5590 data_port = 0;
5591 temp = 0;
5592 while (i < packet_ptr -> nx_packet_length)
5593 {
5594
5595 /* Is a numeric character present? */
5596 if ((buffer_ptr[i] >= '0') && (buffer_ptr[i] <= '9'))
5597 {
5598
5599 /* Yes, numeric character is present. Update the IP port. */
5600 temp = (temp*10) + (UINT) (buffer_ptr[i] - '0');
5601 }
5602
5603 /* Determine if a CR/LF is present. */
5604 if ((buffer_ptr[i] == 0x0D) || (buffer_ptr[i] == 0x0A) || (buffer_ptr[i] == 0))
5605 {
5606 /* Good condition on the port number! */
5607 break;
5608 }
5609
5610 /* Determine if a comma is present. */
5611 if (buffer_ptr[i] == ',')
5612 {
5613
5614 /* Increment the comma count. */
5615 commas++;
5616
5617 /* Move the data port number up. */
5618 data_port = (data_port << 8) & 0xFFFFFFFF;
5619 data_port = data_port | (temp & 0xFF);
5620 temp = 0;
5621
5622 /* Have we finished with the port? */
5623 if (commas >= 6)
5624 {
5625
5626 /* Error, get out of the loop. */
5627 status = NX_FTP_INVALID_ADDRESS;
5628 break;
5629 }
5630 }
5631
5632 /* Move to next character. */
5633 i++;
5634 }
5635
5636 /* Move port number up. */
5637 data_port = (data_port << 8) & 0xFFFFFFFF;
5638 data_port = data_port | (temp & 0xFF);
5639
5640 /* At this point we are done with the packet. */
5641 nx_packet_release(packet_ptr);
5642
5643 /* Determine if an error occurred. */
5644 if ((status != NX_SUCCESS) || (buffer_ptr[i] != 13) || (commas != 5) || (ip_address == 0) || (data_port == 0))
5645 {
5646
5647 /* Set the error status. */
5648 return NX_FTP_INVALID_COMMAND;
5649 }
5650
5651 /* Save the passive IP address and data port. */
5652 ftp_client_ptr -> nx_ftp_client_data_socket.nx_tcp_socket_connect_ip.nxd_ip_version = NX_IP_VERSION_V4;
5653 ftp_client_ptr -> nx_ftp_client_data_socket.nx_tcp_socket_connect_ip.nxd_ip_address.v4 = ip_address;
5654 ftp_client_ptr -> nx_ftp_client_data_socket.nx_tcp_socket_connect_port = data_port;
5655
5656 #endif /* NX_DISABLE_IPV4 */
5657 }
5658
5659 /* Bind the client data socket to any port. */
5660 status = nx_tcp_client_socket_bind((&ftp_client_ptr -> nx_ftp_client_data_socket), NX_ANY_PORT, wait_option);
5661
5662 /* Check for an error. */
5663 if (status != NX_SUCCESS)
5664 {
5665
5666 /* Unable to bind socket to port. */
5667 return(status);
5668 }
5669
5670 /* Now connect to the IP address and port the server asked us to. */
5671 status = nxd_tcp_client_socket_connect(&(ftp_client_ptr -> nx_ftp_client_data_socket),
5672 &(ftp_client_ptr -> nx_ftp_client_data_socket.nx_tcp_socket_connect_ip),
5673 data_port, wait_option);
5674
5675 /* Check for an error. */
5676 if (status != NX_SUCCESS)
5677 {
5678
5679 /* Unbind the socket. */
5680 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_data_socket));
5681 }
5682
5683 return(status);
5684 }
5685
5686
5687 /**************************************************************************/
5688 /* */
5689 /* FUNCTION RELEASE */
5690 /* */
5691 /* _nx_ftp_client_data_socket_cleanup PORTABLE C */
5692 /* 6.1 */
5693 /* AUTHOR */
5694 /* */
5695 /* Yuxin Zhou, Microsoft Corporation */
5696 /* */
5697 /* DESCRIPTION */
5698 /* */
5699 /* This function cleans up the data socket. */
5700 /* */
5701 /* INPUT */
5702 /* */
5703 /* ftp_client_ptr Pointer to FTP client */
5704 /* */
5705 /* OUTPUT */
5706 /* */
5707 /* None */
5708 /* */
5709 /* CALLS */
5710 /* */
5711 /* nx_tcp_socket_disconnect Disconnect a socket */
5712 /* nx_tcp_client_socket_unbind Release the data socket port */
5713 /* nx_tcp_server_socket_unaccept Unaccept server connection */
5714 /* nx_tcp_server_socket_unlisten Unlisten on server socket */
5715 /* */
5716 /* CALLED BY */
5717 /* */
5718 /* _nx_ftp_client_file_open Open a file for read or write */
5719 /* _nx_ftp_client_file_close Actual client file close call */
5720 /* _nx_ftp_client_directory_listing_get Get directory list */
5721 /* _nx_ftp_client_directory_listing_continue */
5722 /* Continue to get directory list*/
5723 /* */
5724 /* RELEASE HISTORY */
5725 /* */
5726 /* DATE NAME DESCRIPTION */
5727 /* */
5728 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5729 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5730 /* resulting in version 6.1 */
5731 /* */
5732 /**************************************************************************/
_nx_ftp_client_data_socket_cleanup(NX_FTP_CLIENT * ftp_client_ptr,ULONG wait_option)5733 VOID _nx_ftp_client_data_socket_cleanup(NX_FTP_CLIENT *ftp_client_ptr, ULONG wait_option)
5734 {
5735
5736
5737 /* Disconnect the data socket. */
5738 nx_tcp_socket_disconnect(&(ftp_client_ptr -> nx_ftp_client_data_socket), wait_option);
5739
5740 /* Check if enable passive mode. */
5741 if (ftp_client_ptr -> nx_ftp_client_passive_transfer_enabled == NX_FALSE)
5742 {
5743
5744 /* Unaccept the data socket. */
5745 nx_tcp_server_socket_unaccept(&(ftp_client_ptr -> nx_ftp_client_data_socket));
5746
5747 /* Stop listening on the data port. */
5748 nx_tcp_server_socket_unlisten(ftp_client_ptr -> nx_ftp_client_ip_ptr,
5749 ftp_client_ptr -> nx_ftp_client_data_socket.nx_tcp_socket_port);
5750 }
5751 else
5752 {
5753
5754 /* Release the socket port. */
5755 nx_tcp_client_socket_unbind(&(ftp_client_ptr -> nx_ftp_client_data_socket));
5756 }
5757
5758 /* Clear the block size. */
5759 ftp_client_ptr -> nx_ftp_client_block_total_size = 0;
5760 ftp_client_ptr -> nx_ftp_client_block_remaining_size = 0;
5761 }
5762
5763
5764 /**************************************************************************/
5765 /* */
5766 /* FUNCTION RELEASE */
5767 /* */
5768 /* _nx_ftp_client_block_mode_send PORTABLE C */
5769 /* 6.1 */
5770 /* AUTHOR */
5771 /* */
5772 /* Yuxin Zhou, Microsoft Corporation */
5773 /* */
5774 /* DESCRIPTION */
5775 /* */
5776 /* This function sends MODE B command to FTP server for block mode. */
5777 /* */
5778 /* INPUT */
5779 /* */
5780 /* ftp_client_ptr Pointer to FTP client */
5781 /* */
5782 /* OUTPUT */
5783 /* */
5784 /* status Completion status */
5785 /* */
5786 /* CALLS */
5787 /* */
5788 /* nx_packet_release Release packet */
5789 /* nx_tcp_socket_send Send data packet to server */
5790 /* */
5791 /* CALLED BY */
5792 /* */
5793 /* _nx_ftp_client_file_open Open a file for read or write */
5794 /* _nx_ftp_client_directory_listing_get Get directory list */
5795 /* */
5796 /* RELEASE HISTORY */
5797 /* */
5798 /* DATE NAME DESCRIPTION */
5799 /* */
5800 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5801 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5802 /* resulting in version 6.1 */
5803 /* */
5804 /**************************************************************************/
_nx_ftp_client_block_mode_send(NX_FTP_CLIENT * ftp_client_ptr,ULONG wait_option)5805 UINT _nx_ftp_client_block_mode_send(NX_FTP_CLIENT *ftp_client_ptr, ULONG wait_option)
5806 {
5807
5808 UINT status;
5809 NX_PACKET *packet_ptr;
5810 UCHAR *buffer_ptr;
5811
5812
5813 /* Send MODE B command. */
5814
5815 /* Allocate the packet. */
5816 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, NX_NO_WAIT);
5817
5818 /* Determine if the send was unsuccessful. */
5819 if (status)
5820 {
5821
5822 /* Return error. */
5823 return(status);
5824 }
5825
5826 /* We have a packet, setup pointer to the buffer area. */
5827 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
5828
5829 /* Now build the actual MODE B request. */
5830 buffer_ptr[0] = 'M';
5831 buffer_ptr[1] = 'O';
5832 buffer_ptr[2] = 'D';
5833 buffer_ptr[3] = 'E';
5834 buffer_ptr[4] = ' ';
5835 buffer_ptr[5] = 'B';
5836
5837 /* Insert the CR/LF. */
5838 buffer_ptr[6] = 13;
5839 buffer_ptr[7] = 10;
5840
5841 /* Setup the length of the packet. */
5842 packet_ptr -> nx_packet_length = 8;
5843
5844 /* Setup the packet append pointer. */
5845 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
5846
5847 /* Send the MODE B message. */
5848 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_control_socket), packet_ptr, wait_option);
5849
5850 /* Determine if the send was unsuccessful. */
5851 if (status != NX_SUCCESS)
5852 {
5853
5854 /* Release the packet. */
5855 nx_packet_release(packet_ptr);
5856
5857 /* Return error. */
5858 return(status);
5859 }
5860
5861 /* Now wait for response from the FTP server control port. */
5862 status = nx_tcp_socket_receive(&(ftp_client_ptr -> nx_ftp_client_control_socket), &packet_ptr, wait_option);
5863
5864 /* Determine if a packet was not received. */
5865 if (status != NX_SUCCESS)
5866 {
5867
5868 /* Unable to open file with FTP server. */
5869 return(status);
5870 }
5871
5872 /* We have a packet, setup pointer to the buffer area. */
5873 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
5874
5875 /* Check for 2xx message, signaling the data port was connected properly and ready for transfer. */
5876 if (buffer_ptr[0] != '2')
5877 {
5878
5879 /* Release the packet. */
5880 nx_packet_release(packet_ptr);
5881
5882 /* Unable to open file with FTP server. */
5883 return(NX_FTP_EXPECTED_2XX_CODE);
5884 }
5885
5886 /* Release the packet. */
5887 nx_packet_release(packet_ptr);
5888
5889 /* Return success to caller. */
5890 return(NX_SUCCESS);
5891 }
5892
5893
5894 /**************************************************************************/
5895 /* */
5896 /* FUNCTION RELEASE */
5897 /* */
5898 /* _nx_ftp_client_block_header_send PORTABLE C */
5899 /* 6.1 */
5900 /* AUTHOR */
5901 /* */
5902 /* Yuxin Zhou, Microsoft Corporation */
5903 /* */
5904 /* DESCRIPTION */
5905 /* */
5906 /* This function sends the block header for block mode. */
5907 /* */
5908 /* INPUT */
5909 /* */
5910 /* ftp_client_ptr Pointer to FTP client */
5911 /* block_size The size of block data */
5912 /* */
5913 /* OUTPUT */
5914 /* */
5915 /* status Completion status */
5916 /* */
5917 /* CALLS */
5918 /* */
5919 /* nx_packet_release Release packet */
5920 /* nx_tcp_socket_send Send data packet to server */
5921 /* */
5922 /* CALLED BY */
5923 /* */
5924 /* _nx_ftp_client_file_size_set Set the file size for writing */
5925 /* _nx_ftp_client_file_write Send data packet to server */
5926 /* */
5927 /* RELEASE HISTORY */
5928 /* */
5929 /* DATE NAME DESCRIPTION */
5930 /* */
5931 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5932 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5933 /* resulting in version 6.1 */
5934 /* */
5935 /**************************************************************************/
_nx_ftp_client_block_header_send(NX_FTP_CLIENT * ftp_client_ptr,ULONG block_size)5936 UINT _nx_ftp_client_block_header_send(NX_FTP_CLIENT *ftp_client_ptr, ULONG block_size)
5937 {
5938
5939 UINT status;
5940 NX_PACKET *packet_ptr;
5941 UCHAR *buffer_ptr;
5942
5943
5944 /* Use block mode to transfer data. RFC959, Section3.4.2, Page21-22. */
5945
5946 /* Allocate the packet. */
5947 status = _nx_ftp_client_packet_allocate(ftp_client_ptr, &packet_ptr, NX_NO_WAIT);
5948
5949 /* Determine if the send was unsuccessful. */
5950 if (status)
5951 {
5952
5953 /* Return error. */
5954 return(status);
5955 }
5956
5957 /* We have a packet, setup pointer to the buffer area. */
5958 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
5959
5960 /* Set the block header. */
5961 if (block_size)
5962 {
5963
5964 /* Descriptor. */
5965 buffer_ptr[0] = 0;
5966
5967 /* Byte count. */
5968 buffer_ptr[1] = (UCHAR)(block_size >> 8);
5969 buffer_ptr[2] = (UCHAR)(block_size);
5970 }
5971 else
5972 {
5973
5974 /* Descriptor. */
5975 buffer_ptr[0] = 64;
5976
5977 /* Byte count. */
5978 buffer_ptr[1] = 0;
5979 buffer_ptr[2] = 0;
5980 }
5981
5982 /* Setup the length of the packet. */
5983 packet_ptr -> nx_packet_length = 3;
5984
5985 /* Setup the packet append pointer. */
5986 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
5987
5988 /* Write packet payload to the file. */
5989 status = nx_tcp_socket_send(&(ftp_client_ptr -> nx_ftp_client_data_socket), packet_ptr, NX_NO_WAIT);
5990
5991 /* Determine if the send was unsuccessful. */
5992 if (status)
5993 {
5994
5995 /* Release the packet. */
5996 nx_packet_release(packet_ptr);
5997 }
5998
5999 /* Return success to caller. */
6000 return(status);
6001 }
6002
6003
6004 /**************************************************************************/
6005 /* */
6006 /* FUNCTION RELEASE */
6007 /* */
6008 /* _nx_ftp_client_block_header_retrieve PORTABLE C */
6009 /* 6.1 */
6010 /* AUTHOR */
6011 /* */
6012 /* Yuxin Zhou, Microsoft Corporation */
6013 /* */
6014 /* DESCRIPTION */
6015 /* */
6016 /* This function retrieves the block header for block mode. */
6017 /* */
6018 /* INPUT */
6019 /* */
6020 /* ftp_client_ptr Pointer to FTP client */
6021 /* packet_ptr Pointer to packet to write */
6022 /* */
6023 /* OUTPUT */
6024 /* */
6025 /* status Completion status */
6026 /* */
6027 /* CALLS */
6028 /* */
6029 /* nx_packet_release Release packet */
6030 /* nx_tcp_socket_send Send data packet to server */
6031 /* */
6032 /* CALLED BY */
6033 /* */
6034 /* _nx_ftp_client_file_read Read data from server */
6035 /* _nx_ftp_client_directory_listing_get Get directory list */
6036 /* _nx_ftp_client_directory_listing_continue */
6037 /* Continue to get directory list*/
6038 /* */
6039 /* RELEASE HISTORY */
6040 /* */
6041 /* DATE NAME DESCRIPTION */
6042 /* */
6043 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6044 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6045 /* resulting in version 6.1 */
6046 /* */
6047 /**************************************************************************/
_nx_ftp_client_block_header_retrieve(NX_FTP_CLIENT * ftp_client_ptr,NX_PACKET * packet_ptr)6048 UINT _nx_ftp_client_block_header_retrieve(NX_FTP_CLIENT *ftp_client_ptr, NX_PACKET *packet_ptr)
6049 {
6050
6051 ULONG delta;
6052 UCHAR *buffer_ptr;
6053 #ifndef NX_DISABLE_PACKET_CHAIN
6054 NX_PACKET *before_last_packet;
6055 NX_PACKET *last_packet;
6056 #endif /* NX_DISABLE_PACKET_CHAIN */
6057
6058
6059 /* Check if it is the first packet. */
6060 if (ftp_client_ptr -> nx_ftp_client_block_total_size == 0)
6061 {
6062
6063 /* Check the packet length. */
6064 if ((packet_ptr -> nx_packet_length < 3) ||
6065 (packet_ptr -> nx_packet_prepend_ptr + 3 > packet_ptr -> nx_packet_append_ptr))
6066 {
6067
6068 /* Release the packet. */
6069 nx_packet_release(packet_ptr);
6070 return(NX_FTP_CLIENT_INVALID_SIZE);
6071 }
6072
6073 /* We have a packet, setup pointer to the buffer area. */
6074 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
6075
6076 /* Process block header. */
6077 ftp_client_ptr -> nx_ftp_client_block_total_size = (ULONG)((buffer_ptr[1] << 8) | buffer_ptr[2]);
6078 ftp_client_ptr -> nx_ftp_client_block_remaining_size = ftp_client_ptr -> nx_ftp_client_block_total_size;
6079
6080 /* Skip the block header. */
6081 packet_ptr -> nx_packet_prepend_ptr += 3;
6082 packet_ptr -> nx_packet_length -= 3;
6083 }
6084
6085 /* Check if have remaining data. */
6086 if (ftp_client_ptr -> nx_ftp_client_block_remaining_size == 0)
6087 {
6088
6089 /* Release the packet. */
6090 nx_packet_release(packet_ptr);
6091 return(NX_FTP_CLIENT_END_OF_BLOCK);
6092 }
6093
6094 /* Check the data of current packet. */
6095 if (ftp_client_ptr -> nx_ftp_client_block_remaining_size < packet_ptr -> nx_packet_length)
6096 {
6097
6098 /* Remove the extra data, such as: end block header. */
6099
6100 /* Calculate the difference in the length. */
6101 delta = packet_ptr -> nx_packet_length - ftp_client_ptr -> nx_ftp_client_block_remaining_size;
6102
6103 /* Adjust the packet length. */
6104 packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - delta;
6105
6106 /* Adjust the append pointer. */
6107
6108 #ifndef NX_DISABLE_PACKET_CHAIN
6109 /* Loop to process adjustment that spans multiple packets. */
6110 while (delta)
6111 {
6112
6113 /* Determine if the packet is chained (or still chained after the adjustment). */
6114 if (packet_ptr -> nx_packet_last == NX_NULL)
6115 {
6116
6117 /* No, packet is not chained, simply adjust the append pointer in the packet. */
6118 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_append_ptr - delta;
6119
6120 /* Break out of the loop, since the adjustment is complete. */
6121 break;
6122 }
6123
6124 /* Pickup the pointer to the last packet. */
6125 last_packet = packet_ptr -> nx_packet_last;
6126
6127 /* Determine if the amount to adjust is less than the payload in the last packet. */
6128 /*lint -e{946} -e{947} suppress pointer subtraction, since it is necessary. */
6129 if (((ULONG)(last_packet -> nx_packet_append_ptr - last_packet -> nx_packet_prepend_ptr)) > delta)
6130 {
6131
6132 /* Yes, simply adjust the append pointer of the last packet in the chain. */
6133 /*lint -e{946} -e{947} suppress pointer subtraction, since it is necessary. */
6134 last_packet -> nx_packet_append_ptr = last_packet -> nx_packet_append_ptr - delta;
6135
6136 /* Get out of the loop, since the adjustment is complete. */
6137 break;
6138 }
6139 else
6140 {
6141
6142 /* Adjust the delta by the amount in the last packet. */
6143 delta = delta - ((ULONG)(last_packet -> nx_packet_append_ptr - last_packet -> nx_packet_prepend_ptr));
6144
6145 /* Find the packet before the last packet. */
6146 before_last_packet = packet_ptr;
6147 while (before_last_packet -> nx_packet_next != last_packet)
6148 {
6149
6150 /* Move to the next packet in the chain. */
6151 before_last_packet = before_last_packet -> nx_packet_next;
6152 }
6153
6154 /* At this point, we need to release the last packet and adjust the other packet
6155 pointers. */
6156
6157 /* Ensure the next packet pointer is NULL in what is now the last packet. */
6158 before_last_packet -> nx_packet_next = NX_NULL;
6159
6160 /* Determine if the packet is still chained. */
6161 if (packet_ptr != before_last_packet)
6162 {
6163
6164 /* Yes, the packet is still chained, setup the last packet pointer. */
6165 packet_ptr -> nx_packet_last = before_last_packet;
6166 }
6167 else
6168 {
6169
6170 /* The packet is no longer chained, set the last packet pointer to NULL. */
6171 packet_ptr -> nx_packet_last = NX_NULL;
6172 }
6173
6174 /* Release the last packet. */
6175 _nx_packet_release(last_packet);
6176 }
6177 }
6178 #else
6179
6180 /* Simply adjust the append pointer in the packet. */
6181 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_append_ptr - delta;
6182 #endif /* NX_DISABLE_PACKET_CHAIN */
6183 }
6184
6185 /* Update the file size. */
6186 ftp_client_ptr -> nx_ftp_client_block_remaining_size -= packet_ptr -> nx_packet_length;
6187
6188 /* Return success to caller. */
6189 return(NX_SUCCESS);
6190 }
6191