Index: pjproject/branches/1.0/pjlib/include/pj/os.h
===================================================================
--- pjproject/branches/1.0/pjlib/include/pj/os.h	(revision 2481)
+++ pjproject/branches/1.0/pjlib/include/pj/os.h	(revision 2482)
@@ -395,4 +395,16 @@
 PJ_DECL(pj_status_t) pj_symbianos_set_params(pj_symbianos_params *prm);
 
+/**
+ *  Notify PJLIB that the access point connection has been down or unusable
+ *  and PJLIB should not try to access the Symbian socket API (especially ones
+ *  that send packets). Sending packet when RConnection is reconnected to 
+ *  different access point may cause the WaitForRequest() for the function to 
+ *  block indefinitely.
+ *  
+ *  @param up		If set to PJ_FALSE it will cause PJLIB to not try
+ *  			to access socket API, and error will be returned
+ *  			immediately instead.
+ */
+PJ_DECL(void) pj_symbianos_set_connection_status(pj_bool_t up);
 
 /**
Index: pjproject/branches/1.0/pjlib/src/pj/addr_resolv_symbian.cpp
===================================================================
--- pjproject/branches/1.0/pjlib/src/pj/addr_resolv_symbian.cpp	(revision 2481)
+++ pjproject/branches/1.0/pjlib/src/pj/addr_resolv_symbian.cpp	(revision 2482)
@@ -72,4 +72,7 @@
     PJ_ASSERT_RETURN(name && count && ai, PJ_EINVAL);
 
+    // Return failure if access point is marked as down by app.
+    PJ_SYMBIAN_CHECK_CONNECTION();
+	
     // Get resolver for the specified address family
     RHostResolver &resv = PjSymbianOS::Instance()->GetResolver(af);
Index: pjproject/branches/1.0/pjlib/src/pj/ioqueue_symbian.cpp
===================================================================
--- pjproject/branches/1.0/pjlib/src/pj/ioqueue_symbian.cpp	(revision 2481)
+++ pjproject/branches/1.0/pjlib/src/pj/ioqueue_symbian.cpp	(revision 2482)
@@ -636,4 +636,7 @@
     TRequestStatus reqStatus;
 
+    // Return failure if access point is marked as down by app.
+    PJ_SYMBIAN_CHECK_CONNECTION();
+    
     // Convert address
     status = PjSymbianOS::pj2Addr(*(const pj_sockaddr*)addr, addrlen, 
@@ -748,4 +751,7 @@
     PJ_ASSERT_RETURN((flags & PJ_IOQUEUE_ALWAYS_ASYNC)==0, PJ_EINVAL);
 
+    // Return failure if access point is marked as down by app.
+    PJ_SYMBIAN_CHECK_CONNECTION();
+
     // Clear flag
     flags &= ~PJ_IOQUEUE_ALWAYS_ASYNC;
@@ -786,4 +792,7 @@
     PJ_ASSERT_RETURN((flags & PJ_IOQUEUE_ALWAYS_ASYNC)==0, PJ_EINVAL);
 
+    // Return failure if access point is marked as down by app.
+    PJ_SYMBIAN_CHECK_CONNECTION();
+
     // Convert address
     status = PjSymbianOS::pj2Addr(*(const pj_sockaddr*)addr, addrlen, 
Index: pjproject/branches/1.0/pjlib/src/pj/os_core_symbian.cpp
===================================================================
--- pjproject/branches/1.0/pjlib/src/pj/os_core_symbian.cpp	(revision 2481)
+++ pjproject/branches/1.0/pjlib/src/pj/os_core_symbian.cpp	(revision 2482)
@@ -152,5 +152,6 @@
 
 PjSymbianOS::PjSymbianOS()
-: isSocketServInitialized_(false), isResolverInitialized_(false),
+: isConnectionUp_(false),
+  isSocketServInitialized_(false), isResolverInitialized_(false),
   console_(NULL), selectTimeoutTimer_(NULL),
   appSocketServ_(NULL), appConnection_(NULL), appHostResolver_(NULL),
@@ -230,4 +231,6 @@
     }
 
+    isConnectionUp_ = true;
+    
     return KErrNone;
 
@@ -240,4 +243,6 @@
 void PjSymbianOS::Shutdown()
 {
+    isConnectionUp_ = false;
+    
     if (isResolverInitialized_) {
 		hostResolver_.Close();
@@ -253,13 +258,14 @@
     }
 
-    if (console_) {
-	delete console_;
-	console_ = NULL;
-    }
-
-    if (selectTimeoutTimer_) {
-	delete selectTimeoutTimer_;
-	selectTimeoutTimer_ = NULL;
-    }
+    delete console_;
+    console_ = NULL;
+
+    delete selectTimeoutTimer_;
+    selectTimeoutTimer_ = NULL;
+    
+    appSocketServ_ = NULL;
+    appConnection_ = NULL;
+    appHostResolver_ = NULL;
+    appHostResolver6_ = NULL;
 }
 
@@ -304,4 +310,11 @@
     PjSymbianOS::Instance()->SetParameters(prm);
     return PJ_SUCCESS;
+}
+
+
+/* Set connection status */
+PJ_DEF(void) pj_symbianos_set_connection_status(pj_bool_t up)
+{
+    PjSymbianOS::Instance()->SetConnectionStatus(up != 0);
 }
 
