Пример #1
0
        private static TCPv1Bridge ListenForDirectConnection(
            Contact remote,
            Guid remoteGuid,
            NSMessageHandler nsMessageHandler,
            P2PVersion ver,
            P2PSession startupSession,
            IPAddress host, int port, Guid replyGuid, Guid remoteNonce, bool hashed)
        {
            ConnectivitySettings cs = new ConnectivitySettings();

            if (nsMessageHandler.ConnectivitySettings.LocalHost == string.Empty)
            {
                cs.LocalHost = host.ToString();
                cs.LocalPort = port;
            }
            else
            {
                cs.LocalHost = nsMessageHandler.ConnectivitySettings.LocalHost;
                cs.LocalPort = nsMessageHandler.ConnectivitySettings.LocalPort;
            }

            TCPv1Bridge tcpBridge = new TCPv1Bridge(cs, ver, replyGuid, remoteNonce, hashed, startupSession, nsMessageHandler, remote, remoteGuid);

            tcpBridge.Listen(IPAddress.Parse(cs.LocalHost), cs.LocalPort);

            Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo, "Listening on " + cs.LocalHost + ":" + cs.LocalPort.ToString(CultureInfo.InvariantCulture));

            return(tcpBridge);
        }
Пример #2
0
        /// <summary>
        /// Creates a new session initiated locally and prepares the invitation message.
        /// The next step must be Invite().
        /// </summary>
        public P2PSession(P2PApplication app)
        {
            p2pApplication = app;
            version        = app.P2PVersion;

            localContact            = app.Local;
            remoteContact           = app.Remote;
            localContactEndPointID  = NSMessageHandler.MachineGuid;
            remoteContactEndPointID = app.Remote.SelectBestEndPointId();

            nsMessageHandler = app.Local.NSMessageHandler;
            sessionId        = (uint)random.Next(50000, int.MaxValue);

            // These 2 fields are set when optimal bridge found.
            localBaseIdentifier = 0;
            localIdentifier     = 0;

            invitation                         = new SLPRequestMessage(RemoteContactEPIDString, MSNSLPRequestMethod.INVITE);
            invitation.Target                  = RemoteContactEPIDString;
            invitation.Source                  = LocalContactEPIDString;
            invitation.ContentType             = "application/x-msnmsgr-sessionreqbody";
            invitation.BodyValues["SessionID"] = SessionId.ToString(System.Globalization.CultureInfo.InvariantCulture);
            app.SetupInviteMessage(invitation);

            app.P2PSession = this; // Register events
            remoteContact.DirectBridgeEstablished += RemoteDirectBridgeEstablished;

            Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo,
                              String.Format("{0} created (Initiated locally)", SessionId), GetType().Name);

            status = P2PSessionStatus.WaitingForRemote;
            // Next step must be: Invite()
        }
Пример #3
0
        /// <summary>
        /// Defaults the Flags property to 0x100.
        /// </summary>
        public P2PDCHandshakeMessage(P2PVersion ver)
            : base(ver)
        {
            if (ver == P2PVersion.P2PV1)
            {
                V1Header.Flags = P2PFlag.DirectHandshake;
            }

            InnerBody = new byte[0];
        }
Пример #4
0
        private P2PSession FindSession(P2PMessage msg, SLPMessage slp)
        {
            P2PSession p2pSession = null;
            uint       sessionID  = (msg != null) ? msg.Header.SessionId : 0;

            if ((sessionID == 0) && (slp != null))
            {
                if (slp.BodyValues.ContainsKey("SessionID"))
                {
                    if (!uint.TryParse(slp.BodyValues["SessionID"].Value, out sessionID))
                    {
                        Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning,
                                          "Unable to parse SLP message SessionID", GetType().Name);

                        sessionID = 0;
                    }
                }

                if (sessionID == 0)
                {
                    // We don't get a session ID in BYE requests
                    // So we need to find the session by its call ID
                    P2PVersion p2pVersion = slp.P2PVersion;
                    p2pSession = FindSessionByCallId(slp.CallId, p2pVersion);

                    if (p2pSession != null)
                    {
                        return(p2pSession);
                    }
                }
            }

            // Sometimes we only have a messageID to find the session with...
            if ((sessionID == 0) && (msg.Header.Identifier != 0))
            {
                p2pSession = FindSessionByExpectedIdentifier(msg);

                if (p2pSession != null)
                {
                    return(p2pSession);
                }
            }

            if (sessionID != 0)
            {
                p2pSession = FindSessionBySessionId(sessionID, msg.Version);

                if (p2pSession != null)
                {
                    return(p2pSession);
                }
            }

            return(null);
        }
Пример #5
0
        public P2PMessage(P2PVersion ver)
        {
            version = ver;

            if (ver == P2PVersion.P2PV1)
            {
                header = new P2Pv1Header();
            }
            else if (ver == P2PVersion.P2PV2)
            {
                header = new P2Pv2Header();
            }
        }
Пример #6
0
        private P2PSession FindSessionByCallId(Guid callId, P2PVersion version)
        {
            List <P2PSession> sessions = (version == P2PVersion.P2PV2) ? p2pV2Sessions : p2pV1Sessions;

            foreach (P2PSession session in sessions)
            {
                if (session.Invitation.CallId == callId)
                {
                    return(session);
                }
            }

            return(null);
        }
