diff --git a/daemon/src/sip/sipaccount.cpp b/daemon/src/sip/sipaccount.cpp
index fdd463449f0e624cae0ad0f99c1eca0473013fa3..efde26c18c528e5b3c463427eb14ffdaf1bcdacf 100644
--- a/daemon/src/sip/sipaccount.cpp
+++ b/daemon/src/sip/sipaccount.cpp
@@ -38,6 +38,7 @@
 #include <sstream>
 #include <cassert>
 
+
 SIPAccount::SIPAccount(const std::string& accountID)
     : Account(accountID, "SIP")
     , transport_(NULL)
@@ -82,6 +83,7 @@ SIPAccount::SIPAccount(const std::string& accountID)
     , zrtpHelloHash_(true)
     , zrtpNotSuppWarning_(true)
     , registrationStateDetailed_()
+    , keepAliveTimer_()
 {
     link_ = SIPVoIPLink::instance();
 }
@@ -234,9 +236,9 @@ void SIPAccount::serialize(Conf::YamlEmitter *emitter)
         delete node->getValue(REALM);
         delete node;
     }
-}
-
 
+    
+}
 
 void SIPAccount::unserialize(Conf::MappingNode *map)
 {
@@ -567,6 +569,31 @@ void SIPAccount::unregisterVoIPLink()
     }
 }
 
