Ilya I / Mbed 2 deprecated iva2k_NetHttpServerTcpSockets

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lwipNetUdpSocket.cpp Source File

lwipNetUdpSocket.cpp

00001 
00002 /*
00003 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
00004  
00005 Permission is hereby granted, free of charge, to any person obtaining a copy
00006 of this software and associated documentation files (the "Software"), to deal
00007 in the Software without restriction, including without limitation the rights
00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00009 copies of the Software, and to permit persons to whom the Software is
00010 furnished to do so, subject to the following conditions:
00011  
00012 The above copyright notice and this permission notice shall be included in
00013 all copies or substantial portions of the Software.
00014  
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00021 THE SOFTWARE.
00022 */
00023 
00024 #include "lwipNetUdpSocket.h"
00025 #include "lwip/udp.h"
00026 
00027 //#define __DEBUG
00028 #include "dbg/dbg.h"
00029 
00030 #include "netCfg.h"
00031 #if NET_LWIP_STACK
00032 
00033 LwipNetUdpSocket::LwipNetUdpSocket(udp_pcb* pPcb /*= NULL*/) : m_pPcb(pPcb), m_lInPkt() //Passes a pcb if already created (by an accept req for instance), in that case transfers ownership
00034 {
00035   DBG("New NetUdpSocket %p\r\n", (void*)this);
00036   if(!m_pPcb)
00037     m_pPcb = udp_new();
00038   if(m_pPcb)
00039   {
00040     //Setup callback
00041    // udp_recv( (udp_pcb*) m_pPcb, LwipNetUdpSocket::sRecvCb, (void*) this );
00042   }
00043 }
00044 
00045 LwipNetUdpSocket::~LwipNetUdpSocket()
00046 {
00047   close();
00048 }
00049   
00050 NetUdpSocketErr LwipNetUdpSocket::bind(const Host& me)
00051 {
00052   if(!m_pPcb)
00053     return NETUDPSOCKET_MEM; //NetUdpSocket was not properly initialised, should destroy it & retry
00054     
00055 /*  err_t err = udp_bind( (udp_pcb*) m_pPcb, IP_ADDR_ANY, me.getPort()); //IP_ADDR_ANY : Bind the connection to all local addresses
00056   if(err)
00057     return NETUDPSOCKET_INUSE;*/
00058     
00059   //Setup callback
00060   udp_recv( (udp_pcb*) m_pPcb, LwipNetUdpSocket::sRecvCb, (void*) this );
00061     
00062   return NETUDPSOCKET_OK;
00063 }
00064 
00065 #define MAX(a,b) ((a>b)?a:b)
00066 #define MIN(a,b) ((a<b)?a:b)
00067 
00068 int /*if < 0 : NetUdpSocketErr*/ LwipNetUdpSocket::sendto(const char* buf, int len, Host* pHost)
00069 {
00070   if( !m_pPcb ) //Pcb doesn't exist (anymore)
00071     return NETUDPSOCKET_MEM;
00072   pbuf* p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM);
00073   if( !p )
00074     return NETUDPSOCKET_MEM;
00075   memcpy (p->payload, (void*)buf, len);  
00076   //udp_connect( (udp_pcb*) m_pPcb, &(pHost->getIp().getStruct()), pHost->getPort() );
00077   //err_t err = udp_send( (udp_pcb*) m_pPcb, p);
00078   err_t err = udp_sendto( (udp_pcb*) m_pPcb, p, &(pHost->getIp().getStruct()), pHost->getPort() );
00079   pbuf_free( p );
00080   if(err)
00081     return NETUDPSOCKET_SETUP; //Connection problem
00082   DBG("%d bytes sent in UDP Socket.\r\n", len);
00083   return len;
00084 }
00085 
00086 int /*if < 0 : NetUdpSocketErr*/ LwipNetUdpSocket::recvfrom(char* buf, int len, Host* pHost)
00087 {
00088   if( !m_pPcb ) //Pcb doesn't exist (anymore)
00089     return NETUDPSOCKET_MEM;
00090   int inLen = 0;
00091   int cpyLen = 0;
00092   
00093   static int rmgLen = 0; 
00094   //Contains the remaining len in this pbuf
00095   
00096   if( m_lInPkt.empty() )
00097     return 0;
00098     
00099   pbuf* pBuf = (pbuf*) m_lInPkt.front().pBuf;
00100   
00101   if(pHost)
00102     *pHost = Host( IpAddr(&m_lInPkt.front().addr), m_lInPkt.front().port );
00103   
00104   if( !pBuf )
00105   {
00106     rmgLen = 0;
00107     return 0;
00108   }
00109   
00110   if ( !rmgLen ) //We did not know m_pReadPbuf->len last time we called this fn
00111   {
00112     rmgLen = pBuf->len;
00113   }
00114   
00115   while ( inLen < len )
00116   {
00117     cpyLen = MIN( (len - inLen), rmgLen ); //Remaining len to copy, remaining len in THIS pbuf
00118     memcpy((void*)buf, (void*)((char*)(pBuf->payload) + (pBuf->len - rmgLen)), cpyLen);
00119     inLen += cpyLen;
00120     buf += cpyLen;
00121     
00122     rmgLen = rmgLen - cpyLen; //Update rmgLen
00123     
00124     if( rmgLen > 0 )
00125     {
00126       //We did not read this pbuf completely, so let's save it's pos & return
00127       break;
00128     }
00129     
00130     if(pBuf->next)
00131     {
00132       pbuf* pNextPBuf = pBuf->next;
00133       pBuf->next = NULL; //So that it is not freed as well
00134       //We get the reference to pNextPBuf from m_pReadPbuf
00135       pbuf_free((pbuf*)pBuf);
00136       pBuf = pNextPBuf;
00137       rmgLen = pBuf->len;
00138     }
00139     else
00140     {
00141       pbuf_free((pbuf*)pBuf);
00142       pBuf = NULL;
00143       rmgLen = 0;
00144       m_lInPkt.pop_front();
00145       break; //No more data to read
00146     } 
00147   }
00148   
00149   return inLen;
00150 }
00151 
00152 NetUdpSocketErr LwipNetUdpSocket::close()
00153 {
00154   //DBG("LwipNetUdpSocket::close() : Closing...\r\n");
00155 
00156   if(m_closed)
00157     return NETUDPSOCKET_OK; //Already being closed
00158   m_closed = true;
00159   
00160   if( !m_pPcb ) //Pcb doesn't exist (anymore)
00161     return NETUDPSOCKET_MEM;
00162     
00163   //Cleanup incoming data
00164   cleanUp();
00165  
00166   udp_remove( (udp_pcb*) m_pPcb);
00167   
00168   m_pPcb = NULL;
00169   return NETUDPSOCKET_OK;
00170 }
00171 
00172 NetUdpSocketErr LwipNetUdpSocket::poll()
00173 {
00174   NetUdpSocket::flushEvents();
00175   return NETUDPSOCKET_OK;
00176 }
00177 
00178 // Callbacks events
00179 
00180 void LwipNetUdpSocket::recvCb(udp_pcb* pcb, struct pbuf* p, ip_addr_t* addr, u16_t port)
00181 {
00182   DBG(" Packet of length %d arrived in UDP Socket.\r\n", p->tot_len);
00183   list<InPacket>::iterator it;
00184   for ( it = m_lInPkt.begin(); it != m_lInPkt.end(); it++ )
00185   {
00186     if( ip_addr_cmp((&((*it).addr)), addr) && ((*it).port == port) )
00187     {
00188       //Let's tail this packet to the previous one
00189       pbuf_cat((pbuf*)(*it).pBuf, p);
00190       //No need to queue an event in that case since the read buf has not been processed yet
00191       return;
00192     }
00193   }
00194 
00195   //New host, add a packet to the queue
00196   InPacket pkt;
00197   pkt.pBuf = p;
00198   pkt.addr = *addr;
00199   pkt.port = port;
00200   m_lInPkt.push_back(pkt);
00201   
00202   queueEvent(NETUDPSOCKET_READABLE);
00203 }
00204 
00205 void LwipNetUdpSocket::cleanUp() //Flush input buffer
00206 {
00207   list<InPacket>::iterator it;
00208   for ( it = m_lInPkt.begin(); it != m_lInPkt.end(); it++ )
00209   {
00210     //Free buf
00211     pbuf_free((pbuf*)(*it).pBuf);
00212   } 
00213   recvfrom(NULL, 0, NULL);
00214   m_lInPkt.clear();
00215 }
00216 
00217 // Static callback from LwIp
00218 
00219 void LwipNetUdpSocket::sRecvCb(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
00220 {
00221   LwipNetUdpSocket* pMe = (LwipNetUdpSocket*) arg;
00222   return pMe->recvCb( pcb, p, addr, port );
00223 }
00224 
00225 #endif