summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNanang Izzuddin <nanang@teluu.com>2009-03-02 15:48:45 +0000
committerNanang Izzuddin <nanang@teluu.com>2009-03-02 15:48:45 +0000
commitc205201320f80d9e25e554566da5b7f11203f871 (patch)
tree9c36ccb99099beae87670633c72e63358c95df80
parent33e9dc9f2613a86b0fcfea7d669d1b83934d45fd (diff)
Ticket #732:
- Added new Symbian specific API in PJLIB, pj_symbianos_set_connection_status(), to let PJLIB knows the connection status. - Added connection status checks before Symbian socket operations. - Added loop limiter in Symbian busy_sleep() to avoid the possibility of infinite loop. - Added sample of connection monitor in Symbian sample application (ua.cpp). git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2481 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjlib/include/pj/os.h12
-rw-r--r--pjlib/src/pj/addr_resolv_symbian.cpp3
-rw-r--r--pjlib/src/pj/ioqueue_symbian.cpp9
-rw-r--r--pjlib/src/pj/os_core_symbian.cpp31
-rw-r--r--pjlib/src/pj/os_symbian.h28
-rw-r--r--pjlib/src/pj/sock_symbian.cpp21
-rw-r--r--pjsip-apps/src/symbian_ua/ua.cpp104
-rw-r--r--pjsip/src/pjsua-lib/pjsua_core.c6
8 files changed, 202 insertions, 12 deletions
diff --git a/pjlib/include/pj/os.h b/pjlib/include/pj/os.h
index 0bd18638..4a5a77f8 100644
--- a/pjlib/include/pj/os.h
+++ b/pjlib/include/pj/os.h
@@ -394,6 +394,18 @@ typedef struct pj_symbianos_params
*/
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);
/**
* @}
diff --git a/pjlib/src/pj/addr_resolv_symbian.cpp b/pjlib/src/pj/addr_resolv_symbian.cpp
index cfd8aa5d..fbca1085 100644
--- a/pjlib/src/pj/addr_resolv_symbian.cpp
+++ b/pjlib/src/pj/addr_resolv_symbian.cpp
@@ -71,6 +71,9 @@ static pj_status_t getaddrinfo_by_af(int af, const pj_str_t *name,
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);
diff --git a/pjlib/src/pj/ioqueue_symbian.cpp b/pjlib/src/pj/ioqueue_symbian.cpp
index ba4092b9..ee6d7e0d 100644
--- a/pjlib/src/pj/ioqueue_symbian.cpp
+++ b/pjlib/src/pj/ioqueue_symbian.cpp
@@ -635,6 +635,9 @@ PJ_DEF(pj_status_t) pj_ioqueue_connect( pj_ioqueue_key_t *key,
TInetAddr inetAddr;
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,
inetAddr);
@@ -747,6 +750,9 @@ PJ_DEF(pj_status_t) pj_ioqueue_send( pj_ioqueue_key_t *key,
// Forcing pending operation is not supported.
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;
@@ -785,6 +791,9 @@ PJ_DEF(pj_status_t) pj_ioqueue_sendto( pj_ioqueue_key_t *key,
// Forcing pending operation is not supported.
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,
inetAddr);
diff --git a/pjlib/src/pj/os_core_symbian.cpp b/pjlib/src/pj/os_core_symbian.cpp
index 5fbf3d47..983ce88a 100644
--- a/pjlib/src/pj/os_core_symbian.cpp
+++ b/pjlib/src/pj/os_core_symbian.cpp
@@ -151,7 +151,8 @@ TInt CPjTimeoutTimer::RunError(TInt aError)
//
PjSymbianOS::PjSymbianOS()
-: isSocketServInitialized_(false), isResolverInitialized_(false),
+: isConnectionUp_(false),
+ isSocketServInitialized_(false), isResolverInitialized_(false),
console_(NULL), selectTimeoutTimer_(NULL),
appSocketServ_(NULL), appConnection_(NULL), appHostResolver_(NULL),
appHostResolver6_(NULL)
@@ -229,6 +230,8 @@ TInt PjSymbianOS::Initialize()
isResolverInitialized_ = true;
}
+ isConnectionUp_ = true;
+
return KErrNone;
on_error:
@@ -239,6 +242,8 @@ on_error:
// Shutdown
void PjSymbianOS::Shutdown()
{
+ isConnectionUp_ = false;
+
if (isResolverInitialized_) {
hostResolver_.Close();
#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6!=0
@@ -252,15 +257,16 @@ void PjSymbianOS::Shutdown()
isSocketServInitialized_ = false;
}
- if (console_) {
- delete console_;
- console_ = NULL;
- }
+ delete console_;
+ console_ = NULL;
- if (selectTimeoutTimer_) {
- delete selectTimeoutTimer_;
- selectTimeoutTimer_ = NULL;
- }
+ delete selectTimeoutTimer_;
+ selectTimeoutTimer_ = NULL;
+
+ appSocketServ_ = NULL;
+ appConnection_ = NULL;
+ appHostResolver_ = NULL;
+ appHostResolver6_ = NULL;
}
// Convert to Unicode
@@ -306,6 +312,13 @@ PJ_DEF(pj_status_t) pj_symbianos_set_params(pj_symbianos_params *prm)
}
+/* Set connection status */
+PJ_DEF(void) pj_symbianos_set_connection_status(pj_bool_t up)
+{
+ PjSymbianOS::Instance()->SetConnectionStatus(up != 0);
+}
+
+
/*
* pj_init(void).
* Init PJLIB!
diff --git a/pjlib/src/pj/os_symbian.h b/pjlib/src/pj/os_symbian.h
index 74ae7f0c..3497e7af 100644
--- a/pjlib/src/pj/os_symbian.h
+++ b/pjlib/src/pj/os_symbian.h
@@ -313,6 +313,21 @@ public:
}
}
+ //
+ // 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;
+ }
//
// Unicode Converter
@@ -353,6 +368,8 @@ public:
}
private:
+ bool isConnectionUp_;
+
bool isSocketServInitialized_;
RSocketServ socketServ_;
@@ -374,6 +391,17 @@ private:
PjSymbianOS();
};
+// 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__ */
diff --git a/pjlib/src/pj/sock_symbian.cpp b/pjlib/src/pj/sock_symbian.cpp
index a1bd0a30..a0ca80e0 100644
--- a/pjlib/src/pj/sock_symbian.cpp
+++ b/pjlib/src/pj/sock_symbian.cpp
@@ -463,6 +463,9 @@ PJ_DEF(const pj_str_t*) pj_gethostname(void)
TRequestStatus reqStatus;
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);
@@ -488,6 +491,9 @@ PJ_DEF(pj_status_t) pj_sock_socket(int af,
/* Sanity checks. */
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) {
if (type == pj_SOCK_STREAM())
@@ -642,6 +648,9 @@ PJ_DEF(pj_status_t) pj_sock_send(pj_sock_t sock,
PJ_CHECK_STACK();
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();
@@ -678,6 +687,9 @@ PJ_DEF(pj_status_t) pj_sock_sendto(pj_sock_t sock,
PJ_CHECK_STACK();
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,6 +729,9 @@ PJ_DEF(pj_status_t) pj_sock_recv(pj_sock_t sock,
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;
RSocket &rSock = pjSock->Socket();
@@ -771,6 +786,9 @@ PJ_DEF(pj_status_t) pj_sock_recvfrom(pj_sock_t sock,
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;
RSocket &rSock = pjSock->Socket();
@@ -868,6 +886,9 @@ PJ_DEF(pj_status_t) pj_sock_connect( pj_sock_t sock,
PJ_ASSERT_RETURN(((pj_sockaddr*)addr)->addr.sa_family == PJ_AF_INET,
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();
diff --git a/pjsip-apps/src/symbian_ua/ua.cpp b/pjsip-apps/src/symbian_ua/ua.cpp
index 442b0521..11adb154 100644
--- a/pjsip-apps/src/symbian_ua/ua.cpp
+++ b/pjsip-apps/src/symbian_ua/ua.cpp
@@ -441,6 +441,7 @@ class ConsoleUI : public CActive
{
public:
ConsoleUI(CConsoleBase *con);
+ ~ConsoleUI();
// Run console UI
void Run();
@@ -466,6 +467,11 @@ ConsoleUI::ConsoleUI(CConsoleBase *con)
CActiveScheduler::Add(this);
}
+ConsoleUI::~ConsoleUI()
+{
+ Stop();
+}
+
// Run console UI
void ConsoleUI::Run()
{
@@ -476,7 +482,7 @@ void ConsoleUI::Run()
// Stop console UI
void ConsoleUI::Stop()
{
- DoCancel();
+ Cancel();
}
// Cancel asynchronous read.
@@ -730,6 +736,96 @@ static void SelectIAP()
#endif
+// 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()
{
@@ -772,14 +868,20 @@ int ua_main()
return status;
}
+
// Run the UI
ConsoleUI *con = new ConsoleUI(console);
con->Run();
PrintMenu();
+ // Init & start connection monitor
+ CConnMon *connmon = CConnMon::NewL(aConn, aSocketServer);
+ connmon->Start();
+
CActiveScheduler::Start();
+ delete connmon;
delete con;
// Dump memory statistics
diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c
index b59fe26e..4b7c4baa 100644
--- a/pjsip/src/pjsua-lib/pjsua_core.c
+++ b/pjsip/src/pjsua-lib/pjsua_core.c
@@ -835,8 +835,10 @@ static void busy_sleep(unsigned msec)
pj_time_val_normalize(&timeout);
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));
}