Пример #7
0
        private P2PSession FindSessionBySessionId(uint sessionId, P2PVersion version)
        {
            List <P2PSession> sessions = (version == P2PVersion.P2PV2) ? p2pV2Sessions : p2pV1Sessions;

            foreach (P2PSession session in sessions)
            {
                if (session.SessionId == sessionId)
                {
                    return(session);
                }
            }

            return(null);
        }
Пример #8
0
        /// <summary>
        /// Constructor.
        /// </summary>
        public P2PDirectProcessor(
            ConnectivitySettings connectivitySettings,
            P2PVersion p2pVersion,
            Guid reply, Guid authNonce, bool isNeedHash,
            P2PSession p2pMessageSession,
            NSMessageHandler nsMessageHandler)
        {
            Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo, "Constructing object - " + p2pVersion, GetType().Name);

            Processor = new TcpSocketMessageProcessor(connectivitySettings, new P2PDCPool());

            this.version          = p2pVersion;
            this.nonce            = authNonce;
            this.reply            = reply;
            this.needHash         = isNeedHash;
            this.startupSession   = p2pMessageSession;
            this.nsMessageHandler = nsMessageHandler;
        }
Пример #9
0
        protected P2PApplication(P2PVersion ver, Contact remote, Guid remoteEP)
        {
            if (ver == P2PVersion.None)
            {
                throw new InvalidOperationException(remote.ToString() + " doesn't support P2P");
            }

            this.version = ver;

            this.local   = remote.NSMessageHandler.Owner;
            this.localEP = NSMessageHandler.MachineGuid;

            this.remote   = remote;
            this.remoteEP = remoteEP;

            this.nsMessageHandler = remote.NSMessageHandler;

            Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo,
                              "Application created: " + ver, GetType().Name);
        }
Пример #10
0
        public static Guid CreateGuidFromData(P2PVersion ver, byte[] data)
        {
            Guid ret = Guid.Empty;

            if (ver == P2PVersion.P2PV1)
            {
                P2PMessage message = new P2PMessage(ver);
                message.ParseBytes(data);

                ret = new Guid(
                    (int)message.V1Header.AckSessionId,

                    (short)(message.Header.AckIdentifier & 0x0000FFFF),
                    (short)((message.Header.AckIdentifier & 0xFFFF0000) >> 16),

                    (byte)((message.V1Header.AckTotalSize & 0x00000000000000FF)),
                    (byte)((message.V1Header.AckTotalSize & 0x000000000000FF00) >> 8),
                    (byte)((message.V1Header.AckTotalSize & 0x0000000000FF0000) >> 16),
                    (byte)((message.V1Header.AckTotalSize & 0x00000000FF000000) >> 24),
                    (byte)((message.V1Header.AckTotalSize & 0x000000FF00000000) >> 32),
                    (byte)((message.V1Header.AckTotalSize & 0x0000FF0000000000) >> 40),
                    (byte)((message.V1Header.AckTotalSize & 0x00FF000000000000) >> 48),
                    (byte)((message.V1Header.AckTotalSize & 0xFF00000000000000) >> 56)
                    );
            }
            else if (ver == P2PVersion.P2PV2)
            {
                Int32 a = BitUtility.ToInt32(data, 0, BitConverter.IsLittleEndian);
                Int16 b = BitUtility.ToInt16(data, 4, BitConverter.IsLittleEndian);
                Int16 c = BitUtility.ToInt16(data, 6, BitConverter.IsLittleEndian);
                byte  d = data[8], e = data[9], f = data[10], g = data[11];
                byte  h = data[12], i = data[13], j = data[14], k = data[15];

                ret = new Guid(a, b, c, d, e, f, g, h, i, j, k);
            }

            return(ret);
        }
Пример #11
0
        public static Guid CreateGuidFromData(P2PVersion ver, byte[] data)
        {
            Guid ret = Guid.Empty;

            if (ver == P2PVersion.P2PV1)
            {
                P2PMessage message = new P2PMessage(ver);
                message.ParseBytes(data);

                ret = new Guid(
                    (int)message.V1Header.AckSessionId,

                    (short)(message.Header.AckIdentifier & 0x0000FFFF),
                    (short)((message.Header.AckIdentifier & 0xFFFF0000) >> 16),

                    (byte)((message.V1Header.AckTotalSize & 0x00000000000000FF)),
                    (byte)((message.V1Header.AckTotalSize & 0x000000000000FF00) >> 8),
                    (byte)((message.V1Header.AckTotalSize & 0x0000000000FF0000) >> 16),
                    (byte)((message.V1Header.AckTotalSize & 0x00000000FF000000) >> 24),
                    (byte)((message.V1Header.AckTotalSize & 0x000000FF00000000) >> 32),
                    (byte)((message.V1Header.AckTotalSize & 0x0000FF0000000000) >> 40),
                    (byte)((message.V1Header.AckTotalSize & 0x00FF000000000000) >> 48),
                    (byte)((message.V1Header.AckTotalSize & 0xFF00000000000000) >> 56)
                );
            }
            else if (ver == P2PVersion.P2PV2)
            {
                Int32 a = BitUtility.ToInt32(data, 0, BitConverter.IsLittleEndian);
                Int16 b = BitUtility.ToInt16(data, 4, BitConverter.IsLittleEndian);
                Int16 c = BitUtility.ToInt16(data, 6, BitConverter.IsLittleEndian);
                byte d = data[8], e = data[9], f = data[10], g = data[11];
                byte h = data[12], i = data[13], j = data[14], k = data[15];

                ret = new Guid(a, b, c, d, e, f, g, h, i, j, k);
            }

            return ret;
        }