Index: pjproject/branches/1.0/pjlib/src/pj/os_symbian.h
===================================================================
--- pjproject/branches/1.0/pjlib/src/pj/os_symbian.h	(revision 2481)
+++ pjproject/branches/1.0/pjlib/src/pj/os_symbian.h	(revision 2482)
@@ -314,4 +314,19 @@
     }
 
+    //
+    // Return true if the access point connection is up
+    //
+    bool IsConnectionUp() const
+    {
+	return isConnectionUp_;
+    }
+
+    //
+    // Set access point connection status
+    //
+    void SetConnectionStatus(bool up)
+    {
+	isConnectionUp_ = up;
+    }
 
     //
@@ -354,4 +369,6 @@
 
 private:
+    bool isConnectionUp_;
+    
     bool isSocketServInitialized_;
     RSocketServ socketServ_;
@@ -375,4 +392,15 @@
 };
 
+// This macro is used to check the access point connection status and return
+// failure if the AP connection is down or unusable. See the documentation
+// of pj_symbianos_set_connection_status() for more info
+#define PJ_SYMBIAN_CHECK_CONNECTION() \
+    PJ_SYMBIAN_CHECK_CONNECTION2(PJ_ECANCELLED)
+
+#define PJ_SYMBIAN_CHECK_CONNECTION2(retval) \
+    do { \
+	if (!PjSymbianOS::Instance()->IsConnectionUp()) \
+	    return retval; \
+    } while (0);
 
 #endif	/* __OS_SYMBIAN_H__ */
Index: pjproject/branches/1.0/pjlib/src/pj/sock_symbian.cpp
===================================================================
--- pjproject/branches/1.0/pjlib/src/pj/sock_symbian.cpp	(revision 2481)
+++ pjproject/branches/1.0/pjlib/src/pj/sock_symbian.cpp	(revision 2482)
@@ -464,4 +464,7 @@
 	THostName tmpName;
 
+	// Return empty hostname if access point is marked as down by app.
+	PJ_SYMBIAN_CHECK_CONNECTION2(&hostname);
+
 	resv.GetHostName(tmpName, reqStatus);
 	User::WaitForRequest(reqStatus);
@@ -489,4 +492,7 @@
     PJ_ASSERT_RETURN(p_sock!=NULL, PJ_EINVAL);
 
+    // Return failure if access point is marked as down by app.
+    PJ_SYMBIAN_CHECK_CONNECTION();
+    
     /* Set proto if none is specified. */
     if (proto == 0) {
@@ -643,4 +649,7 @@
     PJ_ASSERT_RETURN(sock && buf && len, PJ_EINVAL);
 
+    // Return failure if access point is marked as down by app.
+    PJ_SYMBIAN_CHECK_CONNECTION();
+    
     CPjSocket *pjSock = (CPjSocket*)sock;
     RSocket &rSock = pjSock->Socket();
@@ -679,4 +688,7 @@
     PJ_ASSERT_RETURN(sock && buf && len, PJ_EINVAL);
 
+    // Return failure if access point is marked as down by app.
+    PJ_SYMBIAN_CHECK_CONNECTION();
+    
     CPjSocket *pjSock = (CPjSocket*)sock;
     RSocket &rSock = pjSock->Socket();
@@ -717,4 +729,7 @@
     PJ_ASSERT_RETURN(sock && buf && len, PJ_EINVAL);
     PJ_ASSERT_RETURN(*len > 0, PJ_EINVAL);
+
+    // Return failure if access point is marked as down by app.
+    PJ_SYMBIAN_CHECK_CONNECTION();
 
     CPjSocket *pjSock = (CPjSocket*)sock;
@@ -771,4 +786,7 @@
     PJ_ASSERT_RETURN(*len > 0, PJ_EINVAL);
     PJ_ASSERT_RETURN(*fromlen >= (int)sizeof(pj_sockaddr_in), PJ_EINVAL);
+
+    // Return failure if access point is marked as down by app.
+    PJ_SYMBIAN_CHECK_CONNECTION();
 
     CPjSocket *pjSock = (CPjSocket*)sock;
@@ -869,4 +887,7 @@
 		     PJ_EINVAL);
 
+    // Return failure if access point is marked as down by app.
+    PJ_SYMBIAN_CHECK_CONNECTION();
+    
     CPjSocket *pjSock = (CPjSocket*)sock;
     RSocket &rSock = pjSock->Socket();
