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