Changes between Version 10 and Version 11 of Symbian_AP_Reconnection


Ignore:
Timestamp:
Mar 2, 2009 3:34:41 PM (10 years ago)
Author:
bennylp
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Symbian_AP_Reconnection

    v10 v11  
    9898[[BR]] 
    9999 
    100 == Symbian specific issues == #sym 
    101  
    102 === Socket call get stuck after reconnecting to different access point (AP) === #symstk1 
    103  
    104  '''Symptom:''' :: 
    105  The library gets stuck in {{{pjsua_destroy()}}} when the application tries to destroy the stack when it detects that the AP connection is down.  
    106  
    107 This is a problem with the socket in general and not PJSIP. Below are steps to reproduce with a plain UDP socket: 
    108  1. Create RConnection, call Start() to connect to AP 
    109  2. Create UDP socket, call !SendTo() to send a packet 
    110  3. Disconnect the AP (Menu -> Connectivity -> Conn. mgr. -> Active data connections -> (highlight the AP) -> Options (menu) -> Disconnect). 
    111  4. Call udp.!SendTo() again 
    112  5. AP selection dialog appears, select different AP 
    113  6. !WaitForRequest() to the udp.!SendTo() operation now '''will get stuck for 1-2 minutes''' before ''tcpip6_error_NoRoute'' error (-5105) is returned. 
    114  7. Now if you call udp.!SendTo() again, now !WaitForRequest() will get stuck indefinitely 
    115  
    116 The problem above does not occur if: 
    117  - the user selects the same AP. In this case the udp.!SendTo() should complete successfully 
    118  - the user cancels the AP selection dialog. In this case the udp.!SendTo() will fail immediately with KErrCancel without blocking the application. 
    119  - the socket is closed and re-opened. In this case the udp.!SendTo() should complete successfully 
    120  
    121 As additional info: 
    122  - the problem still persists even if the RConnection is restarted (RConnection.Start() is called to select new AP) in between step 3 and 4 above. 
    123  
    124  
    125 Currently we don't have a solution for this, except to only use one AP (perhaps to select the AP when PJSIP is started and lock the RConnection that is assigned to PJLIB to this AP). 
    126  
     100== Symbian specific solution == #sym 
     101 
     102In Symbian, the {{{RConnection.ProgressNotification()}}} method can be used to register an Active Object to be run when the connection status has changed. Below is a sample code taken from {{{symbian_ua\ua.cpp}}} file to restart PJSIP when the connection is down. 
     103 
     104 {{{ 
     105class CConnMon : public CActive { 
     106public: 
     107    static CConnMon* NewL(RConnection &conn, RSocketServ &sserver) { 
     108        CConnMon *self = new (ELeave) CConnMon(conn, sserver); 
     109        CleanupStack::PushL(self); 
     110        self->ConstructL(); 
     111        CleanupStack::Pop(self); 
     112        return self; 
     113    } 
     114     
     115    void Start() { 
     116        conn_.ProgressNotification(nif_progress_, iStatus); 
     117        SetActive(); 
     118    } 
     119     
     120    void Stop() { 
     121        Cancel(); 
     122    } 
     123     
     124    ~CConnMon() { Stop(); } 
     125     
     126private: 
     127    CConnMon(RConnection &conn, RSocketServ &sserver) :  
     128        CActive(EPriorityHigh),  
     129        conn_(conn),  
     130        sserver_(sserver) 
     131    { 
     132        CActiveScheduler::Add(this); 
     133    } 
     134     
     135    void ConstructL() {} 
     136 
     137    void DoCancel() { 
     138        conn_.CancelProgressNotification(); 
     139    } 
     140 
     141    void RunL() { 
     142        if (nif_progress_().iStage == KLinkLayerClosed) { 
     143            pj_status_t status; 
     144            TInt err; 
     145 
     146            // Tell pjlib the connection has been down. 
     147            pj_symbianos_set_connection_status(PJ_FALSE); 
     148             
     149            PJ_LOG(3, (THIS_FILE, "RConnection closed, restarting PJSUA..")); 
     150             
     151            // Destroy pjsua 
     152            pjsua_destroy(); 
     153            PJ_LOG(3, (THIS_FILE, "PJSUA destroyed.")); 
     154 
     155            // Reopen the connection 
     156            err = conn_.Open(sserver_); 
     157            if (err == KErrNone) 
     158                err = conn_.Start(); 
     159            if (err != KErrNone) { 
     160                CActiveScheduler::Stop(); 
     161                return; 
     162            } 
     163 
     164            // Reinit Symbian OS param before pj_init() 
     165            pj_symbianos_params sym_params; 
     166            pj_bzero(&sym_params, sizeof(sym_params)); 
     167            sym_params.rsocketserv = &sserver_; 
     168            sym_params.rconnection = &conn_; 
     169            pj_symbianos_set_params(&sym_params); 
     170 
     171            // Reinit pjsua 
     172            status = app_startup(); 
     173            if (status != PJ_SUCCESS) { 
     174                pjsua_perror(THIS_FILE, "app_startup() error", status); 
     175                CActiveScheduler::Stop(); 
     176                return; 
     177            } 
     178 
     179             
     180            PJ_LOG(3, (THIS_FILE, "PJSUA restarted.")); 
     181            PrintMenu(); 
     182        } 
     183         
     184        Start(); 
     185    } 
     186     
     187private: 
     188    RConnection& conn_; 
     189    RSocketServ& sserver_; 
     190    TNifProgressBuf nif_progress_; 
     191}; 
     192 
     193What the code in {{{RunL()}}} above does is it shuts down PJSIP when the connection is down, ask user to reconnect by showing up the access point dialog, and (re)start the application. 
     194 
     195The '''{{{pj_symbianos_set_connection_status()}}}''' API was added in PJSIP version 1.0.2/1.1. This function is used to tell PJLIB that it should not access any socket calls anymore since the connection has been down. Without this function, Symbian will pop up the access point selection dialog again in {{{pjsua_destroy()}}}, and if the user selects different access point then it will cause the socket to block indefinitely in {{{WaitForRequest()}}}. 
     196 
     197 }}} 
    127198 
    128199