Example program with HTTPServer and sensor data streaming over TCPSockets, using Donatien Garnier's Net APIs and services code on top of LWIP. Files StreamServer.h and .cpp encapsulate streaming over TCPSockets. Broadcast is done by sendToAll(), and all incoming data is echoed back to the client. Echo code can be replaced with some remote control of the streaming interface. See main() that shows how to periodically send some data to all subscribed clients. To subscribe, a client should open a socket at <mbed_ip> port 123. I used few lines in TCL code to set up a quick sink for the data. HTTP files are served on port 80 concurrently to the streaming.

Dependencies:   mbed

Committer:
iva2k
Date:
Mon Jun 14 03:24:33 2010 +0000
Revision:
1:3ee499525aa5
Parent:
0:e614f7875b60

        

Who changed what in which revision?

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