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