Пример #12
0
        public TCPv1Bridge(
            ConnectivitySettings connectivitySettings,
            P2PVersion p2pVersion,
            Guid replyNonce, Guid remoteNonce, bool isNeedHash,
            P2PSession p2pSession,
            NSMessageHandler ns,
            Contact remote, Guid remoteEpId)
            : base(0, ns)
        {
            this.startupSession = p2pSession;
            this.remote         = remote;
            this.remoteEpId     = remoteEpId;

            directConnection = new P2PDirectProcessor(connectivitySettings, p2pVersion, replyNonce, remoteNonce, isNeedHash, p2pSession, ns);
            directConnection.HandshakeCompleted += new EventHandler <EventArgs>(directConnection_HandshakeCompleted);
            directConnection.P2PMessageReceived += new EventHandler <P2PMessageEventArgs>(directConnection_P2PMessageReceived);
            directConnection.SendCompleted      += new EventHandler <MSNPSharp.Core.ObjectEventArgs>(directConnection_SendCompleted);

            directConnection.DirectNegotiationTimedOut += new EventHandler <EventArgs>(directConnection_DirectNegotiationTimedOut);
            directConnection.ConnectionClosed          += new EventHandler <EventArgs>(directConnection_ConnectionClosed);
            directConnection.ConnectingException       += new EventHandler <ExceptionEventArgs>(directConnection_ConnectingException);
            directConnection.ConnectionException       += new EventHandler <ExceptionEventArgs>(directConnection_ConnectionException);
        }
Пример #13
0
        private static void ProcessDCReqInvite(SLPMessage message, NSMessageHandler ns, P2PSession startupSession)
        {
            if (startupSession != null && startupSession.Bridge != null &&
                startupSession.Bridge is TCPv1Bridge)
            {
                return; // We are using a dc bridge already. Don't allow second one.
            }

            if (message.BodyValues.ContainsKey("Bridges") &&
                message.BodyValues["Bridges"].ToString().Contains("TCPv1"))
            {
                SLPStatusMessage slpMessage = new SLPStatusMessage(message.Source, 200, "OK");
                slpMessage.Target               = message.Source;
                slpMessage.Source               = message.Target;
                slpMessage.Branch               = message.Branch;
                slpMessage.CSeq                 = 1;
                slpMessage.CallId               = message.CallId;
                slpMessage.MaxForwards          = 0;
                slpMessage.ContentType          = "application/x-msnmsgr-transrespbody";
                slpMessage.BodyValues["Bridge"] = "TCPv1";

                Guid    remoteGuid = message.FromEndPoint;
                Contact remote     = ns.ContactList.GetContactWithCreate(message.FromEmailAccount, IMAddressInfoType.WindowsLive);

                DCNonceType dcNonceType;
                Guid        remoteNonce = ParseDCNonce(message.BodyValues, out dcNonceType);
                if (remoteNonce == Guid.Empty) // Plain
                {
                    remoteNonce = remote.dcPlainKey;
                }

                bool   hashed         = (dcNonceType == DCNonceType.Sha1);
                string nonceFieldName = hashed ? "Hashed-Nonce" : "Nonce";
                Guid   myHashedNonce  = hashed ? remote.dcLocalHashedNonce : remoteNonce;
                Guid   myPlainNonce   = remote.dcPlainKey;
                if (dcNonceType == DCNonceType.Sha1)
                {
                    // Remote contact supports Hashed-Nonce
                    remote.dcType = dcNonceType;
                    remote.dcRemoteHashedNonce = remoteNonce;
                }
                else
                {
                    remote.dcType = DCNonceType.Plain;
                    myPlainNonce  = remote.dcPlainKey = remote.dcLocalHashedNonce = remote.dcRemoteHashedNonce = remoteNonce;
                }

                // Find host by name
                IPAddress ipAddress = ns.LocalEndPoint.Address;
                int       port;

                P2PVersion ver = message.P2PVersion;

                if (Settings.DisableP2PDirectConnections ||
                    false == ipAddress.Equals(ns.ExternalEndPoint.Address) ||
                    (0 == (port = GetNextDirectConnectionPort(ipAddress))))
                {
                    slpMessage.BodyValues["Listening"]    = "false";
                    slpMessage.BodyValues[nonceFieldName] = Guid.Empty.ToString("B").ToUpper(CultureInfo.InvariantCulture);
                }
                else
                {
                    // Let's listen
                    remote.DirectBridge = ListenForDirectConnection(remote, remoteGuid, ns, ver, startupSession, ipAddress, port, myPlainNonce, remoteNonce, hashed);

                    slpMessage.BodyValues["Listening"]          = "true";
                    slpMessage.BodyValues["Capabilities-Flags"] = "1";
                    slpMessage.BodyValues["IPv6-global"]        = string.Empty;
                    slpMessage.BodyValues["Nat-Trav-Msg-Type"]  = "WLX-Nat-Trav-Msg-Direct-Connect-Resp";
                    slpMessage.BodyValues["UPnPNat"]            = "false";

                    slpMessage.BodyValues["NeedConnectingEndpointInfo"] = "true";

                    slpMessage.BodyValues["Conn-Type"]          = "Direct-Connect";
                    slpMessage.BodyValues["TCP-Conn-Type"]      = "Direct-Connect";
                    slpMessage.BodyValues[nonceFieldName]       = myHashedNonce.ToString("B").ToUpper(CultureInfo.InvariantCulture);
                    slpMessage.BodyValues["IPv4Internal-Addrs"] = ipAddress.ToString();
                    slpMessage.BodyValues["IPv4Internal-Port"]  = port.ToString(CultureInfo.InvariantCulture);

                    // check if client is behind firewall (NAT-ted)
                    // if so, send the public ip also the client, so it can try to connect to that ip
                    if (!ns.ExternalEndPoint.Address.Equals(ns.LocalEndPoint.Address))
                    {
                        slpMessage.BodyValues["IPv4External-Addrs"] = ns.ExternalEndPoint.Address.ToString();
                        slpMessage.BodyValues["IPv4External-Port"]  = port.ToString(CultureInfo.InvariantCulture);
                    }
                }

                P2PMessage p2pMessage = new P2PMessage(ver);
                p2pMessage.InnerMessage = slpMessage;

                if (ver == P2PVersion.P2PV2)
                {
                    p2pMessage.V2Header.TFCombination = TFCombination.First;
                }
                else if (ver == P2PVersion.P2PV1)
                {
                    p2pMessage.V1Header.Flags = P2PFlag.MSNSLPInfo;
                }

                if (startupSession != null)
                {
                    startupSession.SetupDCTimer();
                    startupSession.Bridge.Send(null, startupSession.Remote, startupSession.RemoteContactEndPointID, p2pMessage);
                }
                else
                {
                    ns.SDGBridge.Send(null, remote, remoteGuid, p2pMessage);
                }
            }
            else
            {
                if (startupSession != null)
                {
                    startupSession.DirectNegotiationFailed();
                }
            }
        }
