Darran Shepherd
/
AutoIpNetStack
Net stack with AutoIP enabled
Embed:
(wiki syntax)
Show/hide line numbers
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*/) : NetUdpSocket(), 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("\r\nNew LwipNetUdpSocket %p (pPCb=%p)\r\n", (void*)this, (void*) pPcb); 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_TRANSPORT, len, PBUF_POOL); 00073 if( !p ) 00074 return NETUDPSOCKET_MEM; 00075 char* pBuf = (char*) buf; 00076 pbuf* q = p; 00077 do 00078 { 00079 memcpy (q->payload, (void*)pBuf, q->len); 00080 pBuf += q->len; 00081 q = q->next; 00082 } while(q != NULL); 00083 00084 err_t err = udp_sendto( (udp_pcb*) m_pPcb, p, &(pHost->getIp().getStruct()), pHost->getPort() ); 00085 pbuf_free( p ); 00086 if(err) 00087 return NETUDPSOCKET_SETUP; //Connection problem 00088 DBG("\r\n%d bytes sent in UDP Socket.\r\n", len); 00089 return len; 00090 } 00091 00092 int /*if < 0 : NetUdpSocketErr*/ LwipNetUdpSocket::recvfrom(char* buf, int len, Host* pHost) 00093 { 00094 if( !m_pPcb ) //Pcb doesn't exist (anymore) 00095 return NETUDPSOCKET_MEM; 00096 int inLen = 0; 00097 int cpyLen = 0; 00098 00099 static int rmgLen = 0; 00100 //Contains the remaining len in this pbuf 00101 00102 if( m_lInPkt.empty() ) 00103 return 0; 00104 00105 pbuf* pBuf = (pbuf*) m_lInPkt.front().pBuf; 00106 00107 if(pHost) 00108 *pHost = Host( IpAddr(&m_lInPkt.front().addr), m_lInPkt.front().port ); 00109 00110 if( !pBuf ) 00111 { 00112 rmgLen = 0; 00113 return 0; 00114 } 00115 00116 if ( !rmgLen ) //We did not know m_pReadPbuf->len last time we called this fn 00117 { 00118 rmgLen = pBuf->len; 00119 } 00120 00121 while ( inLen < len ) 00122 { 00123 cpyLen = MIN( (len - inLen), rmgLen ); //Remaining len to copy, remaining len in THIS pbuf 00124 memcpy((void*)buf, (void*)((char*)(pBuf->payload) + (pBuf->len - rmgLen)), cpyLen); 00125 inLen += cpyLen; 00126 buf += cpyLen; 00127 00128 rmgLen = rmgLen - cpyLen; //Update rmgLen 00129 00130 if( rmgLen > 0 ) 00131 { 00132 //We did not read this pbuf completely, so let's save it's pos & return 00133 break; 00134 } 00135 00136 if(pBuf->next) 00137 { 00138 pbuf* pNextPBuf = pBuf->next; 00139 pBuf->next = NULL; //So that it is not freed as well 00140 //We get the reference to pNextPBuf from m_pReadPbuf 00141 pbuf_free((pbuf*)pBuf); 00142 pBuf = pNextPBuf; 00143 rmgLen = pBuf->len; 00144 } 00145 else 00146 { 00147 pbuf_free((pbuf*)pBuf); 00148 pBuf = NULL; 00149 rmgLen = 0; 00150 m_lInPkt.pop_front(); 00151 break; //No more data to read 00152 } 00153 } 00154 00155 return inLen; 00156 } 00157 00158 NetUdpSocketErr LwipNetUdpSocket::close() 00159 { 00160 DBG("\r\nLwipNetUdpSocket::close() : Closing...\r\n"); 00161 00162 if(m_closed) 00163 return NETUDPSOCKET_OK; //Already being closed 00164 m_closed = true; 00165 00166 if( !m_pPcb ) //Pcb doesn't exist (anymore) 00167 return NETUDPSOCKET_MEM; 00168 00169 DBG("\r\nLwipNetUdpSocket::close() : Cleanup...\r\n"); 00170 00171 //Cleanup incoming data 00172 cleanUp(); 00173 00174 DBG("\r\nLwipNetUdpSocket::close() : removing m_pPcb...\r\n"); 00175 udp_remove( (udp_pcb*) m_pPcb); 00176 00177 m_pPcb = NULL; 00178 return NETUDPSOCKET_OK; 00179 } 00180 00181 NetUdpSocketErr LwipNetUdpSocket::poll() 00182 { 00183 NetUdpSocket::flushEvents(); 00184 return NETUDPSOCKET_OK; 00185 } 00186 00187 // Callbacks events 00188 00189 void LwipNetUdpSocket::recvCb(udp_pcb* pcb, struct pbuf* p, ip_addr_t* addr, u16_t port) 00190 { 00191 DBG("\r\n Packet of length %d arrived in UDP Socket.\r\n", p->tot_len); 00192 list<InPacket>::iterator it; 00193 for ( it = m_lInPkt.begin(); it != m_lInPkt.end(); it++ ) 00194 { 00195 if( ip_addr_cmp((&((*it).addr)), addr) && ((*it).port == port) ) 00196 { 00197 //Let's tail this packet to the previous one 00198 pbuf_cat((pbuf*)((*it).pBuf), p); 00199 //No need to queue an event in that case since the read buf has not been processed yet 00200 return; 00201 } 00202 } 00203 00204 //New host, add a packet to the queue 00205 InPacket pkt; 00206 pkt.pBuf = p; 00207 pkt.addr = *addr; 00208 pkt.port = port; 00209 m_lInPkt.push_back(pkt); 00210 00211 queueEvent(NETUDPSOCKET_READABLE); 00212 } 00213 00214 void LwipNetUdpSocket::cleanUp() //Flush input buffer 00215 { 00216 //Ensure that further error won't be followed to this inst (which can be destroyed) 00217 if( m_pPcb ) 00218 { 00219 udp_recv( (udp_pcb*) m_pPcb, NULL, (void*) NULL ); 00220 } 00221 00222 list<InPacket>::iterator it; 00223 for ( it = m_lInPkt.begin(); it != m_lInPkt.end(); it++ ) 00224 { 00225 //Free buf 00226 pbuf_free((pbuf*)((*it).pBuf)); 00227 } 00228 m_lInPkt.clear(); 00229 } 00230 00231 // Static callback from LwIp 00232 00233 void LwipNetUdpSocket::sRecvCb(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) 00234 { 00235 LwipNetUdpSocket* pMe = (LwipNetUdpSocket*) arg; 00236 return pMe->recvCb( pcb, p, addr, port ); 00237 } 00238 00239 #endif
Generated on Tue Jul 12 2022 15:37:04 by 1.7.2