diff --git c/api/easyrtc_int.js w/api/easyrtc_int.js
index 38c987c..f57adad 100644
--- c/api/easyrtc_int.js
+++ w/api/easyrtc_int.js
@@ -61,6 +61,13 @@ var Easyrtc = function() {

     var self = this;

+     // Testing truthy / falsy values with assert/expect
+    function assert(condition, failureMsg) {
+        if (!condition) {
+            throw new Error(failureMsg)
+        }
+    }
+
     function logDebug (message, obj) {
         if (self.debugPrinter) {
             self.debugPrinter(message, obj);
@@ -80,7 +87,7 @@ var Easyrtc = function() {
         return true;
     }

-    /**  
+    /** @private 
     peerConns is a map from caller names to the below object structure
      {  
         pc: RTCPeerConnection - the WebRTC peer connection object
@@ -112,7 +119,6 @@ var Easyrtc = function() {
         callFailureCB: function(errorCode, string) - see the easyrtc.call documentation
         wasAcceptedCB: function(boolean, string) - see the easyrtc.call documentation
      }
-     @private
     */
     var peerConns = {};
     /** @private */
@@ -4088,6 +4094,7 @@ var Easyrtc = function() {
     // TODO split buildPeerConnection it more thant 500 lines
     function buildPeerConnection(otherUser, isInitiator, failureCB, streamNames) {
         var pc;
+        var message;

         // Apply peer config
         var pcConfig = pcConfigToUse || {
@@ -4120,17 +4127,10 @@ var Easyrtc = function() {

         try {

-            // Prevent peerConn override
-            if (peerConns[otherUser]) {
-                var duplicateMsg = "Unable to create duplicate PeerConnection object for peer " + otherUser;
-                logDebug(duplicateMsg);
-                throw Error(duplicateMsg);
-            }
-
             pc = self.createRTCPeerConnection(pcConfig, buildPeerConstraints());

             if (!pc) {
-                var message = "Unable to create PeerConnection object, check your ice configuration(" + JSON.stringify(pcConfig) + ")";
+                message = "Unable to create PeerConnection object, check your ice configuration(" + JSON.stringify(pcConfig) + ")";
                 logDebug(message);
                 throw Error(message);
             }
@@ -4558,7 +4558,6 @@ var Easyrtc = function() {
                                 logDebug("calling connectDataConnection(5002,5001)");
                                 pc.connectDataConnection(5002, 5001);
                             }
-
                         }, function(message) {
                             newPeerConn.pendingAwnser = false;
                             self.showError(self.errCodes.INTERNAL_ERR, "setLocalDescription: " + message);
@@ -4582,40 +4581,38 @@ var Easyrtc = function() {
             var localStream = self.getLocalStream();
             if (!localStream && (self.videoEnabled || self.audioEnabled)) {
                 self.initMediaSource(
-                    function() {
-                        doAnswer(caller, msgData);
-                    },
-                    function(errorCode, error) {
-                        self.showError(self.errCodes.MEDIA_ERR, self.format(self.getConstantString("localMediaError")));
-                    }
-                );
-            }
-        } else {
-            if (useFreshIceEachPeer) {
-                self.getFreshIceConfig(function(succeeded) {
-                    if (succeeded) {
-                        doAnswerBody(caller, msgData, streamNames);
-                    }
-                    else {
-                        self.showError(self.errCodes.CALL_ERR, "Failed to get fresh ice config");
-                    }
-                });
-            }
-            else {
-                doAnswerBody(caller, msgData, streamNames);
+                        function() {
+                            doAnswer(caller, msgData);
+                        },
+                        function(errorCode, error) {
+                            self.showError(self.errCodes.MEDIA_ERR, self.format(self.getConstantString("localMediaError")));
+                        });
+                return;
             }
         }
+        if (useFreshIceEachPeer) {
+            self.getFreshIceConfig(function(succeeded) {
+                if (succeeded) {
+                    doAnswerBody(caller, msgData, streamNames);
+                }
+                else {
+                    self.showError(self.errCodes.CALL_ERR, "Failed to get fresh ice config");
+                }
+            });
+        }
+        else {
+            doAnswerBody(caller, msgData, streamNames);
+        }
     }

     /** @private */
     //
     function callBody(otherUser, callSuccessCB, callFailureCB, wasAcceptedCB, streamNames) {
-        
         acceptancePending[otherUser] = Date.now()
-
         var pc = buildPeerConnection(otherUser, true, callFailureCB, streamNames);
+        var message;
         if (!pc) {
-            var message = "buildPeerConnection failed, call not completed";
+            message = "buildPeerConnection failed, call not completed";
             logDebug(message);
             throw message;
         }
@@ -4629,7 +4626,7 @@ var Easyrtc = function() {
     function initiateSendOffer(otherUser, eventTarget, signalingState) {

         var peerConnObj = peerConns[otherUser];
-        if (!peerConnObj) {
+        if( !peerConnObj ) {
            logDebug("message attempt to send offer for nonexistent peer connection " + otherUser);
            return;
         }
@@ -4839,20 +4836,25 @@ var Easyrtc = function() {
         }
     }

-    /** @private */
-    function hangupBody(otherUser, sendRemoteSignal) {
-
+    /**
+     * Hang up on a particular user or all users.
+     *  @param {String} otherUser - the easyrtcid of the person to hang up on.
+     *  @example
+     *     easyrtc.hangup(someEasyrtcid);
+     */
+    this.hangup = function(otherUser) {
+    
         logDebug("Hanging up on " + otherUser);

         // Has connection (or acceptancePending also)
         if (peerConns[otherUser]) {
             closePeer(otherUser);

-            if (sendRemoteSignal && self.webSocket) {
+            if (self.webSocket) {
                 sendSignalling(otherUser, "hangup", null, function() {
-                    logDebug("signaling hangup succeeds");
+                    logDebug("hangup succeeds");
                 }, function(errorCode, errorText) {
-                    logDebug("signaling hangup failed:" + errorText);
+                    logDebug("hangup failed:" + errorText);
                     self.showError(errorCode, errorText);
                 });
             }
@@ -4865,25 +4867,18 @@ var Easyrtc = function() {
                 self.callCancelled(otherUser, true);
             }

-            if (sendRemoteSignal && self.webSocket) {
-                sendSignalling(otherUser, "reject", null, function() {
-                    logDebug("signaling reject succeeds");
-                }, function(errorCode, errorText) {
-                    logDebug("signaling reject failed:" + errorText);
-                    self.showError(errorCode, errorText);
-                });
+            if (self.webSocket) {
+                sendSignalling(otherUser, "reject", null, null, null);
             }
         }
-    }

-    /**
-     * Hang up on a particular user or all users.
-     *  @param {String} otherUser - the easyrtcid of the person to hang up on.
-     *  @example
-     *     easyrtc.hangup(someEasyrtcid);
-     */
-    this.hangup = function(otherUser) {
-        hangupBody(otherUser, true)
+        /*
+        // TODO deploy assert on critical code paths
+        assert(!queuedMessages.hasOwnProperty(otherUser), "Should not have queuedMessages reference for peer: " + otherUser);
+        assert(!acceptancePending.hasOwnProperty(otherUser), "Should not have acceptancePending reference for peer: " + otherUser);
+        assert(!offersPending.hasOwnProperty(otherUser), "Should not have offersPending reference for peer: " + otherUser);
+        assert(!peerConns.hasOwnProperty(otherUser), "Should not have peerConn reference for peer: " + otherUser);
+        */
     };

     /**
@@ -4894,7 +4889,7 @@ var Easyrtc = function() {
     this.hangupAll = function() {
         for (var otherUser in peerConns) {
             if (peerConns.hasOwnProperty(otherUser)) {
-               hangupBody(otherUser, true)
+                this.hangup(otherUser);
             }
         }
     };
@@ -5003,11 +4998,27 @@ var Easyrtc = function() {
             peerConns[easyrtcId].enableNegotiateListener = true;
             removeStreamFromPeerConnection(stream, peerConns[easyrtcId].pc);
         }
+
     };

     /** @private */
     function onRemoteHangup(otherUser) {
-        hangupBody(otherUser, false)
+
+        logDebug("Saw onRemote hangup event");
+        clearQueuedMessages(otherUser);
+
+        // Has connection or calling user
+        if (peerConns[otherUser]) {
+            closePeer(otherUser);
+        }
+        // Has incoming call pending 
+        else if (offersPending[otherUser]) {
+            delete offersPending[otherUser];
+
+            if (self.callCancelled) {
+                self.callCancelled(otherUser, true);
+            }
+        }
     }

     /** @private */
@@ -5373,11 +5384,6 @@ var Easyrtc = function() {
         pc.addIceCandidate(candidate, iceAddSuccess, iceAddFailure);
     }

-    /** @private */
-    function isPolitePeer(caller) {
-        return caller < self.myEasyrtcid
-    }    
-
     /** @private */
     function flushCachedCandidates(caller) {
         var i;
@@ -5390,17 +5396,8 @@ var Easyrtc = function() {
     }

     /** @private */
-    function processCandidateQueue(caller, msgData) {
-        if (peerConns[caller] && peerConns[caller].pc) {
-            processCandidateBody(caller, msgData);
-        }
-        else {
-            if (typeof queuedMessages[caller] === "undefined") {
-                clearQueuedMessages(caller);
-            }
-
-            queuedMessages[caller].candidates.push(msgData);
-        }
+    function isPolitePeer(caller) {
+        return caller < self.myEasyrtcid
     }

     /** @private */
@@ -5605,6 +5602,21 @@ var Easyrtc = function() {
         flushCachedCandidates(caller);
     }

+    /** @private */
+    function processCandidateQueue(caller, msgData) {
+        if (peerConns[caller] && peerConns[caller].pc) {
+            processCandidateBody(caller, msgData);
+        }
+        else {
+            if (!peerConns[caller]) {
+                queuedMessages[caller] = {
+                    candidates: []
+                };
+            }
+            queuedMessages[caller].candidates.push(msgData);
+        }
+    }
+
     /** @private */
     function onChannelCmd(msg, ackAcceptorFn) {

@@ -5614,6 +5626,12 @@ var Easyrtc = function() {

         logDebug('received message of type ' + msgType);

+
+        if (typeof queuedMessages[caller] === "undefined") {
+            clearQueuedMessages(caller);
+        }
+
+
         switch (msgType) {
             case "sessionData":
                 processSessionData(msgData.sessionData);