Пример #14
0
        private P2PSession FindSessionBySessionId(uint sessionId, P2PVersion version)
        {
            List<P2PSession> sessions = (version == P2PVersion.P2PV2) ? p2pV2Sessions : p2pV1Sessions;

            foreach (P2PSession session in sessions)
            {
                if (session.SessionId == sessionId)
                    return session;
            }

            return null;
        }
Пример #15
0
 /// <summary>
 /// Constructs a P2P data message.
 /// </summary>
 public P2PDataMessage(P2PVersion v)
     : base(v)
 {
 }
Пример #16
0
 public P2PDCMessage(P2PVersion ver)
     : base(ver)
 {
 }
Пример #17
0
        private static TCPv1Bridge ListenForDirectConnection(
            Contact remote,
            Guid remoteGuid,
            NSMessageHandler nsMessageHandler,
            P2PVersion ver,
            P2PSession startupSession,
            IPAddress host, int port, Guid replyGuid, Guid remoteNonce, bool hashed)
        {
            ConnectivitySettings cs = new ConnectivitySettings();
            if (nsMessageHandler.ConnectivitySettings.LocalHost == string.Empty)
            {
                cs.LocalHost = host.ToString();
                cs.LocalPort = port;
            }
            else
            {
                cs.LocalHost = nsMessageHandler.ConnectivitySettings.LocalHost;
                cs.LocalPort = nsMessageHandler.ConnectivitySettings.LocalPort;
            }

            TCPv1Bridge tcpBridge = new TCPv1Bridge(cs, ver, replyGuid, remoteNonce, hashed, startupSession, nsMessageHandler, remote, remoteGuid);

            tcpBridge.Listen(IPAddress.Parse(cs.LocalHost), cs.LocalPort);

            Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo, "Listening on " + cs.LocalHost + ":" + cs.LocalPort.ToString(CultureInfo.InvariantCulture));

            return tcpBridge;
        }
