private void removePeerFromRoster(string peerServerId)
        {
            Debug.WriteLine("removePeerFromRoster " + peerServerId);

            var addr = Symple.parseAddress(peerServerId);

            Debug.WriteLine("addr " + addr);

            peerServerId = (string)addr["id"] ?? peerServerId;

            if (_roster.ContainsKey(peerServerId))
            {
                var peer           = _roster[peerServerId];
                int peerLocalIntId = peer.localIntId;

                _roster.Remove(peerServerId);
                _localIntIdsToServerIds.Remove(peerLocalIntId);

                RaiseOnPeerDisconnected(peerLocalIntId);
            }
            else
            {
                Debug.WriteLine("could not find peerServerId " + peerServerId + " in roster");
            }
        }
        // send a message to the given peer
        // m = JSON object
        // to = either a string or a JSON object to build an address from
        public void send(JObject m, JToken to = null)
        {
            Debug.WriteLine("SympleSignaller:send: " + m + " " + to);

            if (!IsConnected())
            {
                throw new Exception("cannot send messages while offline"); // TODO: add to pending queue?
            }

            if (m.Type != JTokenType.Object)
            {
                throw new Exception("message must be an object");
            }

            if (m["type"].Type != JTokenType.String)
            {
                m["type"] = "message";
            }

            if (m["id"] == null)
            {
                m["id"] = Symple.randomString(8);
            }

            if (to != null)
            {
                m["to"] = to;
            }

            if (m["to"] != null && m["to"].Type == JTokenType.Object)
            {
                JObject mToObj = (JObject)m["to"];
                m["to"] = Symple.buildAddress(mToObj);
            }

            if (m["to"] != null && m["to"].Type != JTokenType.String)
            {
                throw new Exception("message 'to' attribute must be an address string");
            }

            m["from"] = buildAddress(_myPeerData);

            if (m["from"] == m["to"])
            {
                throw new Exception("message sender cannot match the recipient");
            }

            Messenger.Broadcast(SympleLog.LogTrace, "symple:client: sending" + m);

            _socket.Send(m);
        }
        private void sendPresence(JObject p)
        {
            p = p ?? new JObject();
            if (p["data"] != null)
            {
                JObject pDataObj = (JObject)p["data"];
                p["data"] = Symple.merge(peerDataToJObject(_myPeerData), pDataObj);
            }
            else
            {
                p["data"] = peerDataToJObject(_myPeerData);
            }

            p["type"] = "presence";

            this.send(p);
        }
 private string buildAddress(PeerData pd)
 {
     return(Symple.buildAddress(peerDataToJObject(pd)));
 }
        private Dictionary <int, string> _localIntIdsToServerIds; // maps local int ids to server ids


        private void SignallerOnMessage(string mType, JObject m)
        {
            Debug.WriteLine("SignallerOnMessage " + mType + " " + m);

            // here we process what the webrtccontext would normally do when a new message comes in.
            // so we adjust the message and pass it on to the Conductor.

            string fromServerId;

            var mFromObj = m["from"] as JObject;

            if (mFromObj != null)
            {
                fromServerId = (string)mFromObj["id"];
            }
            else
            {
                fromServerId = (string)m["from"]; // string instead of json object
            }

            JObject parsedAddress = Symple.parseAddress(fromServerId); // handle case where "from" is name|id

            fromServerId = (string)parsedAddress["id"] ?? fromServerId;


            if (_roster.ContainsKey(fromServerId))
            {
                PeerData fromPd         = _roster[fromServerId];
                int      fromLocalIntId = fromPd.localIntId;

                if (m["offer"] != null)
                {
                    Debug.WriteLine("incoming offer message");

                    JObject messageForConductor = (JObject)m["offer"];

                    RaiseOnMessageFromPeer(fromLocalIntId, messageForConductor.ToString(Formatting.None));
                }
                else if (m["answer"] != null)
                {
                    Debug.WriteLine("incoming answer message");

                    JObject messageForConductor = (JObject)m["answer"];

                    RaiseOnMessageFromPeer(fromLocalIntId, messageForConductor.ToString(Formatting.None));
                }
                else if (m["candidate"] != null)
                {
                    Debug.WriteLine("incoming candidate message");

                    JObject messageForConductor = (JObject)m["candidate"];

                    RaiseOnMessageFromPeer(fromLocalIntId, messageForConductor.ToString(Formatting.None));
                }
                else if (mType == "presence")
                {
                    // the presence messages are handled earlier in the signalling code, so at this point, do nothing with them.
                }
                else if (m["message"] != null)
                {
                    JObject messageForConductor = m; // send the entire raw message! the "message" format will route it correctly

                    RaiseOnMessageFromPeer(fromLocalIntId, messageForConductor.ToString(Formatting.None));
                }
                else
                {
                    // the content of the message is unrecognized by the signaller
                    Debug.WriteLine("TODO: incoming misc message of type " + m["type"]);
                }
            }
            else
            {
                Debug.WriteLine("received message from unknown sender " + fromServerId);
            }
        }
        private void SocketOnMessage(object msg)
        {
            Messenger.Broadcast(SympleLog.LogTrace, "SocketOnMessage: " + msg);

            JObject m = (JObject)msg;

            string mType = (string)m["type"];

            switch (mType)
            {
            case "message":
                break;

            case "command":
                break;

            case "event":
                break;

            case "presence":

                JObject remotePeerData = (JObject)m["data"];     // data about another peer that has been updated or removed

                bool remotePeerOnline = (bool)remotePeerData["online"];

                if (remotePeerOnline)
                {
                    addOrUpdatePeerToRoster(remotePeerData);
                }
                else
                {
                    string remotePeerServerId = (string)remotePeerData["id"];
                    removePeerFromRoster(remotePeerServerId);
                }

                if (m["probe"] != null && (bool)m["probe"] == true)
                {
                    JObject presenceTo = new JObject();
                    presenceTo["to"] = Symple.parseAddress(m["from"].ToString())["id"];

                    this.sendPresence(presenceTo);
                }
                break;

            default:
                m["type"] = m["type"] ?? "message";
                break;
            }

            if (m["from"].Type != JTokenType.String)
            {
                Messenger.Broadcast(SympleLog.LogError, "symple:client: invalid sender address: " + m);
                return;
            }

            // replace the from attribute with the full peer object.
            // this will only work for peer messages, not server messages.

            string mFrom = (string)m["from"];

            Messenger.Broadcast(SympleLog.LogTrace, "looking up rpeer in roster, mFrom = " + mFrom + "...");

            var addr = Symple.parseAddress(mFrom);

            Debug.WriteLine("addr " + addr);
            mFrom = (string)addr["id"] ?? mFrom;

            if (_roster.ContainsKey(mFrom))
            {
                PeerData rpeerData = _roster[mFrom];

                Messenger.Broadcast(SympleLog.LogTrace, "found rpeerData: " + rpeerData);
                m["from"] = peerDataToJObject(rpeerData);
            }
            else
            {
                Messenger.Broadcast(SympleLog.LogDebug, "symple:client: got message from unknown peer: " + m);
            }

            // Dispatch to the application
            SignallerOnMessage(mType, m);
        }