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;