Пример #18
0
        private static void ProcessDCRespInvite(SLPMessage message, NSMessageHandler ns, P2PSession startupSession)
        {
            MimeDictionary bodyValues = message.BodyValues;

            // Check the protocol
            if (bodyValues.ContainsKey("Bridge") &&
                bodyValues["Bridge"].ToString() == "TCPv1" &&
                bodyValues.ContainsKey("Listening") &&
                bodyValues["Listening"].ToString().ToLowerInvariant().IndexOf("true") >= 0)
            {
                Contact remote     = ns.ContactList.GetContactWithCreate(message.FromEmailAccount, IMAddressInfoType.WindowsLive);
                Guid    remoteGuid = message.FromEndPoint;

                DCNonceType dcNonceType;
                Guid        remoteNonce = ParseDCNonce(message.BodyValues, out dcNonceType);
                bool        hashed      = (dcNonceType == DCNonceType.Sha1);
                Guid        replyGuid   = hashed ? remote.dcPlainKey : remoteNonce;

                IPEndPoint[] selectedPoint = SelectIPEndPoint(bodyValues, ns);

                if (selectedPoint != null && selectedPoint.Length > 0)
                {
                    P2PVersion ver = message.P2PVersion;

                    // We must connect to the remote client
                    ConnectivitySettings settings = new ConnectivitySettings();
                    settings.EndPoints  = selectedPoint;
                    remote.DirectBridge = CreateDirectConnection(remote, remoteGuid, ver, settings, replyGuid, remoteNonce, hashed, ns, startupSession);

                    bool needConnectingEndpointInfo;
                    if (bodyValues.ContainsKey("NeedConnectingEndpointInfo") &&
                        bool.TryParse(bodyValues["NeedConnectingEndpointInfo"], out needConnectingEndpointInfo) &&
                        needConnectingEndpointInfo == true)
                    {
                        IPEndPoint ipep = ((TCPv1Bridge)remote.DirectBridge).LocalEndPoint;

                        string desc = "stroPdnAsrddAlanretnI4vPI";
                        char[] rev  = ipep.ToString().ToCharArray();
                        Array.Reverse(rev);
                        string ipandport = new string(rev);

                        SLPRequestMessage slpResponseMessage = new SLPRequestMessage(message.Source, MSNSLPRequestMethod.ACK);
                        slpResponseMessage.Source      = message.Target;
                        slpResponseMessage.Via         = message.Via;
                        slpResponseMessage.CSeq        = 0;
                        slpResponseMessage.CallId      = Guid.Empty;
                        slpResponseMessage.MaxForwards = 0;
                        slpResponseMessage.ContentType = @"application/x-msnmsgr-transdestaddrupdate";

                        slpResponseMessage.BodyValues[desc] = ipandport;
                        slpResponseMessage.BodyValues["Nat-Trav-Msg-Type"] = "WLX-Nat-Trav-Msg-Updated-Connecting-Port";

                        P2PMessage msg = new P2PMessage(ver);
                        msg.InnerMessage = slpResponseMessage;

                        ns.SDGBridge.Send(null, remote, remoteGuid, msg);
                    }

                    return;
                }
            }

            if (startupSession != null)
            {
                startupSession.DirectNegotiationFailed();
            }
        }
Пример #19
0
 /// <summary>
 /// Constructs a P2P data message.
 /// </summary>
 public P2PDataMessage(P2PVersion v)
     : base(v)
 {
 }
Пример #20
0
        private static TCPv1Bridge CreateDirectConnection(Contact remote, Guid remoteGuid, P2PVersion ver, ConnectivitySettings cs, Guid replyGuid, Guid remoteNonce, bool hashed, NSMessageHandler nsMessageHandler, P2PSession startupSession)
        {
            string[] points = new string[cs.EndPoints.Length];

            for (int i = 0; i < points.Length; i++)
            {
                points[i] = cs.EndPoints[i].ToString();
            }

            TCPv1Bridge tcpBridge = new TCPv1Bridge(cs, ver, replyGuid, remoteNonce, hashed, startupSession, nsMessageHandler, remote, remoteGuid);

            Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo, "Trying to setup direct connection with remote hosts " + string.Join(",", points));

            tcpBridge.Connect();

            return tcpBridge;
        }
Пример #21
0
        public bool ProcessP2PMessage(P2PBridge bridge, Contact source, Guid sourceGuid, P2PMessage p2pMessage)
        {
            // 1) SLP BUFFERING: Combine splitted SLP messages
            if (slpMessagePool.BufferMessage(ref p2pMessage))
            {
                // * Buffering: Not completed yet, we must wait next packets -OR-
                // * Invalid packet received: Don't kill me, just ignore it...
                return(true);
            }

            Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose,
                              String.Format("Received P2PMessage from {0}\r\n{1}", bridge.ToString(), p2pMessage.ToDebugString()), GetType().Name);

            // 2) CHECK SLP: Check destination, source, endpoints
            SLPMessage slp = p2pMessage.IsSLPData ? p2pMessage.InnerMessage as SLPMessage : null;

            if (slp != null)
            {
                if (!slpHandler.CheckSLPMessage(bridge, source, sourceGuid, p2pMessage, slp))
                {
                    return(true); // HANDLED, This SLP is not for us.
                }
            }

            // 3) FIRST SLP MESSAGE: Create applications/sessions based on invitation
            if (slp != null && slp is SLPRequestMessage &&
                (slp as SLPRequestMessage).Method == "INVITE" &&
                slp.ContentType == "application/x-msnmsgr-sessionreqbody")
            {
                uint       appId   = slp.BodyValues.ContainsKey("AppID") ? uint.Parse(slp.BodyValues["AppID"].Value) : 0;
                Guid       eufGuid = slp.BodyValues.ContainsKey("EUF-GUID") ? new Guid(slp.BodyValues["EUF-GUID"].Value) : Guid.Empty;
                P2PVersion ver     = slp.P2PVersion;

                if (P2PApplication.IsRegistered(eufGuid, appId))
                {
                    P2PSession newSession = FindSessionByCallId(slp.CallId, ver);

                    if (newSession == null)
                    {
                        newSession         = new P2PSession(slp as SLPRequestMessage, p2pMessage, nsMessageHandler, bridge);
                        newSession.Closed += P2PSessionClosed;

                        if (newSession.Version == P2PVersion.P2PV2)
                        {
                            p2pV2Sessions.Add(newSession);
                        }
                        else
                        {
                            p2pV1Sessions.Add(newSession);
                        }
                    }
                    else
                    {
                        // P2PSession exists, bridge changed...
                        if (newSession.Bridge != bridge)
                        {
                            // BRIDGETODO
                        }
                    }

                    return(true);
                }

                // Not registered application. Decline it without create a new session...
                slpHandler.SendSLPStatus(bridge, p2pMessage, source, sourceGuid, 603, "Decline");
                return(true);
            }

            // 4) FIND SESSION: Search session by SessionId/ExpectedIdentifier
            P2PSession session = FindSession(p2pMessage, slp);

            if (session != null)
            {
                // ResetTimeoutTimer();

                // Keep track of theremoteIdentifier

                // Keep track of the remote identifier
                session.remoteIdentifier = (p2pMessage.Version == P2PVersion.P2PV2) ?
                                           p2pMessage.Header.Identifier + p2pMessage.Header.MessageSize :
                                           p2pMessage.Header.Identifier;

                // Session SLP
                if (slp != null && slpHandler.HandleP2PSessionSignal(bridge, p2pMessage, slp, session))
                {
                    return(true);
                }

                // Session Data
                if (slp == null && session.ProcessP2PData(bridge, p2pMessage))
                {
                    return(true);
                }
            }

            return(false);
        }
