Nicholas Herriot / VodafoneK3770Lib
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PPPIPInterface.cpp Source File

PPPIPInterface.cpp

00001 /* PPPIPInterface.cpp */
00002 /*
00003 Copyright (C) 2012 ARM Limited.
00004 
00005 Permission is hereby granted, free of charge, to any person obtaining a copy of
00006 this software and associated documentation files (the "Software"), to deal in
00007 the Software without restriction, including without limitation the rights to
00008 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
00009 of the Software, and to permit persons to whom the Software is furnished to do
00010 so, subject to the following conditions:
00011 
00012 The above copyright notice and this permission notice shall be included in all
00013 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 THE
00021 SOFTWARE.
00022 */
00023 
00024 #define __DEBUG__ 2 //Maximum verbosity
00025 #ifndef __MODULE__
00026 #define __MODULE__ "PPPIPInterface.cpp"
00027 #endif
00028 
00029 #include "core/fwk.h"
00030 #include "rtos.h"
00031 
00032 #include "PPPIPInterface.h"
00033 
00034 extern "C" {
00035 #include "lwip/ip_addr.h"
00036 #include "lwip/inet.h"
00037 #include "netif/ppp/ppp.h"
00038 }
00039 
00040 PPPIPInterface::PPPIPInterface(IOStream* pStream) : LwIPInterface(), m_linkStatusSphre(1), m_pppErrCode(0), m_pStream(pStream), m_streamAvail(true), m_pppd(-1)
00041 {
00042   m_linkStatusSphre.wait();
00043 }
00044 
00045 /*virtual*/ PPPIPInterface::~PPPIPInterface()
00046 {
00047 
00048 }
00049 
00050 /*virtual*/ int PPPIPInterface::init() //Init PPP-specific stuff, create the right bindings, etc
00051 {
00052   DBG("Initializing LwIP");
00053   LwIPInterface::init(); //Init LwIP, NOT including PPP
00054   DBG("Initializing PPP");
00055   pppInit();
00056   DBG("Done");
00057   return OK;
00058 }
00059 
00060 int PPPIPInterface::setup(const char* user, const char* pw)
00061 {
00062   DBG("Configuring PPP authentication method");
00063   pppSetAuth(PPPAUTHTYPE_ANY, user, pw);
00064   DBG("Done");
00065   return OK;
00066 }
00067 
00068 /*virtual*/ int PPPIPInterface::connect()
00069 {
00070   DBG("Trying to connect with PPP");
00071   m_linkStatusSphre.wait(0);
00072   if((m_pppd != -1) && (m_pppErrCode == 0)) //Already connected
00073   {
00074     return NET_INVALID;
00075   }
00076   int ret = pppOverSerialOpen(this, PPPIPInterface::linkStatusCb, this);
00077   if(ret < 0)
00078   {
00079     switch(ret)
00080     {
00081     case PPPERR_OPEN:
00082     default:
00083       return NET_FULL; //All available resources are already used
00084     }
00085   }
00086   m_pppd = ret; //PPP descriptor
00087   m_linkStatusSphre.wait(); //Block indefinitely; there should be a timeout there
00088   if(m_pppErrCode != PPPERR_NONE)
00089   {
00090     m_pppd = -1;
00091   }
00092   switch(m_pppErrCode)
00093   {
00094   case PPPERR_NONE: //Connected OK
00095     return OK;
00096   case PPPERR_CONNECT: //Connection lost
00097     return NET_INTERRUPTED;
00098   case PPPERR_AUTHFAIL: //Authentication failed
00099     return NET_AUTH;
00100   case PPPERR_PROTOCOL: //Protocol error
00101     return NET_PROTOCOL;
00102   default:
00103     return NET_UNKNOWN;
00104   }
00105 }
00106 
00107 /*virtual*/ int PPPIPInterface::disconnect()
00108 {
00109   int ret = m_linkStatusSphre.wait(0);
00110   if(ret > 0) //Already disconnected?
00111   {
00112     m_pppd = -1; //Discard PPP descriptor
00113     switch(m_pppErrCode)
00114       {
00115       case PPPERR_CONNECT: //Connection terminated
00116       case PPPERR_AUTHFAIL: //Authentication failed
00117       case PPPERR_PROTOCOL: //Protocol error
00118       case PPPERR_USER:
00119         return OK;
00120       default:
00121         return NET_UNKNOWN;
00122       }
00123   }
00124   else
00125   {
00126     if(m_pppd == -1)
00127     {
00128       return NET_INVALID;
00129     }
00130     pppClose(m_pppd);
00131     do
00132     {
00133       m_linkStatusSphre.wait(); //Block indefinitely; there should be a timeout there
00134       DBG("Received PPP err code %d", m_pppErrCode);
00135     } while(m_pppErrCode != PPPERR_USER);
00136     m_pppd = -1; //Discard PPP descriptor
00137   }
00138   return OK;
00139 }
00140 
00141 /*static*/ void PPPIPInterface::linkStatusCb(void *ctx, int errCode, void *arg) //PPP link status
00142 {
00143   PPPIPInterface* pIf = (PPPIPInterface*)ctx;
00144   struct ppp_addrs* addrs = (struct ppp_addrs*) arg;
00145 
00146   switch(errCode)
00147   {
00148   case PPPERR_NONE:
00149     WARN("Connected via PPP.");
00150     DBG("Local IP address: %s", inet_ntoa(addrs->our_ipaddr));
00151     DBG("Netmask: %s", inet_ntoa(addrs->netmask));
00152     DBG("Remote IP address: %s", inet_ntoa(addrs->his_ipaddr));
00153     DBG("Primary DNS: %s", inet_ntoa(addrs->dns1));
00154     DBG("Secondary DNS: %s", inet_ntoa(addrs->dns2));
00155     break;
00156   case PPPERR_CONNECT: //Connection lost
00157     WARN("Connection lost/terminated");
00158     break;
00159   case PPPERR_AUTHFAIL: //Authentication failed
00160     WARN("Authentication failed");
00161     break;
00162   case PPPERR_PROTOCOL: //Protocol error
00163     WARN("Protocol error");
00164     break;
00165   case PPPERR_USER:
00166     WARN("Disconnected by user");
00167     break;
00168   default:
00169     WARN("Unknown error (%d)", errCode);
00170     break;
00171   }
00172 
00173   pIf->m_linkStatusSphre.wait(0); //If previous event has not been handled, "delete" it now
00174   pIf->m_pppErrCode = errCode;
00175   pIf->m_linkStatusSphre.release();
00176 }
00177 
00178 //LwIP PPP implementation
00179 extern "C"
00180 {
00181 
00182 /**
00183  * Writes to the serial device.
00184  *
00185  * @param fd serial device handle
00186  * @param data pointer to data to send
00187  * @param len length (in bytes) of data to send
00188  * @return number of bytes actually sent
00189  *
00190  * @note This function will block until all data can be sent.
00191  */
00192 u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len)
00193 {
00194   DBG("sio_write");
00195   PPPIPInterface* pIf = (PPPIPInterface*)fd;
00196   int ret;
00197   if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further
00198   {
00199     return 0;
00200   }
00201   ret = pIf->m_pStream->write(data, len, osWaitForever); //Blocks until all data is sent or an error happens
00202   if(ret != OK)
00203   {
00204     return 0;
00205   }
00206   return len;
00207 }
00208 
00209 /**
00210  * Reads from the serial device.
00211  *
00212  * @param fd serial device handle
00213  * @param data pointer to data buffer for receiving
00214  * @param len maximum length (in bytes) of data to receive
00215  * @return number of bytes actually received - may be 0 if aborted by sio_read_abort
00216  *
00217  * @note This function will block until data can be received. The blocking
00218  * can be cancelled by calling sio_read_abort().
00219  */
00220 u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len)
00221 {
00222   DBG("sio_read");
00223   PPPIPInterface* pIf = (PPPIPInterface*)fd;
00224   int ret;
00225   size_t readLen;
00226   if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further
00227   {
00228     WARN("EXIT NOT AVAIL");
00229     return 0;
00230   }
00231   ret = pIf->m_pStream->read(data, &readLen, len, osWaitForever); //Blocks until some data is received or an error happens
00232   if(ret != OK)
00233   {
00234     return 0;
00235   }
00236   DBG("ret");
00237   return readLen;
00238 }
00239 
00240 /**
00241  * Aborts a blocking sio_read() call.
00242  *
00243  * @param fd serial device handle
00244  */
00245 void sio_read_abort(sio_fd_t fd)
00246 {
00247   DBG("sio_read_abort");
00248   PPPIPInterface* pIf = (PPPIPInterface*)fd;
00249   if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further
00250   {
00251     return;
00252   }
00253   pIf->m_pStream->abortRead();
00254   DBG("ret");
00255 }
00256 
00257 }