Version of http://mbed.org/cookbook/NetServicesTribute with setting set the same for LPC2368

Dependents:   UDPSocketExample 24LCxx_I2CApp WeatherPlatform_pachube HvZServerLib ... more

Committer:
simon
Date:
Tue Nov 23 14:15:36 2010 +0000
Revision:
0:350011bf8be7
Experimental version for testing UDP

Who changed what in which revision?

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