Пример #22
0
        /// <summary>
        /// Creates a new session initiated remotely. If the application cannot be handled, decline message will be sent.
        /// The application will handle all messages automatically and no user interaction is required if AutoAccept is true.
        /// If AutoAccept is false, <see cref="P2PHandler.InvitationReceived"/> event will be fired.
        /// </summary>
        public P2PSession(SLPRequestMessage slp, P2PMessage msg, NSMessageHandler ns, P2PBridge bridge)
        {
            nsMessageHandler = ns;
            invitation = slp;
            version = slp.P2PVersion;

            if (version == P2PVersion.P2PV1)
            {
                localContact = (slp.ToEmailAccount == ns.Owner.Account) ?
                    ns.Owner : ns.ContactList.GetContactWithCreate(slp.ToEmailAccount, IMAddressInfoType.WindowsLive);

                remoteContact = ns.ContactList.GetContactWithCreate(slp.FromEmailAccount, IMAddressInfoType.WindowsLive);
            }
            else
            {
                localContact = (slp.ToEmailAccount == ns.Owner.Account) ?
                    ns.Owner : ns.ContactList.GetContactWithCreate(slp.ToEmailAccount, IMAddressInfoType.WindowsLive);
                localContactEndPointID = slp.ToEndPoint;

                remoteContact = ns.ContactList.GetContactWithCreate(slp.FromEmailAccount, IMAddressInfoType.WindowsLive);
                remoteContactEndPointID = slp.FromEndPoint;
            }

            if (!uint.TryParse(slp.BodyValues["SessionID"].Value, out sessionId))
            {
                Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning,
                    "Can't parse SessionID: " + SessionId, GetType().Name);
            }

            p2pBridge = bridge;
            localBaseIdentifier = bridge.SequenceId;
            localIdentifier = localBaseIdentifier;
            status = P2PSessionStatus.WaitingForLocal;

            Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo,
              String.Format("{0} created (Initiated remotely)", SessionId), GetType().Name);

            remoteContact.DirectBridgeEstablished += RemoteDirectBridgeEstablished;

            if (msg != null)
            {
                // Set remote baseID
                remoteBaseIdentifier = msg.Header.Identifier;
                remoteIdentifier = remoteBaseIdentifier;

                if (version == P2PVersion.P2PV2)
                    remoteIdentifier += msg.V2Header.MessageSize;
            }

            // Create application based on invitation
            uint appId = slp.BodyValues.ContainsKey("AppID") ? uint.Parse(slp.BodyValues["AppID"].Value) : 0;
            Guid eufGuid = slp.BodyValues.ContainsKey("EUF-GUID") ? new Guid(slp.BodyValues["EUF-GUID"].Value) : Guid.Empty;
            p2pApplication = P2PApplication.CreateInstance(eufGuid, appId, this);

            if (p2pApplication != null && p2pApplication.ValidateInvitation(invitation))
            {
                if (p2pApplication.AutoAccept)
                {
                    Accept();
                }
                else
                {
                    ns.P2PHandler.OnInvitationReceived(new P2PSessionEventArgs(this));
                }
            }
            else
            {
                Decline();
            }
        }
Пример #23
0
        public TCPv1Bridge(
            ConnectivitySettings connectivitySettings,
            P2PVersion p2pVersion,
            Guid replyNonce, Guid remoteNonce, bool isNeedHash,
            P2PSession p2pSession,
            NSMessageHandler ns,
            Contact remote, Guid remoteEpId)
            : base(0, ns)
        {
            this.startupSession = p2pSession;
            this.remote = remote;
            this.remoteEpId = remoteEpId;

            directConnection = new P2PDirectProcessor(connectivitySettings, p2pVersion, replyNonce, remoteNonce, isNeedHash, p2pSession, ns);
            directConnection.HandshakeCompleted += new EventHandler<EventArgs>(directConnection_HandshakeCompleted);
            directConnection.P2PMessageReceived += new EventHandler<P2PMessageEventArgs>(directConnection_P2PMessageReceived);
            directConnection.SendCompleted += new EventHandler<MSNPSharp.Core.ObjectEventArgs>(directConnection_SendCompleted);

            directConnection.DirectNegotiationTimedOut += new EventHandler<EventArgs>(directConnection_DirectNegotiationTimedOut);
            directConnection.ConnectionClosed += new EventHandler<EventArgs>(directConnection_ConnectionClosed);
            directConnection.ConnectingException += new EventHandler<ExceptionEventArgs>(directConnection_ConnectingException);
            directConnection.ConnectionException += new EventHandler<ExceptionEventArgs>(directConnection_ConnectionException);
        }
