1 /* This NetX test concentrates on the basic SMTP operation. The Server supports
2    auth login, auth plain and will send a one packet response to the EHLO message. The Client
3    then authenticates itself by AUTH LOGIN, sends a message of three packets, and quits. */
4 
5 
6 #include   "tx_api.h"
7 #include   "nx_api.h"
8 
9 
10 extern void test_control_return(UINT status);
11 
12 #if !defined(NX_DISABLE_IPV4)
13 
14 #include   "nxd_smtp_client.h"
15 
16 #define     DEMO_STACK_SIZE         2048
17 #define     SERVER_IPADR            IP_ADDRESS(10, 0, 0, 1)
18 #define     CLIENT_IPADR            IP_ADDRESS(10, 0, 0, 10)
19 
20 /* Define the ThreadX and NetX object control blocks...  */
21 
22 static TX_THREAD               thread_client;
23 static TX_THREAD               thread_server;
24 
25 static NX_PACKET_POOL          client_packet_pool;
26 static NX_IP                   client_ip;
27 static NX_IP                   server_ip;
28 
29 
30 static NX_PACKET_POOL          server_packet_pool;
31 static NX_TCP_SOCKET           server_socket;
32 static NX_SMTP_CLIENT          smtp_client;
33 
34 #define SUBJECT_LINE           "NetX Duo SMTP Client Demo"
35 #define MAIL_BODY              ".NetX Duo SMTP client is a simple SMTP client implementation  \r\n" \
36                                ".that allow embedded devices to send email to an SMTP server. \r\n" \
37                                "This feature is intended to allow a device to send simple status\r\n " \
38                                "reports using the most universal Internet application email.\r\n" \
39                                "The rest of this narrative is merely to supply this most interesting quote: \r\n" \
40                                "Perhaps the most vivid recollection of my youth is that of the local wheelmen, \r\n" \
41                                "led by my father, stopping at our home to eat pone, sip mint juleps, and flog \r\n" \
42                                "the field hands. This more than anything cultivated my life-long aversion \r\n"  \
43                                "to bicycles. ~~ Tennessee Williams.\r\n\r\n" \
44                                "Nothing compares to the simple pleasure of a bike ride. --John F. Kennedy, (surely you've heard of him?)\r\n\r\n" \
45                                "Perhaps the most vivid recollection of my youth is that of being flogged \r\n" \
46                                "by the local wheelmen, along with the field hands, the postman, and a \r\n" \
47                                "young Tennessee Williams. This more than anything cultivated my life-long " \
48                                "aversion to his plays. -Truman Capote\r\n" \
49                                "When I see an adult on a bicycle, I do not despair for the future of the human race. H.G. Wells \r\n"  \
50                                "during the Second World War, if the United States had retooled its \r\n" \
51                                "factories for manufacturing bicycles instead of munitions, we'd be one of \r\n" \
52                                "the healthiest, least oil-dependent, and most environmentally-sound \r\n" \
53                                "constituents in the Nazi empire today. -Ralph Nader."
54 
55 
56 #define PASSWORD               "testpwd"
57 #define RECIPIENT_ADDRESS      "recipient@domain.com"
58 #define LOCAL_DOMAIN           "domain.com"
59 #define FROM_ADDRESS           "recipient@domain.com"
60 #define USERNAME               FROM_ADDRESS
61 #define SMTP_SERVER_PORT       25
62 
63 
64 /* See the NetX Duo SMTP Client User Guide for how to set the authentication type.  */
65 #define CLIENT_AUTHENTICATION_TYPE NX_SMTP_CLIENT_AUTH_PLAIN
66 
67 #if defined(__PRODUCT_NETXDUO__)
68 static NXD_ADDRESS server_ip_address;
69 #else
70 static ULONG server_ip_address;
71 #endif
72 
73 
74 static UINT server_complete = NX_FALSE;
75 
76 /* Define the counters used in the demo application...  */
77 
78 static UINT                    status;
79 static ULONG                   error_counter = 0;
80 static ULONG                   notify_calls =  0;
81 
82 /* Define thread prototypes.  */
83 
84 static void    thread_0_entry(ULONG thread_input);
85 static void    thread_1_entry(ULONG thread_input);
86 extern void    _nx_ram_network_driver_1024(struct NX_IP_DRIVER_STRUCT *driver_req);
87 static void    receive_packet_function(NX_TCP_SOCKET *socket_ptr);
88 
89 /* SMTP Tests.  */
90 static void    smtp_test_initialize();
91 
92 /* Send SMTP server response.  */
93 static UINT    nx_smtp_response_packet_send(NX_TCP_SOCKET *server_socket, UINT port, UINT packet_number);
94 
95 extern char response_220_greetings_pkt[185];
96 extern int  response_220_greetings_size;
97 
98 /* This is the one packet 250 EHLO message */
99 extern char response_250_ehlo_pkt[145];
100 extern int response_250_ehlo_size;
101 
102 extern char response_334_pkt[6];
103 extern int response_334_size;
104 
105 extern char response_235_auth_passed_pkt[85];
106 extern int response_235_auth_passed_size;
107 
108 extern char response_250_sender_ok_pkt[40];
109 extern int response_250_sender_ok_size;
110 
111 extern char response_250_recipient_ok_pkt[43];
112 extern int response_250_recipient_ok_size;
113 
114 extern char response_354_enter_mail_pkt[40];
115 extern int response_354_enter_mail_size;
116 
117 extern char response_250_message_saved_pkt[92];
118 extern int response_250_message_saved_size;
119 
120 extern char response_221_bye_pkt[80];
121 extern int response_221_bye_size;
122 
123 
124 typedef struct SMTP_TEST_STRUCT
125 {
126     char          *smtp_test_pkt_data;
127     int           smtp_test_pkt_size;
128 } SMTP_TEST;
129 
130 
131 #define MSG_COUNT      9
132 
133 static SMTP_TEST       smtp_test[MSG_COUNT];
134 
135 
136 /* Define what the initial system looks like.  */
137 
138 #ifdef CTEST
test_application_define(void * first_unused_memory)139 VOID test_application_define(void *first_unused_memory)
140 #else
141 void    netx_smtp_basic_function_test_application_define(void *first_unused_memory)
142 #endif
143 {
144 
145 CHAR    *pointer;
146 
147     /* Setup the working pointer.  */
148     pointer =  (CHAR *) first_unused_memory;
149 
150     /* Create the SMTP client thread.  */
151     tx_thread_create(&thread_client, "thread client", thread_0_entry, 0,
152             pointer, DEMO_STACK_SIZE,
153             4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
154     pointer =  pointer + DEMO_STACK_SIZE;
155 
156     tx_thread_create(&thread_server, "thread server", thread_1_entry, 0,
157             pointer, DEMO_STACK_SIZE,
158             3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
159     pointer =  pointer + DEMO_STACK_SIZE;
160 
161     /* Initialize the NetX system.  */
162     nx_system_initialize();
163 
164     /* Create client packet pool.  */
165     status =  nx_packet_pool_create(&client_packet_pool, "NetX Main Packet Pool", 1536, pointer, 10*1536);
166     pointer = pointer + (10*1536);
167 
168     /* Check for pool creation error.  */
169     if (status)
170         return;
171 
172     /* Create server packet pool.  */
173     status =  nx_packet_pool_create(&server_packet_pool, "NetX Main Packet Pool", 1536, pointer, 10*1536);
174     pointer = pointer + (10*1536);
175 
176     /* Check for pool creation error.  */
177     if (status)
178         return;
179 
180     /* Create an IP instance.  */
181     status = nx_ip_create(&client_ip, "SMTP CLient IP", CLIENT_IPADR, 0xFFFFFF00UL, &client_packet_pool, _nx_ram_network_driver_1024,
182                     pointer, 2048, 1);
183     pointer =  pointer + 2048;
184 
185     /* Create another IP instance.  */
186     status += nx_ip_create(&server_ip, "SMTP Server IP", SERVER_IPADR, 0xFFFFFF00UL, &server_packet_pool, _nx_ram_network_driver_1024,
187                     pointer, 2048, 1);
188     pointer =  pointer + 2048;
189 
190     /* Check for IP create errors.  */
191     if (status)
192         error_counter++;
193 
194     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
195     status =  nx_arp_enable(&client_ip, (void *) pointer, 1024);
196     pointer = pointer + 1024;
197 
198     /* Enable ARP and supply ARP cache memory for IP Instance 1.  */
199     status +=  nx_arp_enable(&server_ip, (void *) pointer, 1024);
200     pointer = pointer + 1024;
201 
202     /* Check for ARP enable errors.  */
203     if (status)
204         error_counter++;
205 
206     /* Enable TCP traffic.  */
207     status =  nx_tcp_enable(&client_ip);
208     status += nx_tcp_enable(&server_ip);
209 
210     /* Check for TCP enable errors.  */
211     if (status)
212         error_counter++;
213 
214 
215     /* The demo client username and password is the authentication
216    data used when the server attempts to authentication the client. */
217 
218 #if defined(__PRODUCT_NETXDUO__)
219     server_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
220     server_ip_address.nxd_ip_address.v4 = SERVER_IPADR;
221 
222     status =  nxd_smtp_client_create(&smtp_client, &client_ip, &client_packet_pool,
223                                      USERNAME,
224                                      PASSWORD,
225                                      FROM_ADDRESS,
226                                      LOCAL_DOMAIN, CLIENT_AUTHENTICATION_TYPE,
227                                      &server_ip_address, SMTP_SERVER_PORT);
228 #else
229     server_ip_address = SERVER_IPADR;
230 
231     status =  nx_smtp_client_create(&smtp_client, &client_ip, &client_packet_pool,
232                                      USERNAME,
233                                      PASSWORD,
234                                      FROM_ADDRESS,
235                                      LOCAL_DOMAIN, CLIENT_AUTHENTICATION_TYPE,
236                                      server_ip_address, SMTP_SERVER_PORT);
237 #endif
238 
239     if (status != NX_SUCCESS)
240     {
241         error_counter++;
242     }
243 
244     return;
245 }
246 
247 
248 /* Define the test threads.  */
249 
thread_0_entry(ULONG thread_input)250 static void    thread_0_entry(ULONG thread_input)
251 {
252 
253 ULONG       actual_status;
254 UINT        wait_timeout = 300;
255 
256 
257     printf("NetX Test:   SMTP Basic Function Test..................................");
258 
259     /* Check for earlier errors.  */
260     if(error_counter)
261     {
262         printf("ERROR!\n");
263         test_control_return(1);
264     }
265 
266 #ifdef FEATURE_NX_IPV6
267     /* Sleep 5 seconds to finish DAD.  */
268     tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
269 #endif
270 
271     /* Ensure the IP instance has been initialized.  */
272     status = nx_ip_status_check(&client_ip, NX_IP_INITIALIZE_DONE, &actual_status, 100);
273 
274     /* Check status...*/
275     if(status != NX_SUCCESS)
276     {
277         printf("ERROR!\n");
278         test_control_return(1);
279     }
280 
281     /* Let the server get set up first. */
282     tx_thread_sleep(20);
283 
284 
285     /* The SMTP test initialize.  */
286     smtp_test_initialize();
287 
288      /* Create a mail instance with the above text message and recipient info. */
289     status =  nx_smtp_mail_send(&smtp_client, RECIPIENT_ADDRESS, NX_SMTP_MAIL_PRIORITY_NORMAL,
290                                 SUBJECT_LINE, MAIL_BODY, strlen(MAIL_BODY));
291 
292     /* Create a mail instance with the above text message and recipient info. */
293 
294     /* Check for errors. */
295     if (status != NX_SUCCESS)
296     {
297         error_counter++;
298     }
299 
300     /* Give the server time to disconnect. */
301     while(wait_timeout)
302     {
303 
304         if (server_complete)
305             break;
306 
307         tx_thread_sleep(20);
308 
309         wait_timeout -= 20;
310     }
311 
312     /* Release threadx resources used by client. */
313     status = nx_smtp_client_delete(&smtp_client);
314 
315     /* Return the test result.  */
316     if (error_counter)
317     {
318         printf("ERROR!\n");
319         test_control_return(1);
320     }
321     else
322     {
323 
324         printf("SUCCESS!\n");
325         test_control_return(0);
326     }
327 }
328 
329 /* This thread task simulates SMTP server response to client requests. */
thread_1_entry(ULONG thread_input)330 static void    thread_1_entry(ULONG thread_input)
331 {
332 
333 NX_PACKET   *my_packet;
334 ULONG       port;
335 ULONG       peer_address;
336 UINT        i;
337 UCHAR      *work_ptr;
338 ULONG      actual_status;
339 
340 
341     /* Check for earlier errors.  */
342     if(error_counter)
343     {
344         printf("ERROR!\n");
345         test_control_return(1);
346     }
347 
348 #ifdef FEATURE_NX_IPV6
349     /* Sleep 5 seconds to finish DAD.  */
350     tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
351 #endif /* FEATURE_NX_IPV6 */
352 
353     /* Ensure the IP instance has been initialized.  */
354     status = nx_ip_status_check(&server_ip, NX_IP_INITIALIZE_DONE, &actual_status, 100);
355 
356     /* Check status...*/
357     if(status != NX_SUCCESS)
358     {
359         printf("ERROR!\n");
360         test_control_return(1);
361     }
362 
363     /* Create a TCP socket act as the SMTP server.  */
364     status = nx_tcp_socket_create(&server_ip, &server_socket, "Socket 1",
365                                   NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE,
366                                   8000, NX_NULL, NX_NULL);
367 
368     /* Check status.  */
369     if (status)
370     {
371         error_counter++;
372     }
373 
374     /* Register the receive notify function.  */
375     status =  nx_tcp_socket_receive_notify(&server_socket, receive_packet_function);
376 
377     /* Check status.  */
378     if (status)
379     {
380         error_counter++;
381     }
382 
383     /* Bind the TCP socket to the SMTP port.  */
384     status =  nx_tcp_server_socket_listen(&server_ip, SMTP_SERVER_PORT, &server_socket, 5, NX_NULL);
385 
386     /* Check status.  */
387     if (status)
388     {
389         error_counter++;
390     }
391 
392     status = nx_tcp_server_socket_accept(&server_socket, NX_WAIT_FOREVER);
393 
394         /* Check status.  */
395     if (status)
396     {
397         error_counter++;
398     }
399 
400     /* Act as the SMTP server to receive the SMTP Client query and send the SMTP response.  */
401     for (i = 0; i < MSG_COUNT; i++ )
402     {
403 
404         if (i == 0)
405         {
406             /* This is the greeting, we don't wait for a client response first...*/
407         }
408         else
409         {
410             /* Receive a TCP packet.  */
411             status =  nx_tcp_socket_receive(&server_socket, &my_packet, 100 * NX_IP_PERIODIC_RATE);
412 
413             /* Check status.  */
414             if (status)
415             {
416                 error_counter++;
417                 continue;
418             }
419 
420             /* Get the SMTP client TCP port.  */
421             status = nx_tcp_socket_peer_info_get(&server_socket, &peer_address, &port);
422 
423             /* Check status.  */
424             if (status)
425             {
426                error_counter++;
427             }
428 
429             /* This is the message data. We need to parse for the End Of Message marker. */
430             if (i == 7)
431             {
432                 /* Look for 0x0D 0x0A 0x2E 0x0d 0x0A indiating end of mail message. */
433                 work_ptr = my_packet -> nx_packet_prepend_ptr + my_packet -> nx_packet_length - 5;
434 
435                 if ((*work_ptr == 0x0D) &&
436                     (*(work_ptr + 1) == 0x0A) &&
437                     (*(work_ptr + 2) == 0x2E) &&
438                     (*(work_ptr + 3) == 0x0D) &&
439                     (*(work_ptr + 4) == 0x0A))
440 
441                 {
442 
443                     /* Done iwth message, wait for QUIT command from client. */
444                 }
445                 else
446                 {
447 
448                     /* Stay in this state. */
449 
450                     i--;
451                     nx_packet_release(my_packet);
452                     continue;
453                 }
454              }
455             /* Release the packet.  */
456             nx_packet_release(my_packet);
457         }
458         /* Send the SMTP response packet.  */
459         status = nx_smtp_response_packet_send(&server_socket, port, i);
460 
461         /* Check status.  */
462         if (status)
463         {
464             error_counter++;
465         }
466     }
467 
468     /* Wait for Client process last message. */
469     tx_thread_sleep(20);
470 
471     /* Unlisten and Unbind the TCP socket.  */
472 
473     status = nx_tcp_server_socket_unaccept(&server_socket);
474     status += nx_tcp_server_socket_unlisten(&server_ip, SMTP_SERVER_PORT);
475 
476     /* Check status.  */
477     if (status)
478     {
479         error_counter++;
480     }
481 
482     /* Delete the TCP socket.  */
483     status =  nx_tcp_socket_delete(&server_socket);
484 
485     /* Check status.  */
486     if (status)
487     {
488         error_counter++;
489     }
490 
491     server_complete = NX_TRUE;
492 
493 }
494 
receive_packet_function(NX_TCP_SOCKET * socket_ptr)495 static void    receive_packet_function(NX_TCP_SOCKET *socket_ptr)
496 {
497 
498     if (socket_ptr == &server_socket)
499         notify_calls++;
500 }
501 
nx_smtp_response_packet_send(NX_TCP_SOCKET * server_socket,UINT port,UINT packet_number)502 static UINT   nx_smtp_response_packet_send(NX_TCP_SOCKET *server_socket, UINT port, UINT packet_number)
503 {
504 UINT        status;
505 NX_PACKET   *response_packet;
506 
507     /* Allocate a response packet.  */
508     status =  nx_packet_allocate(&server_packet_pool, &response_packet, NX_TCP_PACKET, 200);
509 
510     /* Check status.  */
511     if (status)
512     {
513         error_counter++;
514         return status;
515     }
516 
517     memset(response_packet -> nx_packet_prepend_ptr, 0, (response_packet -> nx_packet_data_end - response_packet -> nx_packet_prepend_ptr));
518 
519     /* Write the SMTP response messages into the packet payload!  */
520     memcpy(response_packet -> nx_packet_prepend_ptr,
521            smtp_test[packet_number].smtp_test_pkt_data,
522            smtp_test[packet_number].smtp_test_pkt_size);
523 
524     /* Adjust the write pointer.  */
525     response_packet -> nx_packet_length =  smtp_test[packet_number].smtp_test_pkt_size;
526     response_packet -> nx_packet_append_ptr =  response_packet -> nx_packet_prepend_ptr + response_packet -> nx_packet_length;
527 
528     /* Send the TCP packet with the correct port.  */
529     status =  nx_tcp_socket_send(server_socket, response_packet, 100);
530 
531     /* Check the status.  */
532     if (status)
533     {
534         error_counter++;
535         nx_packet_release(response_packet);
536     }
537 
538     return status;
539 }
540 
smtp_test_initialize()541 static void     smtp_test_initialize()
542 {
543 
544     smtp_test[0].smtp_test_pkt_data = &response_220_greetings_pkt[0];
545     smtp_test[0].smtp_test_pkt_size = response_220_greetings_size;
546     smtp_test[1].smtp_test_pkt_data = &response_250_ehlo_pkt[0];
547     smtp_test[1].smtp_test_pkt_size = response_250_ehlo_size;
548     smtp_test[2].smtp_test_pkt_data = &response_334_pkt[0];
549     smtp_test[2].smtp_test_pkt_size = response_334_size;
550     smtp_test[3].smtp_test_pkt_data = &response_235_auth_passed_pkt[0];
551     smtp_test[3].smtp_test_pkt_size = response_235_auth_passed_size;
552 
553     smtp_test[4].smtp_test_pkt_data = &response_250_sender_ok_pkt[0];
554     smtp_test[4].smtp_test_pkt_size = response_250_sender_ok_size;
555     smtp_test[5].smtp_test_pkt_data = &response_250_recipient_ok_pkt[0];
556     smtp_test[5].smtp_test_pkt_size = response_250_recipient_ok_size;
557     smtp_test[6].smtp_test_pkt_data = &response_354_enter_mail_pkt[0];
558     smtp_test[6].smtp_test_pkt_size = response_354_enter_mail_size;
559 
560     smtp_test[7].smtp_test_pkt_data = &response_250_message_saved_pkt[0];
561     smtp_test[7].smtp_test_pkt_size = response_250_message_saved_size;
562 
563     smtp_test[8].smtp_test_pkt_data = &response_221_bye_pkt[0];
564     smtp_test[8].smtp_test_pkt_size = response_221_bye_size;
565 }
566 #else
567 
568 #ifdef CTEST
test_application_define(void * first_unused_memory)569 VOID test_application_define(void *first_unused_memory)
570 #else
571 void    netx_smtp_basic_function_test_application_define(void *first_unused_memory)
572 #endif
573 {
574 
575     /* Print out test information banner.  */
576     printf("NetX Test:   SMTP Basic Function Test..................................N/A\n");
577 
578     test_control_return(3);
579 }
580 #endif