Index: pjproject/branches/1.0/pjsip-apps/src/symbian_ua/ua.cpp
===================================================================
--- pjproject/branches/1.0/pjsip-apps/src/symbian_ua/ua.cpp	(revision 2481)
+++ pjproject/branches/1.0/pjsip-apps/src/symbian_ua/ua.cpp	(revision 2482)
@@ -442,4 +442,5 @@
 public:
     ConsoleUI(CConsoleBase *con);
+    ~ConsoleUI();
 
     // Run console UI
@@ -467,4 +468,9 @@
 }
 
+ConsoleUI::~ConsoleUI() 
+{
+    Stop();
+}
+
 // Run console UI
 void ConsoleUI::Run() 
@@ -477,5 +483,5 @@
 void ConsoleUI::Stop() 
 {
-    DoCancel();
+    Cancel();
 }
 
@@ -731,4 +737,94 @@
 
 
+// Class CConnMon to monitor network connection (RConnection). Whenever
+// the connection is down, it will notify PJLIB and restart PJSUA-LIB.
+class CConnMon : public CActive {
+public:
+    static CConnMon* NewL(RConnection &conn, RSocketServ &sserver) {
+	CConnMon *self = new (ELeave) CConnMon(conn, sserver);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+    }
+    
+    void Start() {
+	conn_.ProgressNotification(nif_progress_, iStatus);
+	SetActive();
+    }
+    
+    void Stop() {
+	Cancel();
+    }
+    
+    ~CConnMon() { Stop(); }
+    
+private:
+    CConnMon(RConnection &conn, RSocketServ &sserver) : 
+	CActive(EPriorityHigh), 
+	conn_(conn), 
+	sserver_(sserver)
+    {
+	CActiveScheduler::Add(this);
+    }
+    
+    void ConstructL() {}
+
+    void DoCancel() {
+	conn_.CancelProgressNotification();
+    }
+
+    void RunL() {
+	int stage = nif_progress_().iStage;
+	
+	if (stage == KLinkLayerClosed) {
+	    pj_status_t status;
+	    TInt err;
+
+	    // Tell pjlib that connection is down.
+	    pj_symbianos_set_connection_status(PJ_FALSE);
+	    
+	    PJ_LOG(3, (THIS_FILE, "RConnection closed, restarting PJSUA.."));
+	    
+	    // Destroy pjsua
+	    pjsua_destroy();
+	    PJ_LOG(3, (THIS_FILE, "PJSUA destroyed."));
+
+	    // Reopen the connection
+	    err = conn_.Open(sserver_);
+	    if (err == KErrNone)
+		err = conn_.Start();
+	    if (err != KErrNone) {
+		CActiveScheduler::Stop();
+		return;
+	    }
+
+	    // Reinit Symbian OS param before pj_init()
+	    pj_symbianos_params sym_params;
+	    pj_bzero(&sym_params, sizeof(sym_params));
+	    sym_params.rsocketserv = &sserver_;
+	    sym_params.rconnection = &conn_;
+	    pj_symbianos_set_params(&sym_params);
+
+	    // Reinit pjsua
+	    status = app_startup();
+	    if (status != PJ_SUCCESS) {
+		pjsua_perror(THIS_FILE, "app_startup() error", status);
+		CActiveScheduler::Stop();
+		return;
+	    }
+	    
+	    PJ_LOG(3, (THIS_FILE, "PJSUA restarted."));
+	    PrintMenu();
+	}
+	
+	Start();
+    }
+    
+    RConnection& conn_;
+    RSocketServ& sserver_;
+    TNifProgressBuf nif_progress_;
+};
+
 ////////////////////////////////////////////////////////////////////////////
 int ua_main() 
@@ -773,4 +869,5 @@
     }
 
+    
     // Run the UI
     ConsoleUI *con = new ConsoleUI(console);
@@ -779,6 +876,11 @@
     PrintMenu();
 
+    // Init & start connection monitor
+    CConnMon *connmon = CConnMon::NewL(aConn, aSocketServer);
+    connmon->Start();
+
     CActiveScheduler::Start();
     
+    delete connmon;
     delete con;
 
Index: pjproject/branches/1.0/pjsip/src/pjsua-lib/pjsua_core.c
===================================================================
--- pjproject/branches/1.0/pjsip/src/pjsua-lib/pjsua_core.c	(revision 2481)
+++ pjproject/branches/1.0/pjsip/src/pjsua-lib/pjsua_core.c	(revision 2482)
@@ -836,6 +836,8 @@
 
     do {
-	while (pjsua_handle_events(10) > 0)
-	    ;
+	int i;
+	i = msec / 10;
+	while (pjsua_handle_events(10) > 0 && i > 0)
+	    --i;
 	pj_gettimeofday(&now);
     } while (PJ_TIME_VAL_LT(now, timeout));
