Michael Spencer / Mbed 2 deprecated LaOS

Dependencies:   mbed

Committer:
Michael J. Spencer
Date:
Wed Mar 05 06:14:02 2014 -0800
Revision:
1:f5ac63519541
Initial commit.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Michael J. Spencer 1:f5ac63519541 1 #pragma diag_remark 1464
Michael J. Spencer 1:f5ac63519541 2 /*
Michael J. Spencer 1:f5ac63519541 3 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
Michael J. Spencer 1:f5ac63519541 4
Michael J. Spencer 1:f5ac63519541 5 Permission is hereby granted, free of charge, to any person obtaining a copy
Michael J. Spencer 1:f5ac63519541 6 of this software and associated documentation files (the "Software"), to deal
Michael J. Spencer 1:f5ac63519541 7 in the Software without restriction, including without limitation the rights
Michael J. Spencer 1:f5ac63519541 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Michael J. Spencer 1:f5ac63519541 9 copies of the Software, and to permit persons to whom the Software is
Michael J. Spencer 1:f5ac63519541 10 furnished to do so, subject to the following conditions:
Michael J. Spencer 1:f5ac63519541 11
Michael J. Spencer 1:f5ac63519541 12 The above copyright notice and this permission notice shall be included in
Michael J. Spencer 1:f5ac63519541 13 all copies or substantial portions of the Software.
Michael J. Spencer 1:f5ac63519541 14
Michael J. Spencer 1:f5ac63519541 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Michael J. Spencer 1:f5ac63519541 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Michael J. Spencer 1:f5ac63519541 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Michael J. Spencer 1:f5ac63519541 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Michael J. Spencer 1:f5ac63519541 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Michael J. Spencer 1:f5ac63519541 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
Michael J. Spencer 1:f5ac63519541 21 THE SOFTWARE.
Michael J. Spencer 1:f5ac63519541 22 */
Michael J. Spencer 1:f5ac63519541 23
Michael J. Spencer 1:f5ac63519541 24 #include "lwip/ip_addr.h"
Michael J. Spencer 1:f5ac63519541 25 #include "lwipNetUdpSocket.h"
Michael J. Spencer 1:f5ac63519541 26 #include "lwip/udp.h"
Michael J. Spencer 1:f5ac63519541 27 #include "lwip/igmp.h"
Michael J. Spencer 1:f5ac63519541 28
Michael J. Spencer 1:f5ac63519541 29
Michael J. Spencer 1:f5ac63519541 30 //#define __DEBUG
Michael J. Spencer 1:f5ac63519541 31 #include "dbg/dbg.h"
Michael J. Spencer 1:f5ac63519541 32
Michael J. Spencer 1:f5ac63519541 33 #include "netCfg.h"
Michael J. Spencer 1:f5ac63519541 34 #if NET_LWIP_STACK
Michael J. Spencer 1:f5ac63519541 35
Michael J. Spencer 1:f5ac63519541 36 LwipNetUdpSocket::LwipNetUdpSocket(udp_pcb* pPcb /*= NULL*/) : NetUdpSocket(), m_pPcb(pPcb), m_lInPkt(), m_multicastGroup() //Passes a pcb if already created (by an accept req for instance), in that case transfers ownership
Michael J. Spencer 1:f5ac63519541 37 {
Michael J. Spencer 1:f5ac63519541 38 DBG("New LwipNetUdpSocket %p (pPCb=%p)\n", (void*)this, (void*) pPcb);
Michael J. Spencer 1:f5ac63519541 39 if(!m_pPcb)
Michael J. Spencer 1:f5ac63519541 40 m_pPcb = udp_new();
Michael J. Spencer 1:f5ac63519541 41 if(m_pPcb)
Michael J. Spencer 1:f5ac63519541 42 {
Michael J. Spencer 1:f5ac63519541 43 //Setup callback
Michael J. Spencer 1:f5ac63519541 44 udp_recv( (udp_pcb*) m_pPcb, LwipNetUdpSocket::sRecvCb, (void*) this );
Michael J. Spencer 1:f5ac63519541 45 }
Michael J. Spencer 1:f5ac63519541 46 }
Michael J. Spencer 1:f5ac63519541 47
Michael J. Spencer 1:f5ac63519541 48 LwipNetUdpSocket::~LwipNetUdpSocket()
Michael J. Spencer 1:f5ac63519541 49 {
Michael J. Spencer 1:f5ac63519541 50 close();
Michael J. Spencer 1:f5ac63519541 51 }
Michael J. Spencer 1:f5ac63519541 52
Michael J. Spencer 1:f5ac63519541 53 NetUdpSocketErr LwipNetUdpSocket::bind(const Host& me)
Michael J. Spencer 1:f5ac63519541 54 {
Michael J. Spencer 1:f5ac63519541 55 err_t err;
Michael J. Spencer 1:f5ac63519541 56
Michael J. Spencer 1:f5ac63519541 57 if(!m_pPcb)
Michael J. Spencer 1:f5ac63519541 58 return NETUDPSOCKET_MEM; //NetUdpSocket was not properly initialised, should destroy it & retry
Michael J. Spencer 1:f5ac63519541 59
Michael J. Spencer 1:f5ac63519541 60 #if LWIP_IGMP //Multicast support enabled
Michael J. Spencer 1:f5ac63519541 61 if(me.getIp().isMulticast())
Michael J. Spencer 1:f5ac63519541 62 {
Michael J. Spencer 1:f5ac63519541 63 DBG("This is a multicast addr, joining multicast group\n");
Michael J. Spencer 1:f5ac63519541 64 m_multicastGroup = me.getIp();
Michael J. Spencer 1:f5ac63519541 65 ip_addr_t multicastGroupAddr = m_multicastGroup.getStruct();
Michael J. Spencer 1:f5ac63519541 66 err = igmp_joingroup(IP_ADDR_ANY, &multicastGroupAddr);
Michael J. Spencer 1:f5ac63519541 67 if(err)
Michael J. Spencer 1:f5ac63519541 68 return NETUDPSOCKET_IF; //Could not find or create group
Michael J. Spencer 1:f5ac63519541 69 }
Michael J. Spencer 1:f5ac63519541 70 #endif
Michael J. Spencer 1:f5ac63519541 71
Michael J. Spencer 1:f5ac63519541 72 err = udp_bind( (udp_pcb*) m_pPcb, IP_ADDR_ANY, me.getPort()); //IP_ADDR_ANY : Bind the connection to all local addresses
Michael J. Spencer 1:f5ac63519541 73 if(err)
Michael J. Spencer 1:f5ac63519541 74 return NETUDPSOCKET_INUSE;
Michael J. Spencer 1:f5ac63519541 75
Michael J. Spencer 1:f5ac63519541 76 //Setup callback
Michael J. Spencer 1:f5ac63519541 77 udp_recv( (udp_pcb*) m_pPcb, LwipNetUdpSocket::sRecvCb, (void*) this );
Michael J. Spencer 1:f5ac63519541 78
Michael J. Spencer 1:f5ac63519541 79 return NETUDPSOCKET_OK;
Michael J. Spencer 1:f5ac63519541 80 }
Michael J. Spencer 1:f5ac63519541 81
Michael J. Spencer 1:f5ac63519541 82 #define MAX(a,b) ((a>b)?a:b)
Michael J. Spencer 1:f5ac63519541 83 #define MIN(a,b) ((a<b)?a:b)
Michael J. Spencer 1:f5ac63519541 84
Michael J. Spencer 1:f5ac63519541 85 int /*if < 0 : NetUdpSocketErr*/ LwipNetUdpSocket::sendto(const char* buf, int len, Host* pHost)
Michael J. Spencer 1:f5ac63519541 86 {
Michael J. Spencer 1:f5ac63519541 87 if( !m_pPcb ) //Pcb doesn't exist (anymore)
Michael J. Spencer 1:f5ac63519541 88 return NETUDPSOCKET_MEM;
Michael J. Spencer 1:f5ac63519541 89 pbuf* p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_POOL);
Michael J. Spencer 1:f5ac63519541 90 if( !p )
Michael J. Spencer 1:f5ac63519541 91 return NETUDPSOCKET_MEM;
Michael J. Spencer 1:f5ac63519541 92 char* pBuf = (char*) buf;
Michael J. Spencer 1:f5ac63519541 93 pbuf* q = p;
Michael J. Spencer 1:f5ac63519541 94 do
Michael J. Spencer 1:f5ac63519541 95 {
Michael J. Spencer 1:f5ac63519541 96 memcpy (q->payload, (void*)pBuf, q->len);
Michael J. Spencer 1:f5ac63519541 97 pBuf += q->len;
Michael J. Spencer 1:f5ac63519541 98 q = q->next;
Michael J. Spencer 1:f5ac63519541 99 } while(q != NULL);
Michael J. Spencer 1:f5ac63519541 100
Michael J. Spencer 1:f5ac63519541 101 ip_addr_t ipaddr = pHost->getIp().getStruct();
Michael J. Spencer 1:f5ac63519541 102 err_t err = udp_sendto( (udp_pcb*) m_pPcb, p, &ipaddr, pHost->getPort() );
Michael J. Spencer 1:f5ac63519541 103 pbuf_free( p );
Michael J. Spencer 1:f5ac63519541 104 if(err)
Michael J. Spencer 1:f5ac63519541 105 return NETUDPSOCKET_SETUP; //Connection problem
Michael J. Spencer 1:f5ac63519541 106 DBG("%d bytes sent in UDP Socket.\n", len);
Michael J. Spencer 1:f5ac63519541 107 return len;
Michael J. Spencer 1:f5ac63519541 108 }
Michael J. Spencer 1:f5ac63519541 109
Michael J. Spencer 1:f5ac63519541 110 int /*if < 0 : NetUdpSocketErr*/ LwipNetUdpSocket::recvfrom(char* buf, int len, Host* pHost)
Michael J. Spencer 1:f5ac63519541 111 {
Michael J. Spencer 1:f5ac63519541 112 if( !m_pPcb ) //Pcb doesn't exist (anymore)
Michael J. Spencer 1:f5ac63519541 113 return NETUDPSOCKET_MEM;
Michael J. Spencer 1:f5ac63519541 114 int inLen = 0;
Michael J. Spencer 1:f5ac63519541 115 int cpyLen = 0;
Michael J. Spencer 1:f5ac63519541 116
Michael J. Spencer 1:f5ac63519541 117 static int rmgLen = 0;
Michael J. Spencer 1:f5ac63519541 118 //Contains the remaining len in this pbuf
Michael J. Spencer 1:f5ac63519541 119
Michael J. Spencer 1:f5ac63519541 120 if( m_lInPkt.empty() )
Michael J. Spencer 1:f5ac63519541 121 return 0;
Michael J. Spencer 1:f5ac63519541 122
Michael J. Spencer 1:f5ac63519541 123 pbuf* pBuf = (pbuf*) m_lInPkt.front().pBuf;
Michael J. Spencer 1:f5ac63519541 124
Michael J. Spencer 1:f5ac63519541 125 if(pHost)
Michael J. Spencer 1:f5ac63519541 126 *pHost = Host( IpAddr(&m_lInPkt.front().addr), m_lInPkt.front().port );
Michael J. Spencer 1:f5ac63519541 127
Michael J. Spencer 1:f5ac63519541 128 if( !pBuf )
Michael J. Spencer 1:f5ac63519541 129 {
Michael J. Spencer 1:f5ac63519541 130 rmgLen = 0;
Michael J. Spencer 1:f5ac63519541 131 return 0;
Michael J. Spencer 1:f5ac63519541 132 }
Michael J. Spencer 1:f5ac63519541 133
Michael J. Spencer 1:f5ac63519541 134 if ( !rmgLen ) //We did not know m_pReadPbuf->len last time we called this fn
Michael J. Spencer 1:f5ac63519541 135 {
Michael J. Spencer 1:f5ac63519541 136 rmgLen = pBuf->len;
Michael J. Spencer 1:f5ac63519541 137 }
Michael J. Spencer 1:f5ac63519541 138
Michael J. Spencer 1:f5ac63519541 139 while ( inLen < len )
Michael J. Spencer 1:f5ac63519541 140 {
Michael J. Spencer 1:f5ac63519541 141 cpyLen = MIN( (len - inLen), rmgLen ); //Remaining len to copy, remaining len in THIS pbuf
Michael J. Spencer 1:f5ac63519541 142 memcpy((void*)buf, (void*)((char*)(pBuf->payload) + (pBuf->len - rmgLen)), cpyLen);
Michael J. Spencer 1:f5ac63519541 143 inLen += cpyLen;
Michael J. Spencer 1:f5ac63519541 144 buf += cpyLen;
Michael J. Spencer 1:f5ac63519541 145
Michael J. Spencer 1:f5ac63519541 146 rmgLen = rmgLen - cpyLen; //Update rmgLen
Michael J. Spencer 1:f5ac63519541 147
Michael J. Spencer 1:f5ac63519541 148 if( rmgLen > 0 )
Michael J. Spencer 1:f5ac63519541 149 {
Michael J. Spencer 1:f5ac63519541 150 //We did not read this pbuf completely, so let's save it's pos & return
Michael J. Spencer 1:f5ac63519541 151 break;
Michael J. Spencer 1:f5ac63519541 152 }
Michael J. Spencer 1:f5ac63519541 153
Michael J. Spencer 1:f5ac63519541 154 if(pBuf->next)
Michael J. Spencer 1:f5ac63519541 155 {
Michael J. Spencer 1:f5ac63519541 156 pbuf* pNextPBuf = pBuf->next;
Michael J. Spencer 1:f5ac63519541 157 pBuf->next = NULL; //So that it is not freed as well
Michael J. Spencer 1:f5ac63519541 158 //We get the reference to pNextPBuf from m_pReadPbuf
Michael J. Spencer 1:f5ac63519541 159 pbuf_free((pbuf*)pBuf);
Michael J. Spencer 1:f5ac63519541 160 pBuf = pNextPBuf;
Michael J. Spencer 1:f5ac63519541 161 rmgLen = pBuf->len;
Michael J. Spencer 1:f5ac63519541 162 }
Michael J. Spencer 1:f5ac63519541 163 else
Michael J. Spencer 1:f5ac63519541 164 {
Michael J. Spencer 1:f5ac63519541 165 pbuf_free((pbuf*)pBuf);
Michael J. Spencer 1:f5ac63519541 166 pBuf = NULL;
Michael J. Spencer 1:f5ac63519541 167 rmgLen = 0;
Michael J. Spencer 1:f5ac63519541 168 m_lInPkt.pop_front();
Michael J. Spencer 1:f5ac63519541 169 break; //No more data to read
Michael J. Spencer 1:f5ac63519541 170 }
Michael J. Spencer 1:f5ac63519541 171 }
Michael J. Spencer 1:f5ac63519541 172
Michael J. Spencer 1:f5ac63519541 173 return inLen;
Michael J. Spencer 1:f5ac63519541 174 }
Michael J. Spencer 1:f5ac63519541 175
Michael J. Spencer 1:f5ac63519541 176 NetUdpSocketErr LwipNetUdpSocket::close()
Michael J. Spencer 1:f5ac63519541 177 {
Michael J. Spencer 1:f5ac63519541 178 DBG("LwipNetUdpSocket::close() : Closing...\n");
Michael J. Spencer 1:f5ac63519541 179
Michael J. Spencer 1:f5ac63519541 180 if(m_closed)
Michael J. Spencer 1:f5ac63519541 181 return NETUDPSOCKET_OK; //Already being closed
Michael J. Spencer 1:f5ac63519541 182 m_closed = true;
Michael J. Spencer 1:f5ac63519541 183
Michael J. Spencer 1:f5ac63519541 184 if( !m_pPcb ) //Pcb doesn't exist (anymore)
Michael J. Spencer 1:f5ac63519541 185 return NETUDPSOCKET_MEM;
Michael J. Spencer 1:f5ac63519541 186
Michael J. Spencer 1:f5ac63519541 187 DBG("LwipNetUdpSocket::close() : Cleanup...\n");
Michael J. Spencer 1:f5ac63519541 188
Michael J. Spencer 1:f5ac63519541 189 //Cleanup incoming data
Michael J. Spencer 1:f5ac63519541 190 cleanUp();
Michael J. Spencer 1:f5ac63519541 191
Michael J. Spencer 1:f5ac63519541 192
Michael J. Spencer 1:f5ac63519541 193 DBG("LwipNetUdpSocket::close() : removing m_pPcb...\n");
Michael J. Spencer 1:f5ac63519541 194 udp_remove( (udp_pcb*) m_pPcb);
Michael J. Spencer 1:f5ac63519541 195
Michael J. Spencer 1:f5ac63519541 196 m_pPcb = NULL;
Michael J. Spencer 1:f5ac63519541 197 return NETUDPSOCKET_OK;
Michael J. Spencer 1:f5ac63519541 198 }
Michael J. Spencer 1:f5ac63519541 199
Michael J. Spencer 1:f5ac63519541 200 NetUdpSocketErr LwipNetUdpSocket::poll()
Michael J. Spencer 1:f5ac63519541 201 {
Michael J. Spencer 1:f5ac63519541 202 NetUdpSocket::flushEvents();
Michael J. Spencer 1:f5ac63519541 203 return NETUDPSOCKET_OK;
Michael J. Spencer 1:f5ac63519541 204 }
Michael J. Spencer 1:f5ac63519541 205
Michael J. Spencer 1:f5ac63519541 206 // Callbacks events
Michael J. Spencer 1:f5ac63519541 207
Michael J. Spencer 1:f5ac63519541 208 void LwipNetUdpSocket::recvCb(udp_pcb* pcb, struct pbuf* p, ip_addr_t* addr, u16_t port)
Michael J. Spencer 1:f5ac63519541 209 {
Michael J. Spencer 1:f5ac63519541 210 DBG(" Packet of length %d arrived in UDP Socket.\n", p->tot_len);
Michael J. Spencer 1:f5ac63519541 211 list<InPacket>::iterator it;
Michael J. Spencer 1:f5ac63519541 212 for ( it = m_lInPkt.begin(); it != m_lInPkt.end(); it++ )
Michael J. Spencer 1:f5ac63519541 213 {
Michael J. Spencer 1:f5ac63519541 214 if( ip_addr_cmp((&((*it).addr)), addr) && ((*it).port == port) )
Michael J. Spencer 1:f5ac63519541 215 {
Michael J. Spencer 1:f5ac63519541 216 //Let's tail this packet to the previous one
Michael J. Spencer 1:f5ac63519541 217 pbuf_cat((pbuf*)((*it).pBuf), p);
Michael J. Spencer 1:f5ac63519541 218 //No need to queue an event in that case since the read buf has not been processed yet
Michael J. Spencer 1:f5ac63519541 219 return;
Michael J. Spencer 1:f5ac63519541 220 }
Michael J. Spencer 1:f5ac63519541 221 }
Michael J. Spencer 1:f5ac63519541 222
Michael J. Spencer 1:f5ac63519541 223 //New host, add a packet to the queue
Michael J. Spencer 1:f5ac63519541 224 InPacket pkt;
Michael J. Spencer 1:f5ac63519541 225 pkt.pBuf = p;
Michael J. Spencer 1:f5ac63519541 226 pkt.addr = *addr;
Michael J. Spencer 1:f5ac63519541 227 pkt.port = port;
Michael J. Spencer 1:f5ac63519541 228 m_lInPkt.push_back(pkt);
Michael J. Spencer 1:f5ac63519541 229
Michael J. Spencer 1:f5ac63519541 230 queueEvent(NETUDPSOCKET_READABLE);
Michael J. Spencer 1:f5ac63519541 231 }
Michael J. Spencer 1:f5ac63519541 232
Michael J. Spencer 1:f5ac63519541 233 void LwipNetUdpSocket::cleanUp() //Flush input buffer
Michael J. Spencer 1:f5ac63519541 234 {
Michael J. Spencer 1:f5ac63519541 235 //Ensure that further error won't be followed to this inst (which can be destroyed)
Michael J. Spencer 1:f5ac63519541 236 if( m_pPcb )
Michael J. Spencer 1:f5ac63519541 237 {
Michael J. Spencer 1:f5ac63519541 238 udp_recv( (udp_pcb*) m_pPcb, NULL, (void*) NULL );
Michael J. Spencer 1:f5ac63519541 239 }
Michael J. Spencer 1:f5ac63519541 240
Michael J. Spencer 1:f5ac63519541 241 //Leaving multicast group(Ok because LwIP has a refscount for multicast group)
Michael J. Spencer 1:f5ac63519541 242 #if LWIP_IGMP //Multicast support enabled
Michael J. Spencer 1:f5ac63519541 243 if(m_multicastGroup.isMulticast())
Michael J. Spencer 1:f5ac63519541 244 {
Michael J. Spencer 1:f5ac63519541 245 ip_addr_t multicastGroupAddr = m_multicastGroup.getStruct();
Michael J. Spencer 1:f5ac63519541 246 igmp_leavegroup(IP_ADDR_ANY, &multicastGroupAddr);
Michael J. Spencer 1:f5ac63519541 247 m_multicastGroup = IpAddr();
Michael J. Spencer 1:f5ac63519541 248 }
Michael J. Spencer 1:f5ac63519541 249 #endif
Michael J. Spencer 1:f5ac63519541 250
Michael J. Spencer 1:f5ac63519541 251 list<InPacket>::iterator it;
Michael J. Spencer 1:f5ac63519541 252 for ( it = m_lInPkt.begin(); it != m_lInPkt.end(); it++ )
Michael J. Spencer 1:f5ac63519541 253 {
Michael J. Spencer 1:f5ac63519541 254 //Free buf
Michael J. Spencer 1:f5ac63519541 255 pbuf_free((pbuf*)((*it).pBuf));
Michael J. Spencer 1:f5ac63519541 256 }
Michael J. Spencer 1:f5ac63519541 257 m_lInPkt.clear();
Michael J. Spencer 1:f5ac63519541 258 }
Michael J. Spencer 1:f5ac63519541 259
Michael J. Spencer 1:f5ac63519541 260 // Static callback from LwIp
Michael J. Spencer 1:f5ac63519541 261
Michael J. Spencer 1:f5ac63519541 262 void LwipNetUdpSocket::sRecvCb(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
Michael J. Spencer 1:f5ac63519541 263 {
Michael J. Spencer 1:f5ac63519541 264 LwipNetUdpSocket* pMe = (LwipNetUdpSocket*) arg;
Michael J. Spencer 1:f5ac63519541 265 return pMe->recvCb( pcb, p, addr, port );
Michael J. Spencer 1:f5ac63519541 266 }
Michael J. Spencer 1:f5ac63519541 267
Michael J. Spencer 1:f5ac63519541 268 #endif