Пример #24
0
        private P2PDCHandshakeMessage VerifyHandshake(byte[] data)
        {
            P2PVersion            authVersion = P2PVersion.P2PV1;
            P2PDCHandshakeMessage ret         = null;

            if (data.Length == 48)
            {
                authVersion = P2PVersion.P2PV1;
            }
            else if (data.Length == 16)
            {
                authVersion = P2PVersion.P2PV2;
            }
            else
            {
                Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning,
                                  "Invalid handshake length, the data was: " + Encoding.ASCII.GetString(data), GetType().Name);

                return(null);
            }

            if (authVersion != this.version)
            {
                Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning,
                                  String.Format("Received version is {0}, expected {1}", authVersion, this.version), GetType().Name);

                return(null);
            }

            P2PDCHandshakeMessage incomingHandshake = new P2PDCHandshakeMessage(version);

            incomingHandshake.ParseBytes(data);

            Guid incomingGuid = incomingHandshake.Guid;

            if (incomingHandshake.Version == P2PVersion.P2PV1 && (P2PFlag.DirectHandshake != (incomingHandshake.V1Header.Flags & P2PFlag.DirectHandshake)))
            {
                Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning,
                                  "Handshake flag not set for v1, the flag was: " + incomingHandshake.V1Header.Flags, GetType().Name);

                return(null);
            }

            Guid compareGuid = incomingGuid;

            if (needHash)
            {
                compareGuid = HashedNonceGenerator.HashNonce(compareGuid);
            }

            if (this.nonce == compareGuid)
            {
                ret = new P2PDCHandshakeMessage(version);
                ret.ParseBytes(data);      // copy identifiers
                ret.Guid = compareGuid;    // set new guid (hashed)
                ret.Header.Identifier = 0; // our id
                return(ret);               // OK this is our handshake message
            }

            return(null);
        }
Пример #25
0
        /// <summary>
        /// Constructor.
        /// </summary>
        public P2PDirectProcessor(
            ConnectivitySettings connectivitySettings,
            P2PVersion p2pVersion,
            Guid reply, Guid authNonce, bool isNeedHash,
            P2PSession p2pMessageSession,
            NSMessageHandler nsMessageHandler)
        {
            Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo, "Constructing object - " + p2pVersion, GetType().Name);

            Processor = new TcpSocketMessageProcessor(connectivitySettings, new P2PDCPool());

            this.version = p2pVersion;
            this.nonce = authNonce;
            this.reply = reply;
            this.needHash = isNeedHash;
            this.startupSession = p2pMessageSession;
            this.nsMessageHandler = nsMessageHandler;
        }
Пример #26
0
        private static TCPv1Bridge CreateDirectConnection(Contact remote, Guid remoteGuid, P2PVersion ver, ConnectivitySettings cs, Guid replyGuid, Guid remoteNonce, bool hashed, NSMessageHandler nsMessageHandler, P2PSession startupSession)
        {
            string[] points = new string[cs.EndPoints.Length];

            for (int i = 0; i < points.Length; i++)
            {
                points[i] = cs.EndPoints[i].ToString();
            }

            TCPv1Bridge tcpBridge = new TCPv1Bridge(cs, ver, replyGuid, remoteNonce, hashed, startupSession, nsMessageHandler, remote, remoteGuid);

            Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo, "Trying to setup direct connection with remote hosts " + string.Join(",", points));

            tcpBridge.Connect();

            return(tcpBridge);
        }
