D:/DRISSI/arduino-0022/arduino-0022/libraries/Ethernet/Udp.cpp
00001 /*
00002  *  Udp.cpp: Library to send/receive UDP packets with the Arduino ethernet shield.
00003  *  This version only offers minimal wrapping of socket.c/socket.h
00004  *  Drop Udp.h/.cpp into the Ethernet library directory at hardware/libraries/Ethernet/ 
00005  *
00006  * MIT License:
00007  * Copyright (c) 2008 Bjoern Hartmann
00008  * Permission is hereby granted, free of charge, to any person obtaining a copy
00009  * of this software and associated documentation files (the "Software"), to deal
00010  * in the Software without restriction, including without limitation the rights
00011  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00012  * copies of the Software, and to permit persons to whom the Software is
00013  * furnished to do so, subject to the following conditions:
00014  * 
00015  * The above copyright notice and this permission notice shall be included in
00016  * all copies or substantial portions of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00019  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00020  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00021  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00022  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00023  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00024  * THE SOFTWARE.
00025  *
00026  * bjoern@cs.stanford.edu 12/30/2008
00027  */
00028 
00029 #include "w5100.h"
00030 #include "socket.h"
00031 #include "Ethernet.h"
00032 #include "Udp.h"
00033 
00034 /* Start UDP socket, listening at local port PORT */
00035 void UdpClass::begin(uint16_t port) {
00036   _port = port;
00037   _sock = 0; //TODO: should not be hardcoded
00038   socket(_sock, SnMR::UDP, _port, 0);
00039 }
00040 
00041 /* Send packet contained in buf of length len to peer at specified ip, and port */
00042 /* Use this function to transmit binary data that might contain 0x00 bytes*/
00043 /* This function returns sent data size for success else -1. */
00044 uint16_t UdpClass::sendPacket(uint8_t * buf, uint16_t len,  uint8_t * ip, uint16_t port){
00045   return sendto(_sock,(const uint8_t *)buf,len,ip,port);
00046 }
00047 
00048 /* Send  zero-terminated string str as packet to peer at specified ip, and port */
00049 /* This function returns sent data size for success else -1. */
00050 uint16_t UdpClass::sendPacket(const char str[], uint8_t * ip, uint16_t port){   
00051   // compute strlen
00052   const char *s;
00053   for(s = str; *s; ++s);
00054   uint16_t len = (s-str);
00055   // send packet
00056   return sendto(_sock,(const uint8_t *)str,len,ip,port);
00057 }
00058 /* Is data available in rx buffer? Returns 0 if no, number of available bytes if yes. 
00059  * returned value includes 8 byte UDP header!*/
00060 int UdpClass::available() {
00061   return W5100.getRXReceivedSize(_sock);
00062 }
00063 
00064 
00065 /* Read a received packet into buffer buf (which is of maximum length len); */
00066 /* store calling ip and port as well. Call available() to make sure data is ready first. */
00067 /* NOTE: I don't believe len is ever checked in implementation of recvfrom(),*/
00068 /*       so it's easy to overflow buffer. so we check and truncate. */
00069 /* returns number of bytes read, or negative number of bytes we would have needed if we truncated */
00070 int UdpClass::readPacket(uint8_t * buf, uint16_t bufLen, uint8_t *ip, uint16_t *port) {
00071   int packetLen = available()-8; //skip UDP header;
00072   if(packetLen < 0 ) return 0; // no real data here     
00073   if(packetLen > (int)bufLen) {
00074     //packet is too large - truncate
00075     //HACK - hand-parse the UDP packet using TCP recv method
00076     uint8_t tmpBuf[8];
00077     int i;
00078     //read 8 header bytes and get IP and port from it
00079     recv(_sock,tmpBuf,8);
00080     ip[0] = tmpBuf[0];
00081     ip[1] = tmpBuf[1];
00082     ip[2] = tmpBuf[2];
00083     ip[3] = tmpBuf[3];
00084     *port = tmpBuf[4];
00085     *port = (*port << 8) + tmpBuf[5];
00086 
00087     //now copy first (bufLen) bytes into buf            
00088     for(i=0;i<(int)bufLen;i++) {
00089       recv(_sock,tmpBuf,1);
00090       buf[i]=tmpBuf[0];
00091     }
00092 
00093     //and just read the rest byte by byte and throw it away
00094     while(available()) {
00095       recv(_sock,tmpBuf,1);
00096     }
00097 
00098     return (-1*packetLen);
00099 
00100     //ALTERNATIVE: requires stdlib - takes a bunch of space
00101     /*//create new buffer and read everything into it
00102                 uint8_t * tmpBuf = (uint8_t *)malloc(packetLen);
00103                 recvfrom(_sock,tmpBuf,packetLen,ip,port);
00104                 if(!tmpBuf) return 0; //couldn't allocate
00105                 // copy first bufLen bytes
00106                 for(unsigned int i=0; i<bufLen; i++) {
00107                         buf[i]=tmpBuf[i];
00108                 }
00109                 //free temp buffer
00110                 free(tmpBuf);
00111                 */
00112 
00113 
00114   } 
00115   return recvfrom(_sock,buf,bufLen,ip,port);
00116 }
00117 
00118 /* Read a received packet, throw away peer's ip and port.  See note above. */
00119 int UdpClass::readPacket(uint8_t * buf, uint16_t len) {
00120   uint8_t ip[4];
00121   uint16_t port[1];
00122   return recvfrom(_sock,buf,len,ip,port);
00123 }
00124 
00125 int UdpClass::readPacket(char * buf, uint16_t bufLen, uint8_t *ip, uint16_t &port) {
00126 uint16_t myPort;
00127 uint16_t ret = readPacket( (byte*)buf, bufLen, ip, &myPort);
00128 port = myPort;
00129 return ret;
00130 }
00131 
00132 
00133 
00134 
00135 /* Create one global object */
00136 UdpClass Udp;