Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
Generated on Tue Jul 12 2022 21:10:25 by
1.7.2