Darran Shepherd
/
AutoIpNetStack
Net stack with AutoIP enabled
Embed:
(wiki syntax)
Show/hide line numbers
lwipNetTcpSocket.cpp
00001 00002 /* 00003 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) 00004 00005 Permission is hereby granted, free of charge, to any person obtaining a copy 00006 of this software and associated documentation files (the "Software"), to deal 00007 in the Software without restriction, including without limitation the rights 00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00009 copies of the Software, and to permit persons to whom the Software is 00010 furnished to do so, subject to the following conditions: 00011 00012 The above copyright notice and this permission notice shall be included in 00013 all copies or substantial portions of the Software. 00014 00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00021 THE SOFTWARE. 00022 */ 00023 00024 #include "lwipNetTcpSocket.h" 00025 #include "lwip/tcp.h" 00026 00027 //#define __DEBUG 00028 #include "dbg/dbg.h" 00029 00030 #include "netCfg.h" 00031 #if NET_LWIP_STACK 00032 00033 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 00034 m_pReadPbuf(NULL) 00035 { 00036 DBG("\r\nNew NetTcpSocket %p\r\n", (void*)this); 00037 if(!m_pPcb) 00038 m_pPcb = tcp_new(); 00039 if(m_pPcb) 00040 { 00041 //Setup callbacks 00042 tcp_arg( (tcp_pcb*) m_pPcb, (void*) this ); //this will be passed to each static callback 00043 00044 tcp_recv( (tcp_pcb*) m_pPcb, LwipNetTcpSocket::sRecvCb ); 00045 tcp_sent((tcp_pcb*) m_pPcb, LwipNetTcpSocket::sSentCb ); 00046 tcp_err( (tcp_pcb*) m_pPcb, LwipNetTcpSocket::sErrCb ); 00047 //Connected callback is defined in connect() 00048 //Accept callback is defined in listen() 00049 DBG("\r\nNetTcpSocket created.\r\n"); 00050 } 00051 } 00052 00053 LwipNetTcpSocket::~LwipNetTcpSocket() 00054 { 00055 /* if(m_pPcb) 00056 tcp_close( (tcp_pcb*) m_pPcb); //Disconnect & free pcb*/ 00057 close(); 00058 } 00059 00060 NetTcpSocketErr LwipNetTcpSocket::bind(const Host& me) 00061 { 00062 if(!m_pPcb) 00063 return NETTCPSOCKET_MEM; //NetTcpSocket was not properly initialised, should destroy it & retry 00064 00065 err_t err = tcp_bind( (tcp_pcb*) m_pPcb, IP_ADDR_ANY, me.getPort()); //IP_ADDR_ANY : Bind the connection to all local addresses 00066 if(err) 00067 return NETTCPSOCKET_INUSE; 00068 00069 return NETTCPSOCKET_OK; 00070 } 00071 00072 NetTcpSocketErr LwipNetTcpSocket::listen() 00073 { 00074 if(!m_pPcb) 00075 return NETTCPSOCKET_MEM; //NetTcpSocket was not properly initialised, should destroy it & retry 00076 /* 00077 From doc/rawapi.txt : 00078 00079 The tcp_listen() function returns a new connection identifier, and 00080 the one passed as an argument to the function will be 00081 deallocated. The reason for this behavior is that less memory is 00082 needed for a connection that is listening, so tcp_listen() will 00083 reclaim the memory needed for the original connection and allocate a 00084 new smaller memory block for the listening connection. 00085 */ 00086 00087 // tcp_pcb* pNewPcb = tcp_listen(m_pPcb); 00088 tcp_pcb* pNewPcb = tcp_listen_with_backlog((tcp_pcb*)m_pPcb, 5); 00089 if( !pNewPcb ) //Not enough memory to create the listening pcb 00090 return NETTCPSOCKET_MEM; 00091 00092 m_pPcb = pNewPcb; 00093 00094 tcp_accept( (tcp_pcb*) m_pPcb, LwipNetTcpSocket::sAcceptCb ); 00095 00096 return NETTCPSOCKET_OK; 00097 } 00098 00099 NetTcpSocketErr LwipNetTcpSocket::connect(const Host& host) 00100 { 00101 if(!m_pPcb) 00102 return NETTCPSOCKET_MEM; //NetTcpSocket was not properly initialised, should destroy it & retry 00103 00104 ip_addr_t ip = host.getIp().getStruct(); 00105 err_t err = tcp_connect( (tcp_pcb*) m_pPcb, &ip, host.getPort(), LwipNetTcpSocket::sConnectedCb ); 00106 00107 if(!err) 00108 return NETTCPSOCKET_MEM; 00109 00110 return NETTCPSOCKET_OK; 00111 } 00112 00113 NetTcpSocketErr LwipNetTcpSocket::accept(Host* pClient, NetTcpSocket** ppNewNetTcpSocket) 00114 { 00115 if( !m_pPcb ) //Pcb doesn't exist (anymore) 00116 return NETTCPSOCKET_MEM; 00117 //Dequeue a connection 00118 //if( m_lpInPcb.empty() ) 00119 if( m_lpInNetTcpSocket.empty() ) 00120 return NETTCPSOCKET_EMPTY; 00121 00122 tcp_accepted( ((tcp_pcb*) m_pPcb) ); //Should fire proper events //WARN: m_pPcb is the GOOD param here (and not pInPcb) 00123 00124 /* tcp_pcb* pInPcb = m_lpInPcb.front(); 00125 m_lpInPcb.pop();*/ 00126 00127 if( (m_lpInNetTcpSocket.front()) == NULL ) 00128 { 00129 m_lpInNetTcpSocket.pop(); 00130 return NETTCPSOCKET_RST; 00131 } 00132 00133 if( (m_lpInNetTcpSocket.front())->m_closed ) 00134 { 00135 Net::releaseTcpSocket(m_lpInNetTcpSocket.front()); 00136 m_lpInNetTcpSocket.pop(); 00137 return NETTCPSOCKET_RST; 00138 } 00139 00140 ip_addr_t* ip = (ip_addr_t*) &( (m_lpInNetTcpSocket.front()->m_pPcb)->remote_ip); 00141 00142 *ppNewNetTcpSocket = m_lpInNetTcpSocket.front(); 00143 *pClient = Host( 00144 IpAddr( 00145 ip 00146 ), 00147 m_lpInNetTcpSocket.front()->m_pPcb->remote_port 00148 ); 00149 m_lpInNetTcpSocket.pop(); 00150 // *pClient = Host( IpAddr(pInPcb->remote_ip), pInPcb->remote_port ); 00151 00152 //Return a new socket 00153 // *ppNewNetTcpSocket = (NetTcpSocket*) new LwipNetTcpSocket(pInPcb); 00154 00155 //tcp_accepted( ((tcp_pcb*) m_pPcb) ); //Should fire proper events //WARN: m_pPcb is the GOOD param here (and not pInPcb) 00156 00157 /* if(*ppNewNetTcpSocket == NULL) 00158 { 00159 DBG("\r\nNot enough mem, socket dropped in LwipNetTcpSocket::accept.\r\n"); 00160 tcp_abort(pInPcb); 00161 }*/ 00162 00163 return NETTCPSOCKET_OK; 00164 } 00165 00166 #define MAX(a,b) (((a)>(b))?(a):(b)) 00167 #define MIN(a,b) (((a)<(b))?(a):(b)) 00168 00169 int /*if < 0 : NetTcpSocketErr*/ LwipNetTcpSocket::send(const char* buf, int len) 00170 { 00171 if( !m_pPcb ) //Pcb doesn't exist (anymore) 00172 return NETTCPSOCKET_MEM; 00173 int outLen = MIN( len, tcp_sndbuf( (tcp_pcb*) m_pPcb) ); 00174 //tcp_sndbuf() returns the number of bytes available in the output queue, so never go above it 00175 err_t err = tcp_write( (tcp_pcb*) m_pPcb, (void*) buf, outLen, TCP_WRITE_FLAG_COPY ); 00176 //Flags are TCP_WRITE_FLAG_COPY & TCP_WRITE_FLAG_MORE (see tcp_out.c) : 00177 //If TCP_WRITE_FLAG_MORE is not set ask client to push buffered data to app 00178 if(err) 00179 { 00180 switch( err ) 00181 { 00182 case ERR_CONN: 00183 return (int) NETTCPSOCKET_SETUP; //Not connected properly 00184 case ERR_ARG: 00185 return (int) NETTCPSOCKET_SETUP; //Wrong args ! (like buf pointing to NULL) 00186 case ERR_MEM: 00187 default: 00188 return (int) NETTCPSOCKET_MEM; //Not enough memory 00189 } 00190 } 00191 return outLen; 00192 } 00193 00194 int /*if < 0 : NetTcpSocketErr*/ LwipNetTcpSocket::recv(char* buf, int len) 00195 { 00196 if( !m_pPcb ) //Pcb doesn't exist (anymore) 00197 return NETTCPSOCKET_MEM; 00198 int inLen = 0; 00199 int cpyLen = 0; 00200 00201 static int rmgLen = 0; 00202 //Contains the remaining len in this pbuf 00203 00204 if( !m_pReadPbuf ) 00205 { 00206 rmgLen = 0; 00207 return 0; 00208 } 00209 00210 if ( !rmgLen ) //We did not know m_pReadPbuf->len last time we called this fn 00211 { 00212 rmgLen = m_pReadPbuf->len; 00213 } 00214 00215 while ( inLen < len ) 00216 { 00217 cpyLen = MIN( (len - inLen), rmgLen ); //Remaining len to copy, remaining len in THIS pbuf 00218 memcpy((void*)buf, (void*)((char*)(m_pReadPbuf->payload) + (m_pReadPbuf->len - rmgLen)), cpyLen); 00219 inLen += cpyLen; 00220 buf += cpyLen; 00221 00222 rmgLen = rmgLen - cpyLen; //Update rmgLen 00223 00224 if( rmgLen > 0 ) 00225 { 00226 //We did not read this pbuf completely, so let's save it's pos & return 00227 break; 00228 } 00229 00230 if(m_pReadPbuf->next) 00231 { 00232 pbuf* pNextPBuf = m_pReadPbuf->next; 00233 m_pReadPbuf->next = NULL; //So that it is not freed as well 00234 //We get the reference to pNextPBuf from m_pReadPbuf 00235 pbuf_free((pbuf*)m_pReadPbuf); 00236 m_pReadPbuf = pNextPBuf; 00237 rmgLen = m_pReadPbuf->len; 00238 } 00239 else 00240 { 00241 pbuf_free((pbuf*)m_pReadPbuf); 00242 m_pReadPbuf = NULL; 00243 rmgLen = 0; 00244 break; //No more data to read 00245 } 00246 00247 } 00248 00249 //tcp_recved(m_pPcb, inLen); //Acknowledge the reception 00250 00251 return inLen; 00252 } 00253 00254 NetTcpSocketErr LwipNetTcpSocket::close() 00255 { 00256 //DBG("\r\nLwipNetTcpSocket::close() : Closing...\r\n"); 00257 00258 if(m_closed) 00259 return NETTCPSOCKET_OK; //Already being closed 00260 m_closed = true; 00261 00262 if( !m_pPcb ) //Pcb doesn't exist (anymore) 00263 return NETTCPSOCKET_MEM; 00264 00265 //Cleanup incoming data 00266 cleanUp(); 00267 00268 if( !!tcp_close( (tcp_pcb*) m_pPcb) ) 00269 { 00270 DBG("\r\nLwipNetTcpSocket::close() could not close properly, abort.\r\n"); 00271 tcp_abort( (tcp_pcb*) m_pPcb); 00272 m_pPcb = NULL; 00273 return NETTCPSOCKET_MEM; 00274 } 00275 00276 DBG("\r\nLwipNetTcpSocket::close() : connection closed successfully.\r\n"); 00277 00278 m_pPcb = NULL; 00279 return NETTCPSOCKET_OK; 00280 } 00281 00282 NetTcpSocketErr LwipNetTcpSocket::poll() 00283 { 00284 NetTcpSocket::flushEvents(); 00285 return NETTCPSOCKET_OK; 00286 } 00287 00288 // Callbacks events 00289 00290 err_t LwipNetTcpSocket::acceptCb(struct tcp_pcb *newpcb, err_t err) 00291 { 00292 if(err) 00293 { 00294 DBG("\r\nError %d in LwipNetTcpSocket::acceptCb.\r\n", err); 00295 return err; 00296 } 00297 //FIXME: MEM Errs 00298 //m_lpInPcb.push(newpcb); //Add connection to the queue 00299 LwipNetTcpSocket* pNewNetTcpSocket = new LwipNetTcpSocket(newpcb); 00300 00301 if(pNewNetTcpSocket == NULL) 00302 { 00303 DBG("\r\nNot enough mem, socket dropped in LwipNetTcpSocket::acceptCb.\r\n"); 00304 tcp_abort(newpcb); 00305 return ERR_ABRT; 00306 } 00307 00308 pNewNetTcpSocket->m_refs++; 00309 m_lpInNetTcpSocket.push( pNewNetTcpSocket ); 00310 00311 // tcp_accepted(newpcb); 00312 // tcp_accepted( m_pPcb ); //Should fire proper events //WARN: m_pPcb is the GOOD param here (and not pInPcb) 00313 queueEvent(NETTCPSOCKET_ACCEPT); 00314 return ERR_OK; 00315 } 00316 00317 err_t LwipNetTcpSocket::connectedCb(struct tcp_pcb *tpcb, err_t err) 00318 { 00319 queueEvent(NETTCPSOCKET_CONNECTED); 00320 return ERR_OK; 00321 } 00322 00323 void LwipNetTcpSocket::errCb(err_t err) 00324 { 00325 DBG("\r\nNetTcpSocket %p - Error %d in LwipNetTcpSocket::errCb.\r\n", (void*)this, err); 00326 //WARN: At this point, m_pPcb has been freed by lwIP 00327 m_pPcb = NULL; 00328 //These errors are fatal, discard all events queued before so that the errors are handled first 00329 discardEvents(); 00330 m_closed = true; 00331 cleanUp(); 00332 if( err == ERR_ABRT) 00333 queueEvent(NETTCPSOCKET_CONABRT); 00334 else //if( err == ERR_RST) 00335 queueEvent(NETTCPSOCKET_CONRST); 00336 } 00337 00338 err_t LwipNetTcpSocket::sentCb(tcp_pcb* tpcb, u16_t len) 00339 { 00340 // DBG("\r\n%d bytes ACKed by host.\r\n", len); 00341 queueEvent(NETTCPSOCKET_WRITEABLE); 00342 return ERR_OK; 00343 } 00344 00345 err_t LwipNetTcpSocket::recvCb(tcp_pcb* tpcb, pbuf *p, err_t err) 00346 { 00347 //Store pbuf ptr 00348 // DBG("\r\nReceive CB with err = %d & len = %d.\r\n", err, p->tot_len); 00349 // tcp_recved( (tcp_pcb*) m_pPcb, p->tot_len); //Acknowledge the reception 00350 00351 if(err) 00352 { 00353 queueEvent(NETTCPSOCKET_ERROR); 00354 return ERR_OK; //FIXME: More robust error handling there 00355 } 00356 else if(!p) 00357 { 00358 DBG("\r\nNetTcpSocket %p - Connection closed by remote host (LwipNetTcpSocket::recvCb).\r\n", (void*)this); 00359 //Buf is NULL, that means that the connection has been closed by remote host 00360 00361 //FIX: 27/05/2010: We do not want to deallocate the socket while some data might still be readable 00362 //REMOVED: close(); 00363 00364 //However we do not want to close the socket yet 00365 00366 queueEvent(NETTCPSOCKET_DISCONNECTED); 00367 return ERR_OK; 00368 } 00369 00370 //We asserted that p is a valid pointer 00371 00372 //New data processing 00373 tcp_recved( tpcb, p->tot_len); //Acknowledge the reception 00374 if(!m_pReadPbuf) 00375 { 00376 m_pReadPbuf = p; 00377 queueEvent(NETTCPSOCKET_READABLE); 00378 } 00379 else 00380 { 00381 pbuf_cat((pbuf*)m_pReadPbuf, p); //m_pReadPbuf is not empty, tail p to it and drop our ref 00382 //No need to queue an event in that case since the read buf has not been processed yet 00383 } 00384 return ERR_OK; 00385 } 00386 00387 00388 void LwipNetTcpSocket::cleanUp() //Flush input buffer 00389 { 00390 //Ensure that further error won't be followed to this inst (which can be destroyed) 00391 if( m_pPcb ) 00392 { 00393 tcp_arg( (tcp_pcb*) m_pPcb, (void*) NULL ); 00394 tcp_recv( (tcp_pcb*) m_pPcb, NULL ); 00395 tcp_sent((tcp_pcb*) m_pPcb, NULL ); 00396 tcp_err( (tcp_pcb*) m_pPcb, NULL ); 00397 } 00398 00399 if( m_pReadPbuf ) 00400 { 00401 DBG("\r\nDeallocating unread data.\r\n"); 00402 pbuf_free((pbuf*)m_pReadPbuf); //Free all unread data 00403 m_pReadPbuf = NULL; 00404 recv(NULL,0); //Update recv ptr position 00405 } 00406 } 00407 00408 // Static callbacks from LwIp 00409 00410 err_t LwipNetTcpSocket::sAcceptCb(void *arg, struct tcp_pcb *newpcb, err_t err) 00411 { 00412 LwipNetTcpSocket* pMe = (LwipNetTcpSocket*) arg; 00413 return pMe->acceptCb( newpcb, err ); 00414 } 00415 00416 err_t LwipNetTcpSocket::sConnectedCb(void *arg, struct tcp_pcb *tpcb, err_t err) 00417 { 00418 LwipNetTcpSocket* pMe = (LwipNetTcpSocket*) arg; 00419 return pMe->connectedCb( tpcb, err ); 00420 } 00421 00422 void LwipNetTcpSocket::sErrCb(void *arg, err_t err) 00423 { 00424 if( !arg ) 00425 { 00426 DBG("\r\nNetTcpSocket - Error %d in LwipNetTcpSocket::sErrCb.\r\n", err); 00427 return; //The socket has been destroyed, discard error 00428 } 00429 LwipNetTcpSocket* pMe = (LwipNetTcpSocket*) arg; 00430 return pMe->errCb( err ); 00431 } 00432 00433 err_t LwipNetTcpSocket::sSentCb(void *arg, struct tcp_pcb *tpcb, u16_t len) 00434 { 00435 LwipNetTcpSocket* pMe = (LwipNetTcpSocket*) arg; 00436 return pMe->sentCb( tpcb, len ); 00437 } 00438 00439 err_t LwipNetTcpSocket::sRecvCb(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) 00440 { 00441 if( tpcb->flags & TF_RXCLOSED ) 00442 { 00443 //The Pcb is in a closing state 00444 //Discard that data here since we might have destroyed the corresponding socket object 00445 tcp_recved( tpcb, p->tot_len); 00446 pbuf_free( p ); 00447 return ERR_OK; 00448 } 00449 LwipNetTcpSocket* pMe = (LwipNetTcpSocket*) arg; 00450 return pMe->recvCb( tpcb, p, err ); 00451 } 00452 00453 #endif
Generated on Tue Jul 12 2022 15:37:04 by 1.7.2