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); }
/// <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() }
/// <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]; }
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); }
public P2PMessage(P2PVersion ver) { version = ver; if (ver == P2PVersion.P2PV1) { header = new P2Pv1Header(); } else if (ver == P2PVersion.P2PV2) { header = new P2Pv2Header(); } }
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); }
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); }
/// <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; }
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); }
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); }
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; }
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); }
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(); } } }
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; }
/// <summary> /// Constructs a P2P data message. /// </summary> public P2PDataMessage(P2PVersion v) : base(v) { }
public P2PDCMessage(P2PVersion ver) : base(ver) { }
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; }
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(); } }
/// <summary> /// Constructs a P2P data message. /// </summary> public P2PDataMessage(P2PVersion v) : base(v) { }
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; }
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); }
/// <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(); } }
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); }
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); }
/// <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; }
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); }
/// <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(); } }
public P2PDCMessage(P2PVersion ver) : base(ver) { }
public P2PMessage(P2PVersion ver) { version = ver; if (ver == P2PVersion.P2PV1) { header = new P2Pv1Header(); } else if (ver == P2PVersion.P2PV2) { header = new P2Pv2Header(); } }
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); }
/// <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() }
/// <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]; }
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; }