Dependencies:   MSCUsbHost NetServices RPCInterface TextLCD mbed

Committer:
yueee_yt
Date:
Wed Aug 22 05:10:09 2012 +0000
Revision:
1:f2088fbce73f
Parent:
0:fd83f3540b1a
???????LM35??????WebServer

Who changed what in which revision?

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