Bonjour/Zerconf library

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lwipNetTcpSocket.cpp Source File

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