Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages   Examples  

/opentcp/udp.c

Go to the documentation of this file.
00001 /*
00002  *Copyright (c) 2000-2002 Viola Systems Ltd.
00003  *All rights reserved.
00004  *
00005  *Redistribution and use in source and binary forms, with or without 
00006  *modification, are permitted provided that the following conditions 
00007  *are met:
00008  *
00009  *1. Redistributions of source code must retain the above copyright 
00010  *notice, this list of conditions and the following disclaimer.
00011  *
00012  *2. Redistributions in binary form must reproduce the above copyright 
00013  *notice, this list of conditions and the following disclaimer in the 
00014  *documentation and/or other materials provided with the distribution.
00015  *
00016  *3. The end-user documentation included with the redistribution, if 
00017  *any, must include the following acknowledgment:
00018  *      "This product includes software developed by Viola 
00019  *      Systems (http://www.violasystems.com/)."
00020  *
00021  *Alternately, this acknowledgment may appear in the software itself, 
00022  *if and wherever such third-party acknowledgments normally appear.
00023  *
00024  *4. The names "OpenTCP" and "Viola Systems" must not be used to 
00025  *endorse or promote products derived from this software without prior 
00026  *written permission. For written permission, please contact 
00027  *opentcp@opentcp.org.
00028  *
00029  *5. Products derived from this software may not be called "OpenTCP", 
00030  *nor may "OpenTCP" appear in their name, without prior written 
00031  *permission of the Viola Systems Ltd.
00032  *
00033  *THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 
00034  *WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
00035  *MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
00036  *IN NO EVENT SHALL VIOLA SYSTEMS LTD. OR ITS CONTRIBUTORS BE LIABLE 
00037  *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00038  *CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
00039  *SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
00040  *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00041  *WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00042  *OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
00043  *EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00044  *====================================================================
00045  *
00046  *OpenTCP is the unified open source TCP/IP stack available on a series 
00047  *of 8/16-bit microcontrollers, please see <http://www.opentcp.org>.
00048  *
00049  *For more information on how to network-enable your devices, or how to 
00050  *obtain commercial technical support for OpenTCP, please see 
00051  *<http://www.violasystems.com/>.
00052  */
00053 
00077 #include <inet/debug.h>
00078 #include <inet/datatypes.h>
00079 #include <inet/ethernet.h>
00080 #include <inet/ip.h>
00081 #include <inet/tcp_ip.h>
00082 #include <inet/system.h>
00083 
00094 struct ucb udp_socket[NO_OF_UDPSOCKETS];
00095 
00101 struct udp_frame received_udp_packet;
00102 
00118 INT8 udp_init (void)
00119 {
00120         UINT8 i;
00121         struct ucb* soc;
00122         
00123         if( NO_OF_UDPSOCKETS < 0 )
00124                 return(-1);
00125         
00126         if( NO_OF_UDPSOCKETS == 0 )
00127                 return(0);
00128         
00129         UDP_DEBUGOUT("Initializing UDP");
00130         
00131         for(i=0; i < NO_OF_UDPSOCKETS; i++) {
00132                 soc = &udp_socket[i];                   /* Get Socket   */
00133                 
00134                 soc->state = UDP_STATE_FREE;
00135                 soc->tos = 0;
00136                 soc->locport = 0;
00137                 soc->opts = UDP_OPT_SEND_CS | UDP_OPT_CHECK_CS;  
00138                 soc->event_listener = 0;
00139                 
00140                 UDP_DEBUGOUT(".");
00141                 
00142         }
00143         
00144         UDP_DEBUGOUT("\n\rUDP Initialized\n\r");
00145         
00146         /* Return number of sockets initialized */
00147         
00148         return(i+1);
00149 
00150 }
00151 
00175 INT8 udp_getsocket (UINT8 tos, INT32 (*listener)(INT8, UINT8, UINT32, UINT16, UINT16, UINT16), UINT8 opts )
00176 {
00177         INT8 i;
00178         struct ucb* soc;
00179         
00180         if( NO_OF_UDPSOCKETS < 0 )
00181                 return(-1);
00182         
00183         if( NO_OF_UDPSOCKETS == 0 )
00184                 return(-1);
00185         
00186         
00187         if(listener == 0) {
00188                 UDP_DEBUGOUT("ERROR:Event listener function for UDP not specified\r\n");
00189                 return(-1);
00190         }
00191         
00192         UDP_DEBUGOUT("Searching for free UDP socket...\r\n");
00193         
00194         for(i=0; i < NO_OF_UDPSOCKETS; i++) {
00195                 soc = &udp_socket[i];                   /* Get Socket   */
00196         
00197                 if(soc->state == UDP_STATE_FREE) {
00198                         /* We found it  */
00199                         
00200                         UDP_DEBUGOUT("Free socket found\r\n");
00201                         
00202                         soc->state = UDP_STATE_CLOSED;
00203                         soc->tos = tos;
00204                         soc->locport = 0;
00205                         
00206                         soc->opts = 0;
00207                         
00208                         if(opts & UDP_OPT_SEND_CS)
00209                                 soc->opts |= UDP_OPT_SEND_CS;
00210                         if(opts & UDP_OPT_CHECK_CS)
00211                                 soc->opts |= UDP_OPT_CHECK_CS;
00212                         
00213                         soc->event_listener = listener;
00214 
00215                         /* Return handle        */
00216                         
00217                         return(i);
00218                 }
00219         
00220         }
00221         
00222         /* We are there so no socket found      */
00223         
00224         UDP_DEBUGOUT("No UDP socket found\r\n");
00225         return(-1);
00226 
00227 }
00228 
00229 
00244 INT8 udp_releasesocket (INT8 sochandle)
00245 {
00246         struct ucb* soc;
00247         
00248         if( NO_OF_UDPSOCKETS < 0 )
00249                 return(-1);
00250         
00251         if( NO_OF_UDPSOCKETS == 0 )
00252                 return(-1);
00253         
00254         if( sochandle > NO_OF_UDPSOCKETS ) {
00255                 UDP_DEBUGOUT("Socket handle non-valid\r\n");
00256                 return(-1);
00257         }
00258         
00259         if( sochandle < 0 ) {
00260                 UDP_DEBUGOUT("Socket handle non-valid\r\n");
00261                 return(-1);
00262         }
00263         
00264         soc = &udp_socket[sochandle];           /* Get referense        */
00265         
00266         soc->state = UDP_STATE_FREE;
00267         soc->tos = 0;
00268         soc->locport = 0;
00269         soc->opts = UDP_OPT_SEND_CS | UDP_OPT_CHECK_CS; 
00270         soc->event_listener = 0;
00271 
00272         return(sochandle);
00273 
00274 }
00275 
00276 
00291 INT8 udp_open (INT8 sochandle, UINT16 locport)
00292 {
00293         struct ucb* soc;
00294         
00295         if( NO_OF_UDPSOCKETS < 0 )
00296                 return(-1);
00297         
00298         if( NO_OF_UDPSOCKETS == 0 )
00299                 return(-1);
00300         
00301         if( sochandle > NO_OF_UDPSOCKETS ) {
00302                 UDP_DEBUGOUT("Socket handle non-valid\r\n");
00303                 return(-1);
00304         }
00305         
00306         if( sochandle < 0 ) {
00307                 UDP_DEBUGOUT("Socket handle non-valid\r\n");
00308                 return(-1);
00309         }
00310         
00311         if(locport == 0) {
00312                 locport=udp_getfreeport();
00313                 return(-1);
00314         }
00315         
00316         soc = &udp_socket[sochandle];           /* Get referense        */
00317 
00318         soc->state = UDP_STATE_OPENED;
00319         soc->locport = locport;
00320         
00321         return(sochandle);
00322 
00323 }
00324 
00325 
00326 
00340 INT8 udp_close (INT8 sochandle)
00341 {
00342         struct ucb* soc;
00343         
00344         if( NO_OF_UDPSOCKETS < 0 )
00345                 return(-1);
00346         
00347         if( NO_OF_UDPSOCKETS == 0 )
00348                 return(-1);
00349         
00350         if( sochandle > NO_OF_UDPSOCKETS ) {
00351                 UDP_DEBUGOUT("Socket handle non-valid\r\n");
00352                 return(-1);
00353         }
00354         
00355         if( sochandle < 0 ) {
00356                 UDP_DEBUGOUT("Socket handle non-valid\r\n");
00357                 return(-1);
00358         }
00359         
00360         soc = &udp_socket[sochandle];           /* Get referense        */
00361 
00362         soc->state = UDP_STATE_CLOSED;
00363         
00364         return(sochandle);
00365 
00366 }
00367 
00368 
00395 INT16 udp_send (INT8 sochandle, UINT32 remip, UINT16 remport, UINT8* buf, UINT16 blen, UINT16 dlen)
00396 {
00397         struct ucb* soc;
00398         UINT8* user_buf_start;
00399         UINT16 cs;
00400         UINT8 cs_cnt;
00401         INT16 i;
00402         
00403         if( NO_OF_UDPSOCKETS < 0 )
00404                 return(-1);
00405         
00406         if( NO_OF_UDPSOCKETS == 0 )
00407                 return(-1);
00408         
00409         if( sochandle > NO_OF_UDPSOCKETS ) {
00410                 UDP_DEBUGOUT("Socket handle non-valid\r\n");
00411                 return(-1);
00412         }
00413         
00414         if( sochandle < 0 ) {
00415                 UDP_DEBUGOUT("Socket handle non-valid\r\n");
00416                 return(-1);
00417         }
00418         
00419         if(remip == 0) {
00420                 UDP_DEBUGOUT("Remote IP 0 not allowed\r\n");
00421                 return(-1);
00422         }
00423         
00424         if(remport == 0) {
00425                 UDP_DEBUGOUT("Remote port 0 not allowed\r\n");
00426                 return(-1);
00427         }
00428         
00429         if( dlen > blen )
00430                 dlen = blen;
00431         
00432         if( (dlen + UDP_HLEN) > UDP_SEND_MTU)
00433                 dlen = UDP_SEND_MTU - UDP_HLEN;
00434         
00435         soc = &udp_socket[sochandle];           /* Get referense        */
00436 
00437         if(soc->state != UDP_STATE_OPENED ) {
00438                 UDP_DEBUGOUT("UDP Socket Closed\r\n");
00439                 return(-3);
00440         }
00441         
00442         if(soc->locport == 0) {
00443                 UDP_DEBUGOUT("ERROR:Socket local port is zero\r\n");
00444                 return(-1);
00445         }
00446 
00447         user_buf_start = buf;
00448         
00449         buf -= UDP_HLEN;
00450         
00451         /* Put header   */
00452         
00453         *buf++ = (UINT8)(soc->locport >> 8);
00454         *buf++ = (UINT8)soc->locport;
00455         *buf++ = (UINT8)(remport >> 8);
00456         *buf++ = (UINT8)remport;
00457         *buf++ = (UINT8)((dlen + UDP_HLEN) >> 8);
00458         *buf++ = (UINT8)(dlen + UDP_HLEN);
00459         *buf++ = 0;
00460         *buf = 0;
00461         
00462         buf = user_buf_start;
00463         buf -= UDP_HLEN;
00464         
00465         /* Calculate checksum if needed */
00466         
00467         cs = 0;
00468         
00469         if( soc->opts & UDP_OPT_SEND_CS) {
00470                 cs = 0;
00471                 cs_cnt = 0;
00472         
00473                 /* Do it firstly to IP pseudo header    */
00474         
00475                 cs = ip_checksum(cs, (UINT8)(localmachine.localip >> 24), cs_cnt++);    
00476                 cs = ip_checksum(cs, (UINT8)(localmachine.localip >> 16), cs_cnt++);
00477                 cs = ip_checksum(cs, (UINT8)(localmachine.localip >> 8), cs_cnt++);
00478                 cs = ip_checksum(cs, (UINT8)localmachine.localip, cs_cnt++);
00479         
00480                 cs = ip_checksum(cs, (UINT8)(remip >> 24), cs_cnt++);   
00481                 cs = ip_checksum(cs, (UINT8)(remip >> 16), cs_cnt++);
00482                 cs = ip_checksum(cs, (UINT8)(remip >> 8), cs_cnt++);
00483                 cs = ip_checksum(cs, (UINT8)remip, cs_cnt++);   
00484         
00485                 cs = ip_checksum(cs, 0, cs_cnt++);
00486         
00487                 cs = ip_checksum(cs, (UINT8)IP_UDP, cs_cnt++);
00488                 
00489                 cs = ip_checksum(cs, (UINT8)((dlen + UDP_HLEN) >> 8), cs_cnt++);
00490                 cs = ip_checksum(cs, (UINT8)(dlen + UDP_HLEN), cs_cnt++);       
00491         
00492                 /* Go to UDP header + data      */
00493         
00494                 buf = user_buf_start;
00495                 buf -= UDP_HLEN;
00496         
00497                 cs = ip_checksum_buf(cs, buf, dlen + UDP_HLEN);
00498                         
00499                 cs = ~ cs;
00500         
00501                 if(cs == 0)
00502                         cs = 0xFFFF;
00503                 
00504                 /* Save checksum in correct place       */
00505                 buf = user_buf_start;
00506                 buf -= UDP_HLEN;
00507                 buf += 6;
00508                 *buf++ = (UINT8)(cs >> 8);
00509                 *buf = (UINT8)cs;       
00510                 
00511                 buf = user_buf_start;
00512                 buf -= UDP_HLEN;
00513                         
00514         }
00515         
00516         /* Send it to IP        */
00517         
00518         UDP_DEBUGOUT("Sending UDP...\r\n");
00519         
00520         i = process_ip_out(remip, IP_UDP, soc->tos, 100, buf, dlen + UDP_HLEN);
00521         
00522         /* Errors?      */
00523         
00524         if( i < 0 )
00525                 return(i);
00526         
00527         UDP_DEBUGOUT("UDP packet sent\r\n");
00528         
00529         return(i - UDP_HLEN);
00530 
00531 
00532 }
00533 
00534 
00535 
00550 INT16 process_udp_in(struct ip_frame* frame, UINT16 len)
00551 {
00552         struct ucb* soc;
00553         UINT16 checksum;
00554         UINT16 i;
00555         INT8 sochandle;
00556                 
00557         /* Is this UDP? */
00558         
00559         UDP_DEBUGOUT("Processing UDP...\n\r");
00560         
00561         if( frame->protocol != IP_UDP ) {
00562                 UDP_DEBUGOUT("ERROR: The protocol is not UDP\n\r");
00563                 return(-1);
00564         }
00565         
00566         /* Start processing the message */
00567         
00568         NETWORK_RECEIVE_INITIALIZE(frame->buf_index);
00569 
00570         received_udp_packet.sport = ((UINT16)RECEIVE_NETWORK_B()) << 8;
00571         received_udp_packet.sport |= RECEIVE_NETWORK_B();
00572         
00573         received_udp_packet.dport = ((UINT16)RECEIVE_NETWORK_B()) << 8;
00574         received_udp_packet.dport |= RECEIVE_NETWORK_B();       
00575         
00576         received_udp_packet.tlen = ((UINT16)RECEIVE_NETWORK_B()) << 8;
00577         received_udp_packet.tlen |= RECEIVE_NETWORK_B();
00578         
00579         received_udp_packet.checksum = ((UINT16)RECEIVE_NETWORK_B()) << 8;
00580         received_udp_packet.checksum |= RECEIVE_NETWORK_B();
00581         
00582         if(received_udp_packet.tlen < UDP_HLEN ) {
00583                 UDP_DEBUGOUT("UDP frame too short\n\r");
00584                 return(-1);
00585         }
00586         
00587         
00588         /* Map UDP socket       */
00589         
00590         sochandle = -1;
00591         
00592         for( i=0; i < NO_OF_UDPSOCKETS; i++) {
00593                 soc = &udp_socket[i];                           /* Get referense        */
00594 
00595                 if(soc->state != UDP_STATE_OPENED )
00596                         continue;
00597                 
00598                 if(soc->locport != received_udp_packet.dport)
00599                         continue;
00600                 
00601                 /* Socket found */
00602                 
00603                 sochandle = i;
00604                 
00605                 break;
00606         }
00607         
00608         if( sochandle < 0 ) {
00609                 UDP_DEBUGOUT("No socket found for received UDP Packet\r\n");
00610                 
00611                 /* TODO: Send ICMP      */
00612                 
00613                 return(-1);
00614         }
00615         
00616         /* Calculate checksum for received packet       */
00617         
00618         if(soc->opts & UDP_OPT_CHECK_CS) {
00619                 if(received_udp_packet.checksum != 0) {
00620                         checksum = 0;
00621                         i = 0;
00622                         
00623                         /* Do it firstly to IP pseudo header    */
00624         
00625                         checksum = ip_checksum(checksum, (UINT8)(frame->dip >> 24), (UINT8)i++);        
00626                         checksum = ip_checksum(checksum, (UINT8)(frame->dip >> 16), (UINT8)i++);
00627                         checksum = ip_checksum(checksum, (UINT8)(frame->dip >> 8), (UINT8)i++);
00628                         checksum = ip_checksum(checksum, (UINT8)frame->dip, (UINT8)i++);
00629         
00630                         checksum = ip_checksum(checksum, (UINT8)(frame->sip >> 24), (UINT8)i++);        
00631                         checksum = ip_checksum(checksum, (UINT8)(frame->sip >> 16), (UINT8)i++);
00632                         checksum = ip_checksum(checksum, (UINT8)(frame->sip >> 8), (UINT8)i++);
00633                         checksum = ip_checksum(checksum, (UINT8)frame->sip, (UINT8)i++);        
00634         
00635                         checksum = ip_checksum(checksum, 0, (UINT8)i++);
00636         
00637                         checksum = ip_checksum(checksum, (UINT8)IP_UDP, (UINT8)i++);
00638                 
00639                         checksum = ip_checksum(checksum, (UINT8)(len >> 8), (UINT8)i++);
00640                         checksum = ip_checksum(checksum, (UINT8)len, (UINT8)i++);       
00641 
00642         
00643                         NETWORK_RECEIVE_INITIALIZE(frame->buf_index);
00644         
00645                         for(i=0; i < len; i++)
00646                                 checksum = ip_checksum(checksum, RECEIVE_NETWORK_B(), (UINT8)i);
00647         
00648                         checksum = ~ checksum;
00649         
00650                         if(checksum != IP_GOOD_CS) {
00651                                 UDP_DEBUGOUT("ERROR: UDP Checksum failed!\n\r");
00652                                 return (-1);
00653                         }
00654                 
00655                 }
00656         
00657                 UDP_DEBUGOUT("UDP Checksum OK\n\r");
00658         
00659         }
00660         
00661         
00662         received_udp_packet.buf_index = frame->buf_index + UDP_HLEN;
00663         NETWORK_RECEIVE_INITIALIZE(received_udp_packet.buf_index);
00664         
00665         /* Generate data event  */
00666         
00667         soc->event_listener(sochandle, UDP_EVENT_DATA, frame->sip, received_udp_packet.sport, received_udp_packet.buf_index, received_udp_packet.tlen - UDP_HLEN);
00668         
00669         return(1);
00670 
00671 }
00672 
00684 UINT16 udp_getfreeport (void){
00685         struct ucb* soc;
00686         static UINT16 lastport = 1;
00687         UINT16 start;
00688         UINT16 i;
00689         
00690 
00691         /* Try with every port to every socket untill free found        */
00692                 
00693         for( start = lastport++; start != lastport; lastport++) {
00694                 if(lastport == UDP_PORTS_END)
00695                         lastport = 1;
00696                         
00697                 for(i = 0; i < NO_OF_UDPSOCKETS; i++) {
00698                         soc = &udp_socket[i];                                   /* Get socket   */
00699                         
00700                         if( (soc->state > UDP_STATE_CLOSED) && (soc->locport == lastport) )                     {
00701                                 /* Blaah, this socket has reserved the port, go to next one     */
00702                                 break; 
00703                         }
00704                         
00705                 }       
00706                         
00707                 /* Did we found it?     */
00708                         
00709                 if( i == NO_OF_UDPSOCKETS)
00710                         break; 
00711                         
00712         }
00713                 
00714         if(lastport == start) {
00715                 DEBUGOUT("Out of UDP ports!!\n\r");
00716                 return(0);
00717         }
00718                 
00719         return(lastport);
00720                 
00721 }
00722 
00723 
00724 
00725 
00726 

Generated on Sun Aug 3 20:33:00 2003 for OpenTCP by doxygen1.2.18