1 /* This is a small demo of the high-performance NetX TCP/IP stack using PPP.
2 This demo concentrates on UDP packet sending and receiving using PPP on a
3 simulated serial link. */
4
5 #include "tx_api.h"
6 #include "nx_api.h"
7
8 #ifndef NX_DISABLE_IPV4
9 #include "nx_ppp.h"
10
11
12 /* Define demo stack size. */
13
14 #define DEMO_STACK_SIZE 2048
15 #define DEMO_DATA "ABCDEFGHIJKLMNOPQRSTUVWXYZ "
16
17
18 /* Define the ThreadX and NetX object control blocks... */
19
20 TX_THREAD thread_0;
21 TX_THREAD thread_1;
22
23 NX_PACKET_POOL pool_0;
24
25 NX_IP ip_0;
26 NX_IP ip_1;
27
28 NX_PPP ppp_0;
29 NX_PPP ppp_1;
30
31 NX_UDP_SOCKET socket_0;
32 NX_UDP_SOCKET socket_1;
33
34
35 /* Define the counters used in the demo application... */
36
37 ULONG thread_0_counter;
38 ULONG thread_1_counter;
39 ULONG ppp_0_link_up_counter;
40 ULONG ppp_0_link_down_counter;
41 ULONG ppp_1_link_up_counter;
42 ULONG ppp_1_link_down_counter;
43 ULONG error_counter;
44
45
46 /* Define thread prototypes. */
47
48 void thread_0_entry(ULONG thread_input);
49 void thread_1_entry(ULONG thread_input);
50 void ppp_0_serial_byte_output(UCHAR byte);
51 void ppp_1_serial_byte_output(UCHAR byte);
52 void invalid_packet_handler(NX_PACKET *packet_ptr);
53 void link_up_callback(NX_PPP *ppp_ptr);
54 void link_down_callback(NX_PPP *ppp_ptr);
55 UINT generate_login(CHAR *name, CHAR *password);
56 UINT verify_login(CHAR *name, CHAR *password);
57
58
59 /* Define main entry point. */
60
main()61 int main()
62 {
63
64 /* Enter the ThreadX kernel. */
65 tx_kernel_enter();
66 }
67
68
69 /* Define what the initial system looks like. */
70
tx_application_define(void * first_unused_memory)71 void tx_application_define(void *first_unused_memory)
72 {
73
74 CHAR *pointer;
75 UINT status;
76
77
78 /* Setup the working pointer. */
79 pointer = (CHAR *) first_unused_memory;
80
81 /* Create the main thread. */
82 tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
83 pointer, DEMO_STACK_SIZE,
84 5, 5, TX_NO_TIME_SLICE, TX_AUTO_START);
85 pointer = pointer + DEMO_STACK_SIZE;
86
87 /* . */
88 tx_thread_create(&thread_1, "thread 1", thread_1_entry, 0,
89 pointer, DEMO_STACK_SIZE,
90 5, 5, TX_NO_TIME_SLICE, TX_AUTO_START);
91 pointer = pointer + DEMO_STACK_SIZE;
92
93 /* Initialize the NetX system. */
94 nx_system_initialize();
95
96 /* Create a packet pool. */
97 status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 128, pointer, 2048);
98 pointer = pointer + 2048;
99
100 /* Check for pool creation error. */
101 if (status)
102 error_counter++;
103
104 /* Create the first PPP instance. */
105 status = nx_ppp_create(&ppp_0, "NetX PPP Instance 0", &ip_0, pointer, 2048, 1, &pool_0, invalid_packet_handler, ppp_0_serial_byte_output);
106 pointer = pointer + 2048;
107
108 /* Check for PPP create error. */
109 if (status)
110 error_counter++;
111
112 /* Define IP address. This PPP instance is effectively the server since it has both IP addresses. */
113 status = nx_ppp_ip_address_assign(&ppp_0, IP_ADDRESS(1, 2, 3, 4), IP_ADDRESS(1, 2, 3, 5));
114
115 /* Check for PPP IP address assign error. */
116 if (status)
117 error_counter++;
118
119 /* Register the link up/down callbacks. */
120 status = nx_ppp_link_up_notify(&ppp_0, link_up_callback);
121 status += nx_ppp_link_down_notify(&ppp_0, link_down_callback);
122
123 /* Check for PPP link up/down callback registration error(s). */
124 if (status)
125 error_counter++;
126
127 /* Setup PAP, this PPP instance is effectively the server since it will verify the name and password. */
128 status = nx_ppp_pap_enable(&ppp_0, NX_NULL, verify_login);
129
130 /* Check for PPP PAP enable error. */
131 if (status)
132 error_counter++;
133
134 /* Create an IP instance. */
135 status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(0, 0, 0, 0), 0xFFFFF000UL, &pool_0, nx_ppp_driver,
136 pointer, 2048, 1);
137 pointer = pointer + 2048;
138
139 /* Create the next PPP instance. */
140 status = nx_ppp_create(&ppp_1, "NetX PPP Instance 1", &ip_1, pointer, 2048, 1, &pool_0, invalid_packet_handler, ppp_1_serial_byte_output);
141 pointer = pointer + 2048;
142
143 /* Check for PPP create error. */
144 if (status)
145 error_counter++;
146
147 /* Define IP address. This PPP instance is effectively the client since it doesn't have any IP addresses. */
148 status = nx_ppp_ip_address_assign(&ppp_1, IP_ADDRESS(0, 0, 0, 0), IP_ADDRESS(0, 0, 0, 0));
149
150 /* Check for PPP IP address assign error. */
151 if (status)
152 error_counter++;
153
154 /* Register the link up/down callbacks. */
155 status = nx_ppp_link_up_notify(&ppp_1, link_up_callback);
156 status += nx_ppp_link_down_notify(&ppp_1, link_down_callback);
157
158 /* Check for PPP link up/down callback registration error(s). */
159 if (status)
160 error_counter++;
161
162 /* Setup PAP, this PPP instance is effectively the since it generates the name and password for the peer. */
163 status = nx_ppp_pap_enable(&ppp_1, generate_login, NX_NULL);
164
165 /* Check for PPP PAP enable error. */
166 if (status)
167 error_counter++;
168
169 /* Create another IP instance. */
170 status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(0, 0, 0, 0), 0xFFFFF000UL, &pool_0, nx_ppp_driver,
171 pointer, 2048, 1);
172 pointer = pointer + 2048;
173
174 /* Enable UDP traffic. */
175 status = nx_udp_enable(&ip_0);
176 status += nx_udp_enable(&ip_1);
177
178 /* Check for UDP enable errors. */
179 if (status)
180 error_counter++;
181 }
182
183
184
185 /* Define the test threads. */
186
thread_0_entry(ULONG thread_input)187 void thread_0_entry(ULONG thread_input)
188 {
189
190 UINT status;
191 ULONG ip_status;
192 NX_PACKET *my_packet;
193
194 NX_PARAMETER_NOT_USED(thread_input);
195
196 do
197 {
198
199 /* Wait for the link to come up. */
200 status = nx_ip_status_check(&ip_0, NX_IP_LINK_ENABLED, &ip_status, 3 * NX_IP_PERIODIC_RATE);
201 } while (status);
202
203 /* Create a UDP socket. */
204 status = nx_udp_socket_create(&ip_0, &socket_0, "Socket 0", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
205
206 /* Check status. */
207 if (status)
208 {
209 error_counter++;
210 return;
211 }
212
213 /* Bind the UDP socket to the IP port. */
214 status = nx_udp_socket_bind(&socket_0, 0x88, TX_WAIT_FOREVER);
215
216 /* Check status. */
217 if (status)
218 {
219 error_counter++;
220 return;
221 }
222
223 /* Disable checksum logic for this socket. */
224 nx_udp_socket_checksum_disable(&socket_0);
225
226 /* Let receiver thread run. */
227 tx_thread_relinquish();
228
229 while(1)
230 {
231
232 /* Allocate a packet. */
233 status = nx_packet_allocate(&pool_0, &my_packet, NX_UDP_PACKET, TX_WAIT_FOREVER);
234
235 /* Check status. */
236 if (status != NX_SUCCESS)
237 break;
238
239 /* Write ABCs into the packet payload! */
240 nx_packet_data_append(my_packet, DEMO_DATA, sizeof(DEMO_DATA), &pool_0, TX_WAIT_FOREVER);
241
242 /* Send the UDP packet. */
243 status = nx_udp_socket_send(&socket_0, my_packet, IP_ADDRESS(1, 2, 3, 5), 0x89);
244
245 /* Check status. */
246 if (status != NX_SUCCESS)
247 {
248 error_counter++;
249 break;
250 }
251
252 /* Increment thread 0's counter. */
253 thread_0_counter++;
254
255 /* Relinquish to thread 1. */
256 tx_thread_relinquish();
257 }
258 }
259
260
thread_1_entry(ULONG thread_input)261 void thread_1_entry(ULONG thread_input)
262 {
263
264 UINT status;
265 ULONG ip_status;
266 NX_PACKET *my_packet;
267
268 NX_PARAMETER_NOT_USED(thread_input);
269
270 do
271 {
272
273 /* Wait for the link to come up. */
274 status = nx_ip_status_check(&ip_1, NX_IP_LINK_ENABLED, &ip_status, 3 * NX_IP_PERIODIC_RATE);
275 } while (status);
276
277 /* Create a UDP socket. */
278 status = nx_udp_socket_create(&ip_1, &socket_1, "Socket 1", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
279
280 /* Check status. */
281 if (status)
282 {
283 error_counter++;
284 return;
285 }
286
287 /* Bind the UDP socket to the IP port. */
288 status = nx_udp_socket_bind(&socket_1, 0x89, TX_WAIT_FOREVER);
289
290 /* Check status. */
291 if (status)
292 {
293 error_counter++;
294 return;
295 }
296
297 while(1)
298 {
299
300
301 /* Receive a UDP packet. */
302 status = nx_udp_socket_receive(&socket_1, &my_packet, TX_WAIT_FOREVER);
303
304 /* Check status. */
305 if (status != NX_SUCCESS)
306 break;
307
308 /* Release the packet. */
309 status = nx_packet_release(my_packet);
310
311 /* Check status. */
312 if (status != NX_SUCCESS)
313 break;
314
315 /* Increment thread 1's counter. */
316 thread_1_counter++;
317 }
318 }
319
320 /* Define serial output routines. Normally these routines would
321 map to physical UART routines and the nx_ppp_byte_receive call
322 would be made from a UART receive interrupt. */
323
ppp_0_serial_byte_output(UCHAR byte)324 void ppp_0_serial_byte_output(UCHAR byte)
325 {
326
327 /* Just feed the PPP 1 input routine. */
328 nx_ppp_byte_receive(&ppp_1, byte);
329 }
330
ppp_1_serial_byte_output(UCHAR byte)331 void ppp_1_serial_byte_output(UCHAR byte)
332 {
333
334 /* Just feed the PPP 0 input routine. */
335 nx_ppp_byte_receive(&ppp_0, byte);
336 }
337
338
invalid_packet_handler(NX_PACKET * packet_ptr)339 void invalid_packet_handler(NX_PACKET *packet_ptr)
340 {
341 /* Print out the non-PPP byte. In Windows, the string "CLIENT" will
342 be sent before Windows PPP starts. Once CLIENT is received, we need
343 to send "CLIENTSERVER" to establish communication. It's also possible
344 to receive modem commands here that might need some response to
345 continue. */
346 nx_packet_release(packet_ptr);
347 }
348
349
link_up_callback(NX_PPP * ppp_ptr)350 void link_up_callback(NX_PPP *ppp_ptr)
351 {
352
353 /* Just increment the link up counter. */
354 if (ppp_ptr == &ppp_0)
355 ppp_0_link_up_counter++;
356 else
357 ppp_1_link_up_counter++;
358 }
359
360
link_down_callback(NX_PPP * ppp_ptr)361 void link_down_callback(NX_PPP *ppp_ptr)
362 {
363
364 /* Just increment the link down counter. */
365 if (ppp_ptr == &ppp_0)
366 ppp_0_link_down_counter++;
367 else
368 ppp_1_link_down_counter++;
369
370 /* Restart the PPP instance. */
371 nx_ppp_restart(ppp_ptr);
372 }
373
374
generate_login(CHAR * name,CHAR * password)375 UINT generate_login(CHAR *name, CHAR *password)
376 {
377
378 /* Make a name and password, called "myname" and "mypassword". */
379 name[0] = 'm';
380 name[1] = 'y';
381 name[2] = 'n';
382 name[3] = 'a';
383 name[4] = 'm';
384 name[5] = 'e';
385 name[6] = (CHAR) 0;
386
387 password[0] = 'm';
388 password[1] = 'y';
389 password[2] = 'p';
390 password[3] = 'a';
391 password[4] = 's';
392 password[5] = 's';
393 password[6] = 'w';
394 password[7] = 'o';
395 password[8] = 'r';
396 password[9] = 'd';
397 password[10] = (CHAR) 0;
398
399 return(NX_SUCCESS);
400 }
401
402
verify_login(CHAR * name,CHAR * password)403 UINT verify_login(CHAR *name, CHAR *password)
404 {
405
406 if ((name[0] == 'm') &&
407 (name[1] == 'y') &&
408 (name[2] == 'n') &&
409 (name[3] == 'a') &&
410 (name[4] == 'm') &&
411 (name[5] == 'e') &&
412 (name[6] == (CHAR) 0) &&
413 (password[0] == 'm') &&
414 (password[1] == 'y') &&
415 (password[2] == 'p') &&
416 (password[3] == 'a') &&
417 (password[4] == 's') &&
418 (password[5] == 's') &&
419 (password[6] == 'w') &&
420 (password[7] == 'o') &&
421 (password[8] == 'r') &&
422 (password[9] == 'd') &&
423 (password[10] == (CHAR) 0))
424 return(NX_SUCCESS);
425 else
426 return(NX_PPP_ERROR);
427 }
428 #endif /* NX_DISABLE_IPV4 */
429