Used in Live Traffic Update Nokia LCD Display Project

Fork of NetServices by Segundo Equipo

Committer:
rrajan8
Date:
Wed Mar 06 19:07:23 2013 +0000
Revision:
8:92b57208ab99
Parent:
0:ac1725ba162c
This project utilizes mbed's networking features to display live traffic updates on the Nokia LCD using the MapQuest API's Traffic Web Service.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
segundo 0:ac1725ba162c 1
segundo 0:ac1725ba162c 2 /*
segundo 0:ac1725ba162c 3 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
segundo 0:ac1725ba162c 4
segundo 0:ac1725ba162c 5 Permission is hereby granted, free of charge, to any person obtaining a copy
segundo 0:ac1725ba162c 6 of this software and associated documentation files (the "Software"), to deal
segundo 0:ac1725ba162c 7 in the Software without restriction, including without limitation the rights
segundo 0:ac1725ba162c 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
segundo 0:ac1725ba162c 9 copies of the Software, and to permit persons to whom the Software is
segundo 0:ac1725ba162c 10 furnished to do so, subject to the following conditions:
segundo 0:ac1725ba162c 11
segundo 0:ac1725ba162c 12 The above copyright notice and this permission notice shall be included in
segundo 0:ac1725ba162c 13 all copies or substantial portions of the Software.
segundo 0:ac1725ba162c 14
segundo 0:ac1725ba162c 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
segundo 0:ac1725ba162c 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
segundo 0:ac1725ba162c 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
segundo 0:ac1725ba162c 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
segundo 0:ac1725ba162c 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
segundo 0:ac1725ba162c 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
segundo 0:ac1725ba162c 21 THE SOFTWARE.
segundo 0:ac1725ba162c 22 */
segundo 0:ac1725ba162c 23
segundo 0:ac1725ba162c 24 #include "lwipNetTcpSocket.h"
segundo 0:ac1725ba162c 25 #include "lwip/tcp.h"
segundo 0:ac1725ba162c 26
segundo 0:ac1725ba162c 27 //#define __DEBUG
segundo 0:ac1725ba162c 28 #include "dbg/dbg.h"
segundo 0:ac1725ba162c 29
segundo 0:ac1725ba162c 30 #include "netCfg.h"
segundo 0:ac1725ba162c 31 #if NET_LWIP_STACK
segundo 0:ac1725ba162c 32
segundo 0:ac1725ba162c 33 LwipNetTcpSocket::LwipNetTcpSocket(tcp_pcb* pPcb /*= NULL*/) : NetTcpSocket(), m_pPcb(pPcb), m_lpInNetTcpSocket(), //Passes a pcb if already created (by an accept req for instance), in that case transfers ownership
segundo 0:ac1725ba162c 34 m_pReadPbuf(NULL)
segundo 0:ac1725ba162c 35 {
segundo 0:ac1725ba162c 36 DBG("New NetTcpSocket %p\n", (void*)this);
segundo 0:ac1725ba162c 37 if(!m_pPcb)
segundo 0:ac1725ba162c 38 {
segundo 0:ac1725ba162c 39 m_pPcb = tcp_new();
segundo 0:ac1725ba162c 40 DBG("Creating new PCB %p\n", m_pPcb);
segundo 0:ac1725ba162c 41 }
segundo 0:ac1725ba162c 42 if(m_pPcb)
segundo 0:ac1725ba162c 43 {
segundo 0:ac1725ba162c 44 //Setup callbacks
segundo 0:ac1725ba162c 45 tcp_arg( (tcp_pcb*) m_pPcb, (void*) this ); //this will be passed to each static callback
segundo 0:ac1725ba162c 46
segundo 0:ac1725ba162c 47 tcp_recv( (tcp_pcb*) m_pPcb, LwipNetTcpSocket::sRecvCb );
segundo 0:ac1725ba162c 48 tcp_sent((tcp_pcb*) m_pPcb, LwipNetTcpSocket::sSentCb );
segundo 0:ac1725ba162c 49 tcp_err( (tcp_pcb*) m_pPcb, LwipNetTcpSocket::sErrCb );
segundo 0:ac1725ba162c 50 //Connected callback is defined in connect()
segundo 0:ac1725ba162c 51 //Accept callback is defined in listen()
segundo 0:ac1725ba162c 52 DBG("NetTcpSocket created.\n");
segundo 0:ac1725ba162c 53 }
segundo 0:ac1725ba162c 54 }
segundo 0:ac1725ba162c 55
segundo 0:ac1725ba162c 56 LwipNetTcpSocket::~LwipNetTcpSocket()
segundo 0:ac1725ba162c 57 {
segundo 0:ac1725ba162c 58 /* if(m_pPcb)
segundo 0:ac1725ba162c 59 tcp_close( (tcp_pcb*) m_pPcb); //Disconnect & free pcb*/
segundo 0:ac1725ba162c 60 close();
segundo 0:ac1725ba162c 61 }
segundo 0:ac1725ba162c 62
segundo 0:ac1725ba162c 63 NetTcpSocketErr LwipNetTcpSocket::bind(const Host& me)
segundo 0:ac1725ba162c 64 {
segundo 0:ac1725ba162c 65 if(!m_pPcb)
segundo 0:ac1725ba162c 66 return NETTCPSOCKET_MEM; //NetTcpSocket was not properly initialised, should destroy it & retry
segundo 0:ac1725ba162c 67
segundo 0:ac1725ba162c 68 err_t err = tcp_bind( (tcp_pcb*) m_pPcb, IP_ADDR_ANY, me.getPort()); //IP_ADDR_ANY : Bind the connection to all local addresses
segundo 0:ac1725ba162c 69 if(err)
segundo 0:ac1725ba162c 70 return NETTCPSOCKET_INUSE;
segundo 0:ac1725ba162c 71
segundo 0:ac1725ba162c 72 return NETTCPSOCKET_OK;
segundo 0:ac1725ba162c 73 }
segundo 0:ac1725ba162c 74
segundo 0:ac1725ba162c 75 NetTcpSocketErr LwipNetTcpSocket::listen()
segundo 0:ac1725ba162c 76 {
segundo 0:ac1725ba162c 77 if(!m_pPcb)
segundo 0:ac1725ba162c 78 return NETTCPSOCKET_MEM; //NetTcpSocket was not properly initialised, should destroy it & retry
segundo 0:ac1725ba162c 79 /*
segundo 0:ac1725ba162c 80 From doc/rawapi.txt :
segundo 0:ac1725ba162c 81
segundo 0:ac1725ba162c 82 The tcp_listen() function returns a new connection identifier, and
segundo 0:ac1725ba162c 83 the one passed as an argument to the function will be
segundo 0:ac1725ba162c 84 deallocated. The reason for this behavior is that less memory is
segundo 0:ac1725ba162c 85 needed for a connection that is listening, so tcp_listen() will
segundo 0:ac1725ba162c 86 reclaim the memory needed for the original connection and allocate a
segundo 0:ac1725ba162c 87 new smaller memory block for the listening connection.
segundo 0:ac1725ba162c 88 */
segundo 0:ac1725ba162c 89
segundo 0:ac1725ba162c 90 // tcp_pcb* pNewPcb = tcp_listen(m_pPcb);
segundo 0:ac1725ba162c 91 tcp_pcb* pNewPcb = tcp_listen_with_backlog((tcp_pcb*)m_pPcb, 5);
segundo 0:ac1725ba162c 92 if( !pNewPcb ) //Not enough memory to create the listening pcb
segundo 0:ac1725ba162c 93 return NETTCPSOCKET_MEM;
segundo 0:ac1725ba162c 94
segundo 0:ac1725ba162c 95 m_pPcb = pNewPcb;
segundo 0:ac1725ba162c 96
segundo 0:ac1725ba162c 97 tcp_accept( (tcp_pcb*) m_pPcb, LwipNetTcpSocket::sAcceptCb );
segundo 0:ac1725ba162c 98
segundo 0:ac1725ba162c 99 return NETTCPSOCKET_OK;
segundo 0:ac1725ba162c 100 }
segundo 0:ac1725ba162c 101
segundo 0:ac1725ba162c 102 NetTcpSocketErr LwipNetTcpSocket::connect(const Host& host)
segundo 0:ac1725ba162c 103 {
segundo 0:ac1725ba162c 104 if(!m_pPcb)
segundo 0:ac1725ba162c 105 return NETTCPSOCKET_MEM; //NetTcpSocket was not properly initialised, should destroy it & retry
segundo 0:ac1725ba162c 106
segundo 0:ac1725ba162c 107 ip_addr_t ip = host.getIp().getStruct();
segundo 0:ac1725ba162c 108 err_t err = tcp_connect( (tcp_pcb*) m_pPcb, &ip, host.getPort(), LwipNetTcpSocket::sConnectedCb );
segundo 0:ac1725ba162c 109
segundo 0:ac1725ba162c 110 if(err)
segundo 0:ac1725ba162c 111 return NETTCPSOCKET_MEM;
segundo 0:ac1725ba162c 112
segundo 0:ac1725ba162c 113 return NETTCPSOCKET_OK;
segundo 0:ac1725ba162c 114 }
segundo 0:ac1725ba162c 115
segundo 0:ac1725ba162c 116 NetTcpSocketErr LwipNetTcpSocket::accept(Host* pClient, NetTcpSocket** ppNewNetTcpSocket)
segundo 0:ac1725ba162c 117 {
segundo 0:ac1725ba162c 118 if( !m_pPcb ) //Pcb doesn't exist (anymore)
segundo 0:ac1725ba162c 119 return NETTCPSOCKET_MEM;
segundo 0:ac1725ba162c 120 //Dequeue a connection
segundo 0:ac1725ba162c 121 //if( m_lpInPcb.empty() )
segundo 0:ac1725ba162c 122 if( m_lpInNetTcpSocket.empty() )
segundo 0:ac1725ba162c 123 return NETTCPSOCKET_EMPTY;
segundo 0:ac1725ba162c 124
segundo 0:ac1725ba162c 125 tcp_accepted( ((tcp_pcb*) m_pPcb) ); //Should fire proper events //WARN: m_pPcb is the GOOD param here (and not pInPcb)
segundo 0:ac1725ba162c 126
segundo 0:ac1725ba162c 127 /* tcp_pcb* pInPcb = m_lpInPcb.front();
segundo 0:ac1725ba162c 128 m_lpInPcb.pop();*/
segundo 0:ac1725ba162c 129
segundo 0:ac1725ba162c 130 if( (m_lpInNetTcpSocket.front()) == NULL )
segundo 0:ac1725ba162c 131 {
segundo 0:ac1725ba162c 132 m_lpInNetTcpSocket.pop();
segundo 0:ac1725ba162c 133 return NETTCPSOCKET_RST;
segundo 0:ac1725ba162c 134 }
segundo 0:ac1725ba162c 135
segundo 0:ac1725ba162c 136 if( (m_lpInNetTcpSocket.front())->m_closed )
segundo 0:ac1725ba162c 137 {
segundo 0:ac1725ba162c 138 Net::releaseTcpSocket(m_lpInNetTcpSocket.front());
segundo 0:ac1725ba162c 139 m_lpInNetTcpSocket.pop();
segundo 0:ac1725ba162c 140 return NETTCPSOCKET_RST;
segundo 0:ac1725ba162c 141 }
segundo 0:ac1725ba162c 142
segundo 0:ac1725ba162c 143 ip_addr_t* ip = (ip_addr_t*) &( (m_lpInNetTcpSocket.front()->m_pPcb)->remote_ip);
segundo 0:ac1725ba162c 144
segundo 0:ac1725ba162c 145 *ppNewNetTcpSocket = m_lpInNetTcpSocket.front();
segundo 0:ac1725ba162c 146 *pClient = Host(
segundo 0:ac1725ba162c 147 IpAddr(
segundo 0:ac1725ba162c 148 ip
segundo 0:ac1725ba162c 149 ),
segundo 0:ac1725ba162c 150 m_lpInNetTcpSocket.front()->m_pPcb->remote_port
segundo 0:ac1725ba162c 151 );
segundo 0:ac1725ba162c 152 m_lpInNetTcpSocket.pop();
segundo 0:ac1725ba162c 153 // *pClient = Host( IpAddr(pInPcb->remote_ip), pInPcb->remote_port );
segundo 0:ac1725ba162c 154
segundo 0:ac1725ba162c 155 //Return a new socket
segundo 0:ac1725ba162c 156 // *ppNewNetTcpSocket = (NetTcpSocket*) new LwipNetTcpSocket(pInPcb);
segundo 0:ac1725ba162c 157
segundo 0:ac1725ba162c 158 //tcp_accepted( ((tcp_pcb*) m_pPcb) ); //Should fire proper events //WARN: m_pPcb is the GOOD param here (and not pInPcb)
segundo 0:ac1725ba162c 159
segundo 0:ac1725ba162c 160 /* if(*ppNewNetTcpSocket == NULL)
segundo 0:ac1725ba162c 161 {
segundo 0:ac1725ba162c 162 DBG("Not enough mem, socket dropped in LwipNetTcpSocket::accept.\n");
segundo 0:ac1725ba162c 163 tcp_abort(pInPcb);
segundo 0:ac1725ba162c 164 }*/
segundo 0:ac1725ba162c 165
segundo 0:ac1725ba162c 166 return NETTCPSOCKET_OK;
segundo 0:ac1725ba162c 167 }
segundo 0:ac1725ba162c 168
segundo 0:ac1725ba162c 169 #define MAX(a,b) (((a)>(b))?(a):(b))
segundo 0:ac1725ba162c 170 #define MIN(a,b) (((a)<(b))?(a):(b))
segundo 0:ac1725ba162c 171
segundo 0:ac1725ba162c 172 int /*if < 0 : NetTcpSocketErr*/ LwipNetTcpSocket::send(const char* buf, int len)
segundo 0:ac1725ba162c 173 {
segundo 0:ac1725ba162c 174 if( !m_pPcb ) //Pcb doesn't exist (anymore)
segundo 0:ac1725ba162c 175 return NETTCPSOCKET_MEM;
segundo 0:ac1725ba162c 176 int outLen = MIN( len, tcp_sndbuf( (tcp_pcb*) m_pPcb) );
segundo 0:ac1725ba162c 177 //tcp_sndbuf() returns the number of bytes available in the output queue, so never go above it
segundo 0:ac1725ba162c 178 err_t err = tcp_write( (tcp_pcb*) m_pPcb, (void*) buf, outLen, TCP_WRITE_FLAG_COPY );
segundo 0:ac1725ba162c 179 //Flags are TCP_WRITE_FLAG_COPY & TCP_WRITE_FLAG_MORE (see tcp_out.c) :
segundo 0:ac1725ba162c 180 //If TCP_WRITE_FLAG_MORE is not set ask client to push buffered data to app
segundo 0:ac1725ba162c 181 if(err)
segundo 0:ac1725ba162c 182 {
segundo 0:ac1725ba162c 183 switch( err )
segundo 0:ac1725ba162c 184 {
segundo 0:ac1725ba162c 185 case ERR_CONN:
segundo 0:ac1725ba162c 186 return (int) NETTCPSOCKET_SETUP; //Not connected properly
segundo 0:ac1725ba162c 187 case ERR_ARG:
segundo 0:ac1725ba162c 188 return (int) NETTCPSOCKET_SETUP; //Wrong args ! (like buf pointing to NULL)
segundo 0:ac1725ba162c 189 case ERR_MEM:
segundo 0:ac1725ba162c 190 default:
segundo 0:ac1725ba162c 191 return (int) NETTCPSOCKET_MEM; //Not enough memory
segundo 0:ac1725ba162c 192 }
segundo 0:ac1725ba162c 193 }
segundo 0:ac1725ba162c 194 return outLen;
segundo 0:ac1725ba162c 195 }
segundo 0:ac1725ba162c 196
segundo 0:ac1725ba162c 197 int /*if < 0 : NetTcpSocketErr*/ LwipNetTcpSocket::recv(char* buf, int len)
segundo 0:ac1725ba162c 198 {
segundo 0:ac1725ba162c 199 if( !m_pPcb ) //Pcb doesn't exist (anymore)
segundo 0:ac1725ba162c 200 return NETTCPSOCKET_MEM;
segundo 0:ac1725ba162c 201 int inLen = 0;
segundo 0:ac1725ba162c 202 int cpyLen = 0;
segundo 0:ac1725ba162c 203
segundo 0:ac1725ba162c 204 static int rmgLen = 0;
segundo 0:ac1725ba162c 205 //Contains the remaining len in this pbuf
segundo 0:ac1725ba162c 206
segundo 0:ac1725ba162c 207 if( !m_pReadPbuf )
segundo 0:ac1725ba162c 208 {
segundo 0:ac1725ba162c 209 rmgLen = 0;
segundo 0:ac1725ba162c 210 return 0;
segundo 0:ac1725ba162c 211 }
segundo 0:ac1725ba162c 212
segundo 0:ac1725ba162c 213 if ( !rmgLen ) //We did not know m_pReadPbuf->len last time we called this fn
segundo 0:ac1725ba162c 214 {
segundo 0:ac1725ba162c 215 rmgLen = m_pReadPbuf->len;
segundo 0:ac1725ba162c 216 }
segundo 0:ac1725ba162c 217
segundo 0:ac1725ba162c 218 while ( inLen < len )
segundo 0:ac1725ba162c 219 {
segundo 0:ac1725ba162c 220 cpyLen = MIN( (len - inLen), rmgLen ); //Remaining len to copy, remaining len in THIS pbuf
segundo 0:ac1725ba162c 221 memcpy((void*)buf, (void*)((char*)(m_pReadPbuf->payload) + (m_pReadPbuf->len - rmgLen)), cpyLen);
segundo 0:ac1725ba162c 222 inLen += cpyLen;
segundo 0:ac1725ba162c 223 buf += cpyLen;
segundo 0:ac1725ba162c 224
segundo 0:ac1725ba162c 225 rmgLen = rmgLen - cpyLen; //Update rmgLen
segundo 0:ac1725ba162c 226
segundo 0:ac1725ba162c 227 if( rmgLen > 0 )
segundo 0:ac1725ba162c 228 {
segundo 0:ac1725ba162c 229 //We did not read this pbuf completely, so let's save it's pos & return
segundo 0:ac1725ba162c 230 break;
segundo 0:ac1725ba162c 231 }
segundo 0:ac1725ba162c 232
segundo 0:ac1725ba162c 233 if(m_pReadPbuf->next)
segundo 0:ac1725ba162c 234 {
segundo 0:ac1725ba162c 235 pbuf* pNextPBuf = m_pReadPbuf->next;
segundo 0:ac1725ba162c 236 m_pReadPbuf->next = NULL; //So that it is not freed as well
segundo 0:ac1725ba162c 237 //We get the reference to pNextPBuf from m_pReadPbuf
segundo 0:ac1725ba162c 238 pbuf_free((pbuf*)m_pReadPbuf);
segundo 0:ac1725ba162c 239 m_pReadPbuf = pNextPBuf;
segundo 0:ac1725ba162c 240 rmgLen = m_pReadPbuf->len;
segundo 0:ac1725ba162c 241 }
segundo 0:ac1725ba162c 242 else
segundo 0:ac1725ba162c 243 {
segundo 0:ac1725ba162c 244 pbuf_free((pbuf*)m_pReadPbuf);
segundo 0:ac1725ba162c 245 m_pReadPbuf = NULL;
segundo 0:ac1725ba162c 246 rmgLen = 0;
segundo 0:ac1725ba162c 247 break; //No more data to read
segundo 0:ac1725ba162c 248 }
segundo 0:ac1725ba162c 249
segundo 0:ac1725ba162c 250 }
segundo 0:ac1725ba162c 251
segundo 0:ac1725ba162c 252 //tcp_recved(m_pPcb, inLen); //Acknowledge the reception
segundo 0:ac1725ba162c 253
segundo 0:ac1725ba162c 254 return inLen;
segundo 0:ac1725ba162c 255 }
segundo 0:ac1725ba162c 256
segundo 0:ac1725ba162c 257 NetTcpSocketErr LwipNetTcpSocket::close()
segundo 0:ac1725ba162c 258 {
segundo 0:ac1725ba162c 259 //DBG("LwipNetTcpSocket::close() : Closing...\n");
segundo 0:ac1725ba162c 260
segundo 0:ac1725ba162c 261 if(m_closed)
segundo 0:ac1725ba162c 262 return NETTCPSOCKET_OK; //Already being closed
segundo 0:ac1725ba162c 263 m_closed = true;
segundo 0:ac1725ba162c 264
segundo 0:ac1725ba162c 265 if( !m_pPcb ) //Pcb doesn't exist (anymore)
segundo 0:ac1725ba162c 266 return NETTCPSOCKET_MEM;
segundo 0:ac1725ba162c 267
segundo 0:ac1725ba162c 268 //Cleanup incoming data
segundo 0:ac1725ba162c 269 cleanUp();
segundo 0:ac1725ba162c 270
segundo 0:ac1725ba162c 271 if( !!tcp_close( (tcp_pcb*) m_pPcb) )
segundo 0:ac1725ba162c 272 {
segundo 0:ac1725ba162c 273 DBG("LwipNetTcpSocket::close() could not close properly, abort.\n");
segundo 0:ac1725ba162c 274 tcp_abort( (tcp_pcb*) m_pPcb);
segundo 0:ac1725ba162c 275 m_pPcb = NULL;
segundo 0:ac1725ba162c 276 return NETTCPSOCKET_MEM;
segundo 0:ac1725ba162c 277 }
segundo 0:ac1725ba162c 278
segundo 0:ac1725ba162c 279 DBG("LwipNetTcpSocket::close() : connection closed successfully.\n");
segundo 0:ac1725ba162c 280
segundo 0:ac1725ba162c 281 m_pPcb = NULL;
segundo 0:ac1725ba162c 282 return NETTCPSOCKET_OK;
segundo 0:ac1725ba162c 283 }
segundo 0:ac1725ba162c 284
segundo 0:ac1725ba162c 285 NetTcpSocketErr LwipNetTcpSocket::poll()
segundo 0:ac1725ba162c 286 {
segundo 0:ac1725ba162c 287 NetTcpSocket::flushEvents();
segundo 0:ac1725ba162c 288 return NETTCPSOCKET_OK;
segundo 0:ac1725ba162c 289 }
segundo 0:ac1725ba162c 290
segundo 0:ac1725ba162c 291 // Callbacks events
segundo 0:ac1725ba162c 292
segundo 0:ac1725ba162c 293 err_t LwipNetTcpSocket::acceptCb(struct tcp_pcb *newpcb, err_t err)
segundo 0:ac1725ba162c 294 {
segundo 0:ac1725ba162c 295 if(err)
segundo 0:ac1725ba162c 296 {
segundo 0:ac1725ba162c 297 DBG("Error %d in LwipNetTcpSocket::acceptCb.\n", err);
segundo 0:ac1725ba162c 298 return err;
segundo 0:ac1725ba162c 299 }
segundo 0:ac1725ba162c 300 //FIXME: MEM Errs
segundo 0:ac1725ba162c 301 //m_lpInPcb.push(newpcb); //Add connection to the queue
segundo 0:ac1725ba162c 302 LwipNetTcpSocket* pNewNetTcpSocket = new LwipNetTcpSocket(newpcb);
segundo 0:ac1725ba162c 303
segundo 0:ac1725ba162c 304 if(pNewNetTcpSocket == NULL)
segundo 0:ac1725ba162c 305 {
segundo 0:ac1725ba162c 306 DBG("Not enough mem, socket dropped in LwipNetTcpSocket::acceptCb.\n");
segundo 0:ac1725ba162c 307 tcp_abort(newpcb);
segundo 0:ac1725ba162c 308 return ERR_ABRT;
segundo 0:ac1725ba162c 309 }
segundo 0:ac1725ba162c 310
segundo 0:ac1725ba162c 311 pNewNetTcpSocket->m_refs++;
segundo 0:ac1725ba162c 312 m_lpInNetTcpSocket.push( pNewNetTcpSocket );
segundo 0:ac1725ba162c 313
segundo 0:ac1725ba162c 314 // tcp_accepted(newpcb);
segundo 0:ac1725ba162c 315 // tcp_accepted( m_pPcb ); //Should fire proper events //WARN: m_pPcb is the GOOD param here (and not pInPcb)
segundo 0:ac1725ba162c 316 queueEvent(NETTCPSOCKET_ACCEPT);
segundo 0:ac1725ba162c 317 return ERR_OK;
segundo 0:ac1725ba162c 318 }
segundo 0:ac1725ba162c 319
segundo 0:ac1725ba162c 320 err_t LwipNetTcpSocket::connectedCb(struct tcp_pcb *tpcb, err_t err)
segundo 0:ac1725ba162c 321 {
segundo 0:ac1725ba162c 322 queueEvent(NETTCPSOCKET_CONNECTED);
segundo 0:ac1725ba162c 323 return ERR_OK;
segundo 0:ac1725ba162c 324 }
segundo 0:ac1725ba162c 325
segundo 0:ac1725ba162c 326 void LwipNetTcpSocket::errCb(err_t err)
segundo 0:ac1725ba162c 327 {
segundo 0:ac1725ba162c 328 DBG("NetTcpSocket %p - Error %d in LwipNetTcpSocket::errCb.\n", (void*)this, err);
segundo 0:ac1725ba162c 329 //WARN: At this point, m_pPcb has been freed by lwIP
segundo 0:ac1725ba162c 330 m_pPcb = NULL;
segundo 0:ac1725ba162c 331 //These errors are fatal, discard all events queued before so that the errors are handled first
segundo 0:ac1725ba162c 332 discardEvents();
segundo 0:ac1725ba162c 333 m_closed = true;
segundo 0:ac1725ba162c 334 cleanUp();
segundo 0:ac1725ba162c 335 if( err == ERR_ABRT)
segundo 0:ac1725ba162c 336 queueEvent(NETTCPSOCKET_CONABRT);
segundo 0:ac1725ba162c 337 else //if( err == ERR_RST)
segundo 0:ac1725ba162c 338 queueEvent(NETTCPSOCKET_CONRST);
segundo 0:ac1725ba162c 339 }
segundo 0:ac1725ba162c 340
segundo 0:ac1725ba162c 341 err_t LwipNetTcpSocket::sentCb(tcp_pcb* tpcb, u16_t len)
segundo 0:ac1725ba162c 342 {
segundo 0:ac1725ba162c 343 // DBG("%d bytes ACKed by host.\n", len);
segundo 0:ac1725ba162c 344 queueEvent(NETTCPSOCKET_WRITEABLE);
segundo 0:ac1725ba162c 345 return ERR_OK;
segundo 0:ac1725ba162c 346 }
segundo 0:ac1725ba162c 347
segundo 0:ac1725ba162c 348 err_t LwipNetTcpSocket::recvCb(tcp_pcb* tpcb, pbuf *p, err_t err)
segundo 0:ac1725ba162c 349 {
segundo 0:ac1725ba162c 350 //Store pbuf ptr
segundo 0:ac1725ba162c 351 // DBG("Receive CB with err = %d & len = %d.\n", err, p->tot_len);
segundo 0:ac1725ba162c 352 // tcp_recved( (tcp_pcb*) m_pPcb, p->tot_len); //Acknowledge the reception
segundo 0:ac1725ba162c 353
segundo 0:ac1725ba162c 354 if(err)
segundo 0:ac1725ba162c 355 {
segundo 0:ac1725ba162c 356 queueEvent(NETTCPSOCKET_ERROR);
segundo 0:ac1725ba162c 357 return ERR_OK; //FIXME: More robust error handling there
segundo 0:ac1725ba162c 358 }
segundo 0:ac1725ba162c 359 else if(!p)
segundo 0:ac1725ba162c 360 {
segundo 0:ac1725ba162c 361 DBG("NetTcpSocket %p - Connection closed by remote host (LwipNetTcpSocket::recvCb).\n", (void*)this);
segundo 0:ac1725ba162c 362 //Buf is NULL, that means that the connection has been closed by remote host
segundo 0:ac1725ba162c 363
segundo 0:ac1725ba162c 364 //FIX: 27/05/2010: We do not want to deallocate the socket while some data might still be readable
segundo 0:ac1725ba162c 365 //REMOVED: close();
segundo 0:ac1725ba162c 366
segundo 0:ac1725ba162c 367 //However we do not want to close the socket yet
segundo 0:ac1725ba162c 368
segundo 0:ac1725ba162c 369 queueEvent(NETTCPSOCKET_DISCONNECTED);
segundo 0:ac1725ba162c 370 return ERR_OK;
segundo 0:ac1725ba162c 371 }
segundo 0:ac1725ba162c 372
segundo 0:ac1725ba162c 373 //We asserted that p is a valid pointer
segundo 0:ac1725ba162c 374
segundo 0:ac1725ba162c 375 //New data processing
segundo 0:ac1725ba162c 376 tcp_recved( tpcb, p->tot_len); //Acknowledge the reception
segundo 0:ac1725ba162c 377 if(!m_pReadPbuf)
segundo 0:ac1725ba162c 378 {
segundo 0:ac1725ba162c 379 m_pReadPbuf = p;
segundo 0:ac1725ba162c 380 queueEvent(NETTCPSOCKET_READABLE);
segundo 0:ac1725ba162c 381 }
segundo 0:ac1725ba162c 382 else
segundo 0:ac1725ba162c 383 {
segundo 0:ac1725ba162c 384 pbuf_cat((pbuf*)m_pReadPbuf, p); //m_pReadPbuf is not empty, tail p to it and drop our ref
segundo 0:ac1725ba162c 385 //No need to queue an event in that case since the read buf has not been processed yet
segundo 0:ac1725ba162c 386 }
segundo 0:ac1725ba162c 387 return ERR_OK;
segundo 0:ac1725ba162c 388 }
segundo 0:ac1725ba162c 389
segundo 0:ac1725ba162c 390
segundo 0:ac1725ba162c 391 void LwipNetTcpSocket::cleanUp() //Flush input buffer
segundo 0:ac1725ba162c 392 {
segundo 0:ac1725ba162c 393 //Ensure that further error won't be followed to this inst (which can be destroyed)
segundo 0:ac1725ba162c 394 if( m_pPcb )
segundo 0:ac1725ba162c 395 {
segundo 0:ac1725ba162c 396 tcp_arg( (tcp_pcb*) m_pPcb, (void*) NULL );
segundo 0:ac1725ba162c 397 tcp_recv( (tcp_pcb*) m_pPcb, NULL );
segundo 0:ac1725ba162c 398 tcp_sent((tcp_pcb*) m_pPcb, NULL );
segundo 0:ac1725ba162c 399 tcp_err( (tcp_pcb*) m_pPcb, NULL );
segundo 0:ac1725ba162c 400 }
segundo 0:ac1725ba162c 401
segundo 0:ac1725ba162c 402 if( m_pReadPbuf )
segundo 0:ac1725ba162c 403 {
segundo 0:ac1725ba162c 404 DBG("Deallocating unread data.\n");
segundo 0:ac1725ba162c 405 pbuf_free((pbuf*)m_pReadPbuf); //Free all unread data
segundo 0:ac1725ba162c 406 m_pReadPbuf = NULL;
segundo 0:ac1725ba162c 407 recv(NULL,0); //Update recv ptr position
segundo 0:ac1725ba162c 408 }
segundo 0:ac1725ba162c 409 }
segundo 0:ac1725ba162c 410
segundo 0:ac1725ba162c 411 // Static callbacks from LwIp
segundo 0:ac1725ba162c 412
segundo 0:ac1725ba162c 413 err_t LwipNetTcpSocket::sAcceptCb(void *arg, struct tcp_pcb *newpcb, err_t err)
segundo 0:ac1725ba162c 414 {
segundo 0:ac1725ba162c 415 LwipNetTcpSocket* pMe = (LwipNetTcpSocket*) arg;
segundo 0:ac1725ba162c 416 return pMe->acceptCb( newpcb, err );
segundo 0:ac1725ba162c 417 }
segundo 0:ac1725ba162c 418
segundo 0:ac1725ba162c 419 err_t LwipNetTcpSocket::sConnectedCb(void *arg, struct tcp_pcb *tpcb, err_t err)
segundo 0:ac1725ba162c 420 {
segundo 0:ac1725ba162c 421 LwipNetTcpSocket* pMe = (LwipNetTcpSocket*) arg;
segundo 0:ac1725ba162c 422 return pMe->connectedCb( tpcb, err );
segundo 0:ac1725ba162c 423 }
segundo 0:ac1725ba162c 424
segundo 0:ac1725ba162c 425 void LwipNetTcpSocket::sErrCb(void *arg, err_t err)
segundo 0:ac1725ba162c 426 {
segundo 0:ac1725ba162c 427 if( !arg )
segundo 0:ac1725ba162c 428 {
segundo 0:ac1725ba162c 429 DBG("NetTcpSocket - Error %d in LwipNetTcpSocket::sErrCb.\n", err);
segundo 0:ac1725ba162c 430 return; //The socket has been destroyed, discard error
segundo 0:ac1725ba162c 431 }
segundo 0:ac1725ba162c 432 LwipNetTcpSocket* pMe = (LwipNetTcpSocket*) arg;
segundo 0:ac1725ba162c 433 return pMe->errCb( err );
segundo 0:ac1725ba162c 434 }
segundo 0:ac1725ba162c 435
segundo 0:ac1725ba162c 436 err_t LwipNetTcpSocket::sSentCb(void *arg, struct tcp_pcb *tpcb, u16_t len)
segundo 0:ac1725ba162c 437 {
segundo 0:ac1725ba162c 438 LwipNetTcpSocket* pMe = (LwipNetTcpSocket*) arg;
segundo 0:ac1725ba162c 439 return pMe->sentCb( tpcb, len );
segundo 0:ac1725ba162c 440 }
segundo 0:ac1725ba162c 441
segundo 0:ac1725ba162c 442 err_t LwipNetTcpSocket::sRecvCb(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
segundo 0:ac1725ba162c 443 {
segundo 0:ac1725ba162c 444 if( tpcb->flags & TF_RXCLOSED )
segundo 0:ac1725ba162c 445 {
segundo 0:ac1725ba162c 446 //The Pcb is in a closing state
segundo 0:ac1725ba162c 447 //Discard that data here since we might have destroyed the corresponding socket object
segundo 0:ac1725ba162c 448 tcp_recved( tpcb, p->tot_len);
segundo 0:ac1725ba162c 449 pbuf_free( p );
segundo 0:ac1725ba162c 450 return ERR_OK;
segundo 0:ac1725ba162c 451 }
segundo 0:ac1725ba162c 452 LwipNetTcpSocket* pMe = (LwipNetTcpSocket*) arg;
segundo 0:ac1725ba162c 453 return pMe->recvCb( tpcb, p, err );
segundo 0:ac1725ba162c 454 }
segundo 0:ac1725ba162c 455
segundo 0:ac1725ba162c 456 #endif