Example self-announcing webserver which controls a servo through a smallHTML userinterface.

Dependencies:   mbed

Committer:
dirkx
Date:
Sat Aug 14 15:56:01 2010 +0000
Revision:
0:a259777c45a3

        

Who changed what in which revision?

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