/[H8]/trunk/PIC/TCP-IP stack/udp.c
ViewVC logotype

Annotation of /trunk/PIC/TCP-IP stack/udp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 54 - (hide annotations) (download)
Fri Apr 27 08:42:17 2007 UTC (17 years, 2 months ago) by hedin
File MIME type: text/plain
File size: 18322 byte(s)
Added basic project
1 hedin 54 /*********************************************************************
2     *
3     * UDP Module for Microchip TCP/IP Stack
4     *
5     *********************************************************************
6     * FileName: UDP.c
7     * Dependencies: StackTsk.h
8     * MAC.h
9     * Processor: PIC18
10     * Complier: MCC18 v1.00.50 or higher
11     * HITECH PICC-18 V8.10PL1 or higher
12     * Company: Microchip Technology, Inc.
13     *
14     * Software License Agreement
15     *
16     * The software supplied herewith by Microchip Technology Incorporated
17     * (the “Company”) for its PICmicro® Microcontroller is intended and
18     * supplied to you, the Company’s customer, for use solely and
19     * exclusively on Microchip PICmicro Microcontroller products. The
20     * software is owned by the Company and/or its supplier, and is
21     * protected under applicable copyright laws. All rights are reserved.
22     * Any use in violation of the foregoing restrictions may subject the
23     * user to criminal sanctions under applicable laws, as well as to
24     * civil liability for the breach of the terms and conditions of this
25     * license.
26     *
27     * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
28     * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
29     * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
30     * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
31     * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
32     * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
33     *
34     *
35     * HiTech PICC18 Compiler Options excluding device selection:
36     * -FAKELOCAL -G -O -Zg -E -C
37     *
38     * Author Date Comment
39     *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
40     * Nilesh Rajbharti 3/19/01 Original (Rev 1.0)
41     * Nilesh Rajbharti 2/26/03 Fixed UDPGet and UDPProcess bugs
42     * as discovered and fixed by John Owen
43     * of Powerwave.
44     * 1. UDPGet would return FALSE on last good byte
45     * 2. UDPProcess was incorrectly calculating length.
46     * Nilesh Rajbharti 5/19/03 Added bFirstRead flag similar to TCP
47     * to detect very first UDPGet and
48     * reset MAC Rx pointer to begining of
49     * UDP data area. This would ensure that
50     * if UDP socket has pending Rx data and
51     * another module resets MAC Rx pointer,
52     * next UDP socket Get would get correct
53     * data.
54     * Robert Sloan (RSS) 5/29/03 Improved FindMatchingSocket()
55     ********************************************************************/
56    
57     #define THIS_IS_UDP_MODULE
58    
59     #include <string.h>
60    
61     #include "stacktsk.h"
62     #include "helpers.h"
63     #include "mac.h"
64     #include "ip.h"
65     #include "udp.h"
66    
67     #if !defined(STACK_USE_UDP)
68     #error UDP module is not enabled.
69     #error If you do not want UDP module, remove this file from your
70     #error project to reduce your code size.
71     #error If you do want UDP module, make sure that STACK_USE_UDP
72     #error is defined in StackTsk.h file.
73     #endif
74    
75     UDP_SOCKET_INFO UDPSocketInfo[MAX_UDP_SOCKETS];
76     UDP_SOCKET activeUDPSocket;
77    
78     static UDP_SOCKET FindMatchingSocket(UDP_HEADER *h, NODE_INFO *remoteNode);
79    
80    
81     /*********************************************************************
82     * Function: void UDPInit(void)
83     *
84     * PreCondition: None
85     *
86     * Input: None
87     *
88     * Output: None
89     *
90     * Side Effects: None
91     *
92     * Overview: Initializes internal variables.
93     *
94     * Note:
95     ********************************************************************/
96     void UDPInit(void)
97     {
98     UDP_SOCKET s;
99    
100     for ( s = 0; s < MAX_UDP_SOCKETS; s++ )
101     {
102     UDPSocketInfo[s].localPort = INVALID_UDP_PORT;
103     UDPSocketInfo[s].Flags.bFirstRead = FALSE;
104     }
105     }
106    
107     /*********************************************************************
108     * Function: UDP_SOCKET UDPOpen(UDP_PORT localPort,
109     * NODE_INFO *remoteNode,
110     * UDP_PORT remotePort)
111     *
112     * PreCondition: UDPInit() is already called
113     *
114     * Input: remoteNode - Remote Node info such as MAC and IP
115     * address
116     * If NULL, broadcast node address is set.
117     * remotePort - Remote Port to which to talk to
118     * If INVALID_UDP_SOCKET, localPort is
119     * opened for Listen.
120     * localPort - A valid port number.
121     *
122     * Output: A valid UDP socket that is to be used for
123     * subsequent UDP communications.
124     *
125     * Side Effects: None
126     *
127     * Overview: A UDP packet header is assembled and loaded into
128     * UDP transmit buffer.
129     *
130     * Note: This call must always have valid localPort
131     * value.
132     ********************************************************************/
133     UDP_SOCKET UDPOpen(UDP_PORT localPort,
134     NODE_INFO *remoteNode,
135     UDP_PORT remotePort)
136     {
137     UDP_SOCKET s;
138     UDP_SOCKET_INFO *p;
139    
140    
141     p = UDPSocketInfo;
142     for ( s = 0; s < MAX_UDP_SOCKETS; s++ )
143     {
144     if ( p->localPort == INVALID_UDP_PORT )
145     {
146     p->localPort = localPort;
147    
148     /*
149     * If remoteNode is supplied, remember it.
150     */
151     if ( remoteNode )
152     {
153     memcpy((void*)&p->remoteNode,
154     (const void*)remoteNode,
155     sizeof(p->remoteNode));
156     }
157     /* else Set broadcast address - TO BE DONE */
158    
159    
160     p->remotePort = remotePort;
161     p->TxCount = 0;
162     p->RxCount = 0;
163    
164     /*
165     * Mark this socket as active.
166     * Once an active socket is set, subsequent operation can be
167     * done without explicitely supply socket identifier.
168     */
169     activeUDPSocket = s;
170     return s;
171     }
172     p++;
173     }
174    
175     return (UDP_SOCKET)INVALID_UDP_SOCKET;
176     }
177    
178    
179    
180    
181     /*********************************************************************
182     * Function: void UDPClose(UDP_SOCKET s)
183     *
184     * PreCondition: UDPOpen() is already called
185     *
186     * Input: s - Socket that is to be closed.
187     *
188     * Output: None
189     *
190     * Side Effects: None
191     *
192     * Overview: Given socket is marked as available for future
193     * new communcations.
194     *
195     * Note: This function does not affect previous
196     * active UDP socket designation.
197     ********************************************************************/
198     void UDPClose(UDP_SOCKET s)
199     {
200     UDPSocketInfo[s].localPort = INVALID_UDP_PORT;
201     }
202    
203    
204     /*********************************************************************
205     * Function: BOOL UDPPut(BYTE v)
206     *
207     * PreCondition: UDPIsPutReady() == TRUE with desired UDP socket
208     * that is to be loaded.
209     *
210     * Input: v - Data byte to loaded into transmit buffer
211     *
212     * Output: TRUE if transmit buffer is still ready to accept
213     * more data bytes
214     *
215     * FALSE if transmit buffer can no longer accept
216     * any more data byte.
217     *
218     * Side Effects: None
219     *
220     * Overview: Given data byte is put into UDP transmit buffer
221     * and active UDP socket buffer length is incremented
222     * by one.
223     * If buffer has become full, FALSE is returned.
224     * Or else TRUE is returned.
225     *
226     * Note: This function loads data into an active UDP socket
227     * as determined by previous call to UDPIsPutReady()
228     ********************************************************************/
229     BOOL UDPPut(BYTE v)
230     {
231     UDP_SOCKET_INFO *p;
232     WORD temp;
233    
234     p = &UDPSocketInfo[activeUDPSocket];
235    
236     if ( p->TxCount == 0 )
237     {
238     /*
239     * This is the very first byte that is loaded in UDP buffer.
240     * Remember what transmit buffer we are loading, and
241     * start loading this and next bytes in data area of UDP
242     * packet.
243     */
244     p->TxBuffer = MACGetTxBuffer();
245    
246     IPSetTxBuffer(p->TxBuffer, sizeof(UDP_HEADER));
247    
248     p->TxOffset = 0;
249     }
250    
251     /*
252     * Load it.
253     */
254     MACPut(v);
255    
256     if ( p->TxOffset++ >= p->TxCount )
257     p->TxCount++;
258    
259     #if 0
260     /*
261     * Keep track of number of bytes loaded.
262     * If total bytes fill up buffer, transmit it.
263     */
264     p->TxCount++;
265     #endif
266    
267     #define SIZEOF_MAC_HEADER (14)
268    
269     /*
270     * Depending on what communication media is used, allowable UDP
271     * data length will vary.
272     */
273     #if !defined(STACK_USE_SLIP)
274     #define MAX_UDP_DATA (MAC_TX_BUFFER_SIZE - SIZEOF_MAC_HEADER - sizeof(IP_HEADER) - sizeof(UDP_HEADER))
275     #else
276     #define MAX_UDP_DATA (MAC_TX_BUFFER_SIZE - sizeof(IP_HEADER) - sizeof(UDP_HEADER) )
277     #endif
278    
279     temp = p->TxCount;
280     if ( temp >= MAX_UDP_DATA )
281     {
282     UDPFlush();
283     }
284     #undef MAX_UDP_DATA
285    
286     return TRUE;
287     }
288    
289    
290     /*********************************************************************
291     * Function: BOOL UDPFlush(void)
292     *
293     * PreCondition: UDPPut() is already called and desired UDP socket
294     * is set as an active socket by calling
295     * UDPIsPutReady().
296     *
297     * Input: None
298     *
299     * Output: All and any data associated with active UDP socket
300     * buffer is marked as ready for transmission.
301     *
302     * Side Effects: None
303     *
304     * Overview: None
305     *
306     * Note: This function transmit all data from
307     * an active UDP socket.
308     ********************************************************************/
309     void UDPFlush(void)
310     {
311     UDP_HEADER h;
312     UDP_SOCKET_INFO *p;
313    
314     /*
315     * When using SLIP (USART), packet transmission takes some time
316     * and hence before sending another packet, we must make sure
317     * that, last packet is transmitted.
318     * When using ethernet controller, transmission occurs very fast
319     * and by the time next packet is transmitted, previous is
320     * transmitted and we do not need to check for last packet.
321     */
322     //while( !IPIsTxReady() );
323    
324     p = &UDPSocketInfo[activeUDPSocket];
325    
326     h.SourcePort = swaps(p->localPort);
327     h.DestinationPort = swaps(p->remotePort);
328     h.Length = (WORD)((WORD)p->TxCount + (WORD)sizeof(UDP_HEADER));
329     // Do not swap h.Length yet. It is needed in IPPutHeader.
330     h.Checksum = 0x00;
331    
332     IPSetTxBuffer(p->TxBuffer, 0);
333    
334     /*
335     * Load IP header.
336     */
337     IPPutHeader( &p->remoteNode,
338     IP_PROT_UDP,
339     h.Length );
340    
341    
342     // Now swap h.Length.
343     h.Length = swaps(h.Length);
344    
345     /*
346     * Now load UDP header.
347     */
348     IPPutArray((BYTE*)&h, sizeof(h));
349    
350     /*
351     * Update checksum.
352     * TO BE IMPLEMENTED
353     */
354    
355     MACFlush();
356    
357     p->TxBuffer = INVALID_BUFFER;
358     p->TxCount = 0;
359    
360     }
361    
362    
363    
364     /*********************************************************************
365     * Function: BOOL UDPIsGetReady(UDP_SOCKET s)
366     *
367     * PreCondition: UDPInit() is already called.
368     *
369     * Input: A valid UDP socket that is already "Listen"ed on
370     * or opened.
371     *
372     * Output: TRUE if given port contains any data.
373     * FALSE if given port does not contain any data.
374     *
375     * Side Effects: Given socket is set as an active UDP Socket.
376     *
377     * Overview: None
378     *
379     * Note: This function automatically sets supplied socket
380     * as an active socket. Caller need not call
381     * explicit function UDPSetActiveSocket(). All
382     * subsequent calls will us this socket as an
383     * active socket.
384     ********************************************************************/
385     BOOL UDPIsGetReady(UDP_SOCKET s)
386     {
387     activeUDPSocket = s;
388     return ( UDPSocketInfo[activeUDPSocket].RxCount > 0 );
389     }
390    
391     /*********************************************************************
392     * Function: BOOL UDPGet(BYTE *v)
393     *
394     * PreCondition: UDPInit() is already called AND
395     * UDPIsGetReady(s) == TRUE
396     *
397     * Input: v - Buffer to receive UDP data byte
398     *
399     * Output: TRUE if a data byte was read
400     * FALSE if no data byte was read or available
401     *
402     * Side Effects: None
403     *
404     * Overview: None
405     *
406     * Note: This function fetches data from an active UDP
407     * socket as set by UDPIsGetReady() call.
408     ********************************************************************/
409     BOOL UDPGet(BYTE *v)
410     {
411     /*
412     * CALLER MUST MAKE SURE THAT THERE IS ENOUGH DATA BYTE IN BUFFER
413     * BEFORE CALLING THIS FUNCTION.
414     * USE UDPIsGetReady() TO CONFIRM.
415     */
416     if ( UDPSocketInfo[activeUDPSocket].RxCount == 0 )
417     return FALSE;
418    
419     // If if this very first read to packet, set MAC Rx Pointer to
420     // beginig of UDP data area.
421     if ( UDPSocketInfo[activeUDPSocket].Flags.bFirstRead )
422     {
423     UDPSocketInfo[activeUDPSocket].Flags.bFirstRead = FALSE;
424     UDPSetRxBuffer(0);
425     }
426    
427     *v = MACGet();
428    
429     UDPSocketInfo[activeUDPSocket].RxCount--;
430    
431     if ( UDPSocketInfo[activeUDPSocket].RxCount == 0 )
432     {
433     MACDiscardRx();
434     }
435    
436     return TRUE;
437     }
438    
439    
440     /*********************************************************************
441     * Function: void UDPDiscard(void)
442     *
443     * PreCondition: UDPInit() is already called AND
444     * UDPIsGetReady() == TRUE with desired UDP socket.
445     *
446     * Input: None
447     *
448     * Output: None
449     *
450     * Side Effects: None
451     *
452     * Overview: None
453     *
454     * Note: This function discards an active UDP socket content.
455     ********************************************************************/
456     void UDPDiscard(void)
457     {
458     if ( UDPSocketInfo[activeUDPSocket].RxCount )
459     MACDiscardRx();
460    
461     UDPSocketInfo[activeUDPSocket].RxCount = 0;
462     }
463    
464    
465    
466     /*********************************************************************
467     * Function: BOOL UDPProcess(NODE_INFO* remoteNode,
468     * WORD len)
469     *
470     * PreCondition: UDPInit() is already called AND
471     * UDP segment is ready in MAC buffer
472     *
473     * Input: remoteNode - Remote node info
474     * len - Total length of UDP semgent.
475     *
476     * Output: TRUE if this function has completed its task
477     * FALSE otherwise
478     *
479     * Side Effects: None
480     *
481     * Overview: None
482     *
483     * Note: None
484     ********************************************************************/
485     BOOL UDPProcess(NODE_INFO *remoteNode, WORD len)
486     {
487     UDP_HEADER h;
488     UDP_SOCKET s;
489    
490     /*
491     * Retrieve UDP header.
492     */
493     MACGetArray((BYTE*)&h, sizeof(h));
494    
495     h.SourcePort = swaps(h.SourcePort);
496     h.DestinationPort = swaps(h.DestinationPort);
497     h.Length = swaps(h.Length) - sizeof(UDP_HEADER);;
498     h.Checksum = swaps(h.Checksum);
499    
500     s = FindMatchingSocket(&h, remoteNode);
501     if ( s == INVALID_UDP_SOCKET )
502     {
503     /*
504     * If there is no matching socket, There is no one to handle
505     * this data. Discard it.
506     */
507     MACDiscardRx();
508     }
509     else
510     {
511     UDPSocketInfo[s].RxCount = h.Length;
512     UDPSocketInfo[s].Flags.bFirstRead = TRUE;
513     }
514    
515    
516     return TRUE;
517     }
518    
519    
520     /*********************************************************************
521     * Function: UDP_SOCKET FindMatchingSocket(UDP_HEADER *h,
522     * NODE_INFO *remoteNode)
523     *
524     * PreCondition: UDP Segment header has been retrieved from buffer
525     * The IP header has also been retrieved
526     *
527     * Input: remoteNode - Remote node info from IP header
528     * h - header of UDP semgent.
529     *
530     * Output: matching UDP socket or INVALID_UDP_SOCKET
531     *
532     * Side Effects: None
533     *
534     * Overview: None
535     *
536     * Note: None
537     ********************************************************************/
538     #define BROADCAST_ADDRESS (0xffffffffL)
539     static UDP_SOCKET FindMatchingSocket(UDP_HEADER *h, NODE_INFO *remoteNode)
540     {
541     UDP_SOCKET s;
542     UDP_SOCKET partialMatch;
543     UDP_SOCKET_INFO *p;
544    
545     partialMatch = INVALID_UDP_SOCKET;
546    
547     p = UDPSocketInfo;
548     for ( s = 0; s < MAX_UDP_SOCKETS; s++ )
549     {
550     /*
551     * This packet is said to be matching with current socket
552     * 1. If its destination port matches with our local port.
553     * 2. This socket does not have any data pending.
554     * 3. Packet source IP address matches with socket remote IP address.
555     * OR this socket had transmitted packet with destination address
556     * as broadcast.
557     */
558     if ( p->localPort == h->DestinationPort )
559     {
560     if ( (p->remotePort == h->SourcePort) && (p->RxCount == 0L) )
561     {
562     if ( (p->remoteNode.IPAddr.Val == remoteNode->IPAddr.Val) ||
563     (p->remoteNode.IPAddr.Val == BROADCAST_ADDRESS) )
564     {
565     return s;
566     }
567     }
568    
569     partialMatch = s;
570     }
571     p++;
572     }
573    
574     if ( partialMatch != INVALID_UDP_SOCKET )
575     {
576     p = &UDPSocketInfo[partialMatch];
577    
578     memcpy((void*)&p->remoteNode,
579     (const void*)remoteNode, sizeof(p->remoteNode) );
580    
581     p->remotePort = h->SourcePort;
582     }
583     return partialMatch;
584     }
585    
586    
587    

  ViewVC Help
Powered by ViewVC 1.1.20