+void SIPAccount::startKeepAliveTimer() {
+    pj_time_val keepAliveDelay_;
+
+    if (isTlsEnabled())
+        return;
+
+    keepAliveTimer_.cb = &SIPAccount::keepAliveRegistrationCb;
+    keepAliveTimer_.user_data = (void *)this; 
+
+    // expiration may no be determined when during the first registration request
+    if(registrationExpire_ == 0) {
+        keepAliveDelay_.sec = 60;
+    }
+    else {
+        keepAliveDelay_.sec = registrationExpire_;
+    }
+    keepAliveDelay_.msec = 0;
+ 
+    reinterpret_cast<SIPVoIPLink *>(link_)->registerKeepAliveTimer(keepAliveTimer_, keepAliveDelay_); 
+}
+
+void SIPAccount::stopKeepAliveTimer() {
+     reinterpret_cast<SIPVoIPLink *>(link_)->cancelKeepAliveTimer(keepAliveTimer_); 
+}
+
 pjsip_ssl_method SIPAccount::sslMethodStringToPjEnum(const std::string& method)
 {
     if (method == "Default")
@@ -745,6 +772,25 @@ std::string SIPAccount::getContactHeader(const std::string& address, const std::
            address + ":" + port + transport + ">";
 }
 
+void SIPAccount::keepAliveRegistrationCb(UNUSED pj_timer_heap_t *th, pj_timer_entry *te) 
+{
+   SIPAccount *sipAccount = reinterpret_cast<SIPAccount *>(te->user_data);
+
+   if (sipAccount->isTlsEnabled())
+       return;
+
+   if(sipAccount->isRegistered()) {
+
+       // send a new register request
+       sipAccount->registerVoIPLink();
+
+       // make sure the current timer is deactivated   
+       sipAccount->stopKeepAliveTimer(); 
+
+       // register a new timer
+       sipAccount->startKeepAliveTimer(); 
+   }
+}
 
 namespace {
 std::string computeMd5HashFromCredential(
diff --git a/daemon/src/sip/sipaccount.h b/daemon/src/sip/sipaccount.h
index 076fe6076c967e381219594d24a8eea01cd103eb..32d5671ddc3b7da07528e45b3f5815361bdff475 100644
--- a/daemon/src/sip/sipaccount.h
+++ b/daemon/src/sip/sipaccount.h
@@ -143,6 +143,19 @@ class SIPAccount : public Account {
          */
         void unregisterVoIPLink();
 
+        /**
+         * Start the keep alive function, once started, the account will be registered periodically
+         * a new REGISTER request is sent bey the client application. The account must be initially
+         * registered for this call to be effective.
+         */
+        void startKeepAliveTimer();
+
+        /**
+         * Stop the keep alive timer. Once canceled, no further registration will be scheduled
+         */
+        void stopKeepAliveTimer();
+          
+
         pjsip_cred_info *getCredInfo() const {
             return cred_;
         }
@@ -174,6 +187,15 @@ class SIPAccount : public Account {
             return registrationExpire_;
         }
 
+        /**
+         * Set the expiration for this account as found in 
+         * the "Expire" sip header or the Contact "expire" param.
+         */
+        void setRegistrationExpire(int expire) {
+            if(expire > 0)
+                registrationExpire_ = expire;
+        }
+
         /**
          * Doubles the Expiration Interval of Contact Addresses.
          */
@@ -188,10 +210,16 @@ class SIPAccount : public Account {
         bool userMatch(const std::string& username) const;
         bool hostnameMatch(const std::string& hostname) const;
 
-        /* Registration flag */
-        bool isRegister() const {
+        /** 
+         * Registration flag 
+	 */
+        bool isRegistered() const {
             return bRegister_;
         }
+
+	/**
+         * Set registration flag
+         */
         void setRegister(bool result) {
             bRegister_ = result;
         }
@@ -410,6 +438,12 @@ class SIPAccount : public Account {
             return zrtpHelloHash_;
         }
 
+        /**
+         * Timer used to periodically send re-register request based
+         * on the "Expire" sip header (or the "expire" Contact parameter)
+         */
+        static void keepAliveRegistrationCb(pj_timer_heap_t *th, pj_timer_entry *te);
+
         pjsip_transport* transport_;
     private:
         NON_COPYABLE(SIPAccount);
@@ -442,9 +476,14 @@ class SIPAccount : public Account {
          */
         static std::string getLoginName();
 
-        // The pjsip client registration information
+        /**
+         * The pjsip client registration information
+	 */
         pjsip_regc *regc_;
-        // To check if the account is registered
+
+        /**
+	 * To check if the account is registered
+         */
         bool bRegister_;
 
         // Network settings
@@ -517,6 +556,17 @@ class SIPAccount : public Account {
         * This is a protocol Code:Description pair.
         */
         std::pair<int, std::string> registrationStateDetailed_;
+       
+        /**
+         * Timer used to regularrly send re-register request based
+         * on the "Expire" sip header (or the "expire" Contact parameter)
+         */ 
+        pj_timer_entry keepAliveTimer_;
+
+        /**
+         * Delay coresponding to a registration interval
+         */
+        // pj_time_val keepAliveDelay_;
 };
 
 #endif
diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp
index cc59163995c5acc63da22704499131dffb7d7aec..e0f00a7df9a3b0fe68f610c6a623a384ef0676cd 100644
--- a/daemon/src/sip/sipvoiplink.cpp
+++ b/daemon/src/sip/sipvoiplink.cpp
@@ -346,6 +346,10 @@ void SIPVoIPLink::sendRegister(Account *a)
     pjsip_transport_dec_ref(account->transport_);
 
     account->setRegistrationInfo(regc);
+
+    // start the periodic registration request based on Expire header
+    // account determines itself if a keep alive is required
+    account->startKeepAliveTimer();
 }
 
 void SIPVoIPLink::sendUnregister(Account *a)
@@ -353,11 +357,14 @@ void SIPVoIPLink::sendUnregister(Account *a)
     SIPAccount *account = dynamic_cast<SIPAccount *>(a);
 
     // This may occurs if account failed to register and is in state INVALID
-    if (!account->isRegister()) {
+    if (!account->isRegistered()) {
         account->setRegistrationState(Unregistered);
         return;
     }
 
+    // Make sure to cancel any ongoing timers before unregister
+    account->stopKeepAliveTimer();
+
     pjsip_regc *regc = account->getRegistrationInfo();
 
     if (!regc)
@@ -374,6 +381,21 @@ void SIPVoIPLink::sendUnregister(Account *a)
     account->setRegister(false);
 }
 
+void SIPVoIPLink::registerKeepAliveTimer(pj_timer_entry& timer, pj_time_val& delay)
+{
+    pj_status_t status;
+
+    status = pjsip_endpt_schedule_timer(endpt_, &timer, &delay); 
+    if(status != PJ_SUCCESS) {
+        ERROR("Could not schedule new timer in pjsip endpoint");
+    }
+}
+
+void SIPVoIPLink::cancelKeepAliveTimer(pj_timer_entry& timer)
+{
+    pjsip_endpt_cancel_timer(endpt_, &timer); 
+}
+
 Call *SIPVoIPLink::newOutgoingCall(const std::string& id, const std::string& toUrl)
 {
     SIPAccount *account = dynamic_cast<SIPAccount *>(Manager::instance().getAccount(Manager::instance().getAccountFromCall(id)));
@@ -1599,6 +1621,8 @@ void registration_cb(struct pjsip_regc_cbparam *param)
         std::pair<int, std::string> details(param->code, state);
         // TODO: there id a race condition for this ressource when closing the application
         account->setRegistrationStateDetailed(details);
+
+        account->setRegistrationExpire(param->expiration);
     }
 
     if (param->status != PJ_SUCCESS) {
@@ -1642,7 +1666,7 @@ void registration_cb(struct pjsip_regc_cbparam *param)
         SIPVoIPLink::instance()->shutdownSipTransport(account);
 
     } else {
-        if (account->isRegister())
+        if (account->isRegistered())
             account->setRegistrationState(Registered);
         else {
             account->setRegistrationState(Unregistered);
diff --git a/daemon/src/sip/sipvoiplink.h b/daemon/src/sip/sipvoiplink.h
index 1c2fceb9bc8fe1f63814dd1cd071e8c1d748e965..665171e1d9e8cf1e3ebc581e11edee5043cafca4 100644
--- a/daemon/src/sip/sipvoiplink.h
+++ b/daemon/src/sip/sipvoiplink.h
@@ -99,6 +99,16 @@ class SIPVoIPLink : public VoIPLink {
          */
         virtual void sendUnregister(Account *a);
 
+        /**
+         * Register a new keepalive registration timer to this endpoint
+         */
+        void registerKeepAliveTimer(pj_timer_entry& timer, pj_time_val& delay);
+
+        /**
+         * Abort currently registered timer
+         */
+        void cancelKeepAliveTimer(pj_timer_entry& timer); 
+
         /**
          * Place a new call
          * @param id  The call identifier