Пример #27
0
        /// <summary>
        /// Creates a new session initiated remotely. If the application cannot be handled, decline message will be sent.
        /// The application will handle all messages automatically and no user interaction is required if AutoAccept is true.
        /// If AutoAccept is false, <see cref="P2PHandler.InvitationReceived"/> event will be fired.
        /// </summary>
        public P2PSession(SLPRequestMessage slp, P2PMessage msg, NSMessageHandler ns, P2PBridge bridge)
        {
            nsMessageHandler = ns;
            invitation       = slp;
            version          = slp.P2PVersion;

            if (version == P2PVersion.P2PV1)
            {
                localContact = (slp.ToEmailAccount == ns.Owner.Account) ?
                               ns.Owner : ns.ContactList.GetContactWithCreate(slp.ToEmailAccount, IMAddressInfoType.WindowsLive);

                remoteContact = ns.ContactList.GetContactWithCreate(slp.FromEmailAccount, IMAddressInfoType.WindowsLive);
            }
            else
            {
                localContact = (slp.ToEmailAccount == ns.Owner.Account) ?
                               ns.Owner : ns.ContactList.GetContactWithCreate(slp.ToEmailAccount, IMAddressInfoType.WindowsLive);
                localContactEndPointID = slp.ToEndPoint;

                remoteContact           = ns.ContactList.GetContactWithCreate(slp.FromEmailAccount, IMAddressInfoType.WindowsLive);
                remoteContactEndPointID = slp.FromEndPoint;
            }

            if (!uint.TryParse(slp.BodyValues["SessionID"].Value, out sessionId))
            {
                Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning,
                                  "Can't parse SessionID: " + SessionId, GetType().Name);
            }

            p2pBridge           = bridge;
            localBaseIdentifier = bridge.SequenceId;
            localIdentifier     = localBaseIdentifier;
            status = P2PSessionStatus.WaitingForLocal;

            Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo,
                              String.Format("{0} created (Initiated remotely)", SessionId), GetType().Name);

            remoteContact.DirectBridgeEstablished += RemoteDirectBridgeEstablished;

            if (msg != null)
            {
                // Set remote baseID
                remoteBaseIdentifier = msg.Header.Identifier;
                remoteIdentifier     = remoteBaseIdentifier;

                if (version == P2PVersion.P2PV2)
                {
                    remoteIdentifier += msg.V2Header.MessageSize;
                }
            }

            // Create application based on invitation
            uint appId   = slp.BodyValues.ContainsKey("AppID") ? uint.Parse(slp.BodyValues["AppID"].Value) : 0;
            Guid eufGuid = slp.BodyValues.ContainsKey("EUF-GUID") ? new Guid(slp.BodyValues["EUF-GUID"].Value) : Guid.Empty;

            p2pApplication = P2PApplication.CreateInstance(eufGuid, appId, this);

            if (p2pApplication != null && p2pApplication.ValidateInvitation(invitation))
            {
                if (p2pApplication.AutoAccept)
                {
                    Accept();
                }
                else
                {
                    ns.P2PHandler.OnInvitationReceived(new P2PSessionEventArgs(this));
                }
            }
            else
            {
                Decline();
            }
        }
Пример #28
0
 public P2PDCMessage(P2PVersion ver)
     : base(ver)
 {
 }
Пример #29
0
        public P2PMessage(P2PVersion ver)
        {
            version = ver;

            if (ver == P2PVersion.P2PV1)
            {
                header = new P2Pv1Header();
            }
            else if (ver == P2PVersion.P2PV2)
            {
                header = new P2Pv2Header();
            }
        }
Пример #30
0
        protected P2PApplication(P2PVersion ver, Contact remote, Guid remoteEP)
        {
            if (ver == P2PVersion.None)
                throw new InvalidOperationException(remote.ToString() + " doesn't support P2P");

            this.version = ver;

            this.local = remote.NSMessageHandler.Owner;
            this.localEP = NSMessageHandler.MachineGuid;

            this.remote = remote;
            this.remoteEP = remoteEP;

            this.nsMessageHandler = remote.NSMessageHandler;

            Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo,
                "Application created: " + ver, GetType().Name);
        }
Пример #31
0
        /// <summary>
        /// Creates a new session initiated locally and prepares the invitation message.
        /// The next step must be Invite().
        /// </summary>
        public P2PSession(P2PApplication app)
        {
            p2pApplication = app;
            version = app.P2PVersion;

            localContact = app.Local;
            remoteContact = app.Remote;
            localContactEndPointID = NSMessageHandler.MachineGuid;
            remoteContactEndPointID = app.Remote.SelectBestEndPointId();

            nsMessageHandler = app.Local.NSMessageHandler;
            sessionId = (uint)random.Next(50000, int.MaxValue);

            // These 2 fields are set when optimal bridge found.
            localBaseIdentifier = 0;
            localIdentifier = 0;

            invitation = new SLPRequestMessage(RemoteContactEPIDString, MSNSLPRequestMethod.INVITE);
            invitation.Target = RemoteContactEPIDString;
            invitation.Source = LocalContactEPIDString;
            invitation.ContentType = "application/x-msnmsgr-sessionreqbody";
            invitation.BodyValues["SessionID"] = SessionId.ToString(System.Globalization.CultureInfo.InvariantCulture);
            app.SetupInviteMessage(invitation);

            app.P2PSession = this; // Register events
            remoteContact.DirectBridgeEstablished += RemoteDirectBridgeEstablished;

            Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo,
                String.Format("{0} created (Initiated locally)", SessionId), GetType().Name);

            status = P2PSessionStatus.WaitingForRemote;
            // Next step must be: Invite()
        }
Пример #32
0
        /// <summary>
        /// Defaults the Flags property to 0x100.
        /// </summary>
        public P2PDCHandshakeMessage(P2PVersion ver)
            : base(ver)
        {
            if (ver == P2PVersion.P2PV1)
                V1Header.Flags = P2PFlag.DirectHandshake;

            InnerBody = new byte[0];
        }
Пример #33
0
        private P2PSession FindSessionByCallId(Guid callId, P2PVersion version)
        {
            List<P2PSession> sessions = (version == P2PVersion.P2PV2) ? p2pV2Sessions : p2pV1Sessions;

            foreach (P2PSession session in sessions)
            {
                if (session.Invitation.CallId == callId)
                    return session;
            }

            return null;
        }