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