/// <summary> /// We are sender /// </summary> /// <param name="p2pSession"></param> public ObjectTransfer(P2PSession p2pSession) : base(p2pSession) { msnObject = new MSNObject(); msnObject.SetContext(p2pSession.Invitation.BodyValues["Context"].Value, true); if (msnObject.ObjectType == MSNObjectType.UserDisplay || msnObject.ObjectType == MSNObjectType.Unknown) { msnObject = NSMessageHandler.Owner.DisplayImage; objStream = NSMessageHandler.Owner.DisplayImage.OpenStream(); } else if (msnObject.ObjectType == MSNObjectType.Scene) { msnObject = NSMessageHandler.Owner.SceneImage; objStream = NSMessageHandler.Owner.SceneImage.OpenStream(); } else if (msnObject.ObjectType == MSNObjectType.Emoticon && Local.Emoticons.ContainsKey(msnObject.Sha)) { msnObject = Local.Emoticons[msnObject.Sha]; objStream = ((Emoticon)msnObject).OpenStream(); } sending = true; if (p2pSession.Invitation.BodyValues.ContainsKey("AppID")) applicationId = uint.Parse(p2pSession.Invitation.BodyValues["AppID"]); }
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); }
protected virtual void SendMultiPacket(P2PSession session, Contact remote, Guid remoteGuid, P2PMessage[] sendList) { foreach (P2PMessage p2pMessage in sendList) { SendOnePacket(session, remote, remoteGuid, p2pMessage); } }
/// <summary> /// /// </summary> /// <param name="e"></param> protected virtual void OnBridgeSent(P2PMessageSessionEventArgs e) { P2PSession session = e.P2PSession; lock (sendingQueues) { if ((session != null) && sendingQueues.ContainsKey(session)) { if (sendingQueues[session].Contains(e.P2PMessage)) { sendingQueues[session].Remove(e.P2PMessage); } else { Trace.WriteLineIf(Settings.TraceSwitch.TraceError, "Sent message not present in sending queue", GetType().Name); } } } if (BridgeSent != null) { BridgeSent(this, e); } ProcessSendQueues(); }
/// <summary> /// /// </summary> /// <param name="session"></param> /// <param name="queue"></param> public virtual void AddQueue(P2PSession session, P2PSendQueue queue) { Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, String.Format("P2PBridge {0} received queue for session {1}", this.ToString(), session.SessionId), GetType().Name); if (sendQueues.ContainsKey(session)) { Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, "A queue is already present for this session, merging the queues", GetType().Name); lock (sendQueues[session]) { while (queue.Count > 0) { sendQueues[session].Enqueue(queue.Dequeue()); } } } else { lock (sendQueues) sendQueues[session] = queue; } ProcessSendQueues(); }
public override bool SuitableFor(P2PSession session) { if (base.SuitableFor(session) && session.RemoteContactEndPointID == RemoteEpId) { return(true); } return(false); }
/// <summary> /// Move the specified <see cref="P2PSession"/> to the new <see cref="P2PBridge"/> specified. /// </summary> /// <param name="session"></param> /// <param name="newBridge"></param> public virtual void MigrateQueue(P2PSession session, P2PBridge newBridge) { Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, String.Format("P2PBridge {0} migrating session {1} queue to new bridge {2}", this.ToString(), session.SessionId, (newBridge != null) ? newBridge.ToString() : "null"), GetType().Name); P2PSendQueue newQueue = new P2PSendQueue(); lock (sendingQueues) { if (sendingQueues.ContainsKey(session)) { if (newBridge != null) { lock (sendingQueues[session]) { foreach (P2PSendItem item in sendingQueues[session]) { newQueue.Enqueue(item); } } } sendingQueues.Remove(session); } } lock (sendQueues) { if (sendQueues.ContainsKey(session)) { if (newBridge != null) { while (sendQueues[session].Count > 0) { newQueue.Enqueue(sendQueues[session].Dequeue()); } } sendQueues.Remove(session); } } lock (stoppedSessions) { if (stoppedSessions.Contains(session)) { stoppedSessions.Remove(session); } } if (newBridge != null) { newBridge.AddQueue(session, newQueue); } }
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); }
protected override void SendOnePacket(P2PSession session, Contact remote, Guid remoteGuid, P2PMessage p2pMessage) { if (remote == null) { return; } string to = ((int)remote.ClientType).ToString() + ":" + remote.Account; string from = ((int)NSMessageHandler.Owner.ClientType).ToString() + ":" + NSMessageHandler.Owner.Account; MultiMimeMessage mmMessage = new MultiMimeMessage(to, from); mmMessage.RoutingHeaders[MIMERoutingHeaders.From][MIMERoutingHeaders.EPID] = NSMessageHandler.MachineGuid.ToString("B").ToLowerInvariant(); mmMessage.RoutingHeaders[MIMERoutingHeaders.To][MIMERoutingHeaders.EPID] = remoteGuid.ToString("B").ToLowerInvariant(); mmMessage.RoutingHeaders[MIMERoutingHeaders.ServiceChannel] = "PE"; mmMessage.RoutingHeaders[MIMERoutingHeaders.Options] = "0"; mmMessage.ContentKeyVersion = "2.0"; SLPMessage slpMessage = p2pMessage.IsSLPData ? p2pMessage.InnerMessage as SLPMessage : null; if (slpMessage != null && ((slpMessage.ContentType == "application/x-msnmsgr-transreqbody" || slpMessage.ContentType == "application/x-msnmsgr-transrespbody" || slpMessage.ContentType == "application/x-msnmsgr-transdestaddrupdate"))) { mmMessage.ContentHeaders[MIMEContentHeaders.MessageType] = MessageTypes.SignalP2P; mmMessage.InnerBody = slpMessage.GetBytes(false); mmMessage.InnerMessage = slpMessage; } else { mmMessage.ContentHeaders[MIMEContentHeaders.ContentType] = "application/x-msnmsgrp2p"; mmMessage.ContentHeaders[MIMEContentHeaders.ContentTransferEncoding] = "binary"; mmMessage.ContentHeaders[MIMEContentHeaders.MessageType] = MessageTypes.Data; //mmMessage.ContentHeaders[MIMEContentHeaders.Pipe] = PackageNo.ToString(); mmMessage.ContentHeaders[MIMEContentHeaders.BridgingOffsets] = "0"; mmMessage.InnerBody = p2pMessage.GetBytes(true); mmMessage.InnerMessage = p2pMessage; } NSMessageProcessor nsmp = (NSMessageProcessor)NSMessageHandler.MessageProcessor; int transId = nsmp.IncreaseTransactionID(); lock (p2pAckMessages) p2pAckMessages[transId] = new P2PMessageSessionEventArgs(p2pMessage, session); NSMessage sdgPayload = new NSMessage("SDG"); sdgPayload.TransactionID = transId; sdgPayload.InnerMessage = mmMessage; nsmp.SendMessage(sdgPayload, sdgPayload.TransactionID); }
/// <summary> /// Send a P2P Message to the specified P2PSession. /// </summary> /// <param name="session"> /// The application layer, which is a <see cref="P2PSession"/> /// </param> /// <param name="remote"> /// he receiver <see cref="Contact"/> /// </param> /// <param name="remoteGuid"> /// A <see cref="Guid"/> /// </param> /// <param name="msg"> /// he <see cref="P2PMessage"/> to be sent. /// </param> /// <param name="ackTimeout"> /// The maximum time to wait for an ACK. <see cref="System.Int32"/> /// </param> /// <param name="ackHandler"> /// The <see cref="AckHandler"/> to handle the ACK. /// </param> public virtual void Send(P2PSession session, Contact remote, Guid remoteGuid, P2PMessage msg, int ackTimeout, AckHandler ackHandler) { if (remote == null) { throw new ArgumentNullException("remote"); } P2PMessage[] msgs = SetSequenceNumberAndRegisterAck(session, remote, msg, ackHandler, ackTimeout); if (session == null) { if (!IsOpen) { Trace.WriteLineIf(Settings.TraceSwitch.TraceError, "Send called with no session on a closed bridge", GetType().Name); return; } // Bypass queueing foreach (P2PMessage m in msgs) { SendOnePacket(null, remote, remoteGuid, m); } return; } if (!SuitableFor(session)) { Trace.WriteLineIf(Settings.TraceSwitch.TraceError, "Send called with a session this bridge is not suitable for", GetType().Name); return; } lock (sendQueues) { if (!sendQueues.ContainsKey(session)) { sendQueues[session] = new P2PSendQueue(); } } lock (sendQueues[session]) { foreach (P2PMessage m in msgs) { sendQueues[session].Enqueue(remote, remoteGuid, m); } } ProcessSendQueues(); }
private static void ProcessDirectAddrUpdate( SLPMessage message, NSMessageHandler nsMessageHandler, P2PSession startupSession) { Contact from = nsMessageHandler.ContactList.GetContactWithCreate(message.FromEmailAccount, IMAddressInfoType.WindowsLive); IPEndPoint[] ipEndPoints = SelectIPEndPoint(message.BodyValues, nsMessageHandler); if (from.DirectBridge != null && ipEndPoints != null && ipEndPoints.Length > 0) { ((TCPv1Bridge)from.DirectBridge).OnDestinationAddressUpdated(new DestinationAddressUpdatedEventArgs(ipEndPoints)); } }
/// <summary> /// Stop sending future messages to the specified <see cref="P2PSession"/>. /// </summary> /// <param name="session"></param> public virtual void StopSending(P2PSession session) { Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, String.Format("P2PBridge {0} stop sending for {1}", this.ToString(), session.SessionId), GetType().Name); lock (stoppedSessions) { if (!stoppedSessions.Contains(session)) { stoppedSessions.Add(session); } else { Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, "Session is already in stopped list", GetType().Name); } } }
private P2PMessage[] SetSequenceNumberAndRegisterAck(P2PSession session, Contact remote, P2PMessage p2pMessage, AckHandler ackHandler, int timeout) { if (p2pMessage.Header.Identifier == 0) { if (p2pMessage.Version == P2PVersion.P2PV1) { p2pMessage.Header.Identifier = ++sequenceId; } else if (p2pMessage.Version == P2PVersion.P2PV2) { p2pMessage.V2Header.Identifier = sequenceId; } } if (p2pMessage.Version == P2PVersion.P2PV1 && p2pMessage.V1Header.AckSessionId == 0) { p2pMessage.V1Header.AckSessionId = (uint)new Random().Next(50000, int.MaxValue); } if (p2pMessage.Version == P2PVersion.P2PV2 && p2pMessage.V2Header.PackageNumber == 0) { p2pMessage.V2Header.PackageNumber = packageNo; } P2PMessage[] msgs = p2pMessage.SplitMessage(MaxDataSize); if (p2pMessage.Version == P2PVersion.P2PV2) { // Correct local sequence no P2PMessage lastMsg = msgs[msgs.Length - 1]; SequenceId = lastMsg.V2Header.Identifier + lastMsg.V2Header.MessageSize; } if (ackHandler != null) { P2PMessage firstMessage = msgs[0]; RegisterAckHandler(new P2PAckMessageEventArgs(firstMessage, ackHandler, timeout)); } if (session != null) { session.LocalIdentifier = SequenceId; } return(msgs); }
/// <summary> /// Continue to send future messages to the specified <see cref="P2PSession"/>. /// </summary> /// <param name="session"></param> public virtual void ResumeSending(P2PSession session) { Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, String.Format("P2PBridge {0} resume sending for {1}", this.ToString(), session.SessionId), GetType().Name); lock (stoppedSessions) { if (stoppedSessions.Contains(session)) { stoppedSessions.Remove(session); ProcessSendQueues(); } else { Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, "Session not present in stopped list", GetType().Name); } } }
/// <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; }
public P2PSession AddTransfer(P2PApplication app) { P2PSession session = new P2PSession(app); session.Closed += P2PSessionClosed; if (app.P2PVersion == P2PVersion.P2PV2) { p2pV2Sessions.Add(session); } else { p2pV1Sessions.Add(session); } session.Invite(); return(session); }
private void P2PSessionClosed(object sender, ContactEventArgs args) { P2PSession session = sender as P2PSession; session.Closed -= P2PSessionClosed; Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, String.Format("P2PSession {0} closed, removing", session.SessionId), GetType().Name); if (session.Version == P2PVersion.P2PV2) { p2pV2Sessions.Remove(session); } else { p2pV1Sessions.Remove(session); } session.Dispose(); }
/// <summary> /// Check if the session is ready to begin sending packets. /// </summary> /// <param name="session"></param> /// <returns></returns> public virtual bool Ready(P2PSession session) { lock (stoppedSessions) { if (queueSize == 0) { return(IsOpen && (!stoppedSessions.Contains(session))); } lock (sendingQueues) { if (!sendingQueues.ContainsKey(session)) { return(IsOpen && SuitableFor(session) && (!stoppedSessions.Contains(session))); } return(IsOpen && (sendingQueues[session].Count < queueSize) && (!stoppedSessions.Contains(session))); } } }
internal P2PBridge GetBridge(P2PSession session) { foreach (P2PBridge existing in bridges) { if (existing.SuitableFor(session)) { return(existing); } } return(nsMessageHandler.SDGBridge); /*MSNP21TODO * P2PBridge bridge = new SBBridge(session); * bridge.BridgeClosed += BridgeClosed; * * bridges.Add(bridge); * * return bridge; * */ }
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); }
public P2PActivity(P2PSession p2pSess) : base(p2pSess.Version, p2pSess.Remote, p2pSess.RemoteContactEndPointID) { try { byte[] byts = Convert.FromBase64String(p2pSess.Invitation.BodyValues["Context"].Value); string activityUrl = System.Text.Encoding.Unicode.GetString(byts); string[] activityProperties = activityUrl.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); if (activityProperties.Length >= 3) { uint.TryParse(activityProperties[0], out applicationId); activityName = activityProperties[2]; } } catch (Exception ex) { Trace.WriteLineIf(Settings.TraceSwitch.TraceError, "An error occured while parsing activity context, error info: " + ex.Message, GetType().Name); } sending = false; }
protected override void SendOnePacket(P2PSession session, Contact remote, Guid remoteGuid, P2PMessage msg) { directConnection.SendMessage(msg, new P2PMessageSessionEventArgs(msg, session)); }
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; }
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(); } }
protected abstract void SendOnePacket(P2PSession session, Contact remote, Guid remoteGuid, P2PMessage msg);
/// <summary> /// Creates a new P2PApplication instance with the parameters provided. /// </summary> /// <param name="eufGuid"></param> /// <param name="appId"></param> /// <param name="withSession"></param> internal static P2PApplication CreateInstance(Guid eufGuid, uint appId, P2PSession withSession) { if (withSession != null && eufGuid != Guid.Empty && p2pAppCache.ContainsKey(eufGuid)) { if (appId != 0) { foreach (P2PApp app in p2pAppCache[eufGuid]) { if (appId == app.AppId) return (P2PApplication)Activator.CreateInstance(app.AppType, withSession); } } return (P2PApplication)Activator.CreateInstance(p2pAppCache[eufGuid][0].AppType, withSession); } return null; }
private P2PMessage[] SetSequenceNumberAndRegisterAck(P2PSession session, Contact remote, P2PMessage p2pMessage, AckHandler ackHandler, int timeout) { if (p2pMessage.Header.Identifier == 0) { if (p2pMessage.Version == P2PVersion.P2PV1) { p2pMessage.Header.Identifier = ++sequenceId; } else if (p2pMessage.Version == P2PVersion.P2PV2) { p2pMessage.V2Header.Identifier = sequenceId; } } if (p2pMessage.Version == P2PVersion.P2PV1 && p2pMessage.V1Header.AckSessionId == 0) { p2pMessage.V1Header.AckSessionId = (uint)new Random().Next(50000, int.MaxValue); } if (p2pMessage.Version == P2PVersion.P2PV2 && p2pMessage.V2Header.PackageNumber == 0) { p2pMessage.V2Header.PackageNumber = packageNo; } P2PMessage[] msgs = p2pMessage.SplitMessage(MaxDataSize); if (p2pMessage.Version == P2PVersion.P2PV2) { // Correct local sequence no P2PMessage lastMsg = msgs[msgs.Length - 1]; SequenceId = lastMsg.V2Header.Identifier + lastMsg.V2Header.MessageSize; } if (ackHandler != null) { P2PMessage firstMessage = msgs[0]; RegisterAckHandler(new P2PAckMessageEventArgs(firstMessage, ackHandler, timeout)); } if (session != null) { session.LocalIdentifier = SequenceId; } return msgs; }
public FileTransferForm(P2PSession p2pSess) { this.p2pSession = p2pSess; this.fileTransfer = p2pSess.Application as FileTransfer; InitializeComponent(); }
/// <summary> /// Check whether the P2P session can be transfer on the bridge. /// </summary> /// <param name="session"> /// The <see cref="P2PSession"/> needs to check. /// </param> /// <returns> /// A <see cref="System.Boolean"/> /// </returns> public virtual bool SuitableFor(P2PSession session) { Contact remote = Remote; return (session != null) && (remote != null) && (session.Remote.IsSibling(remote)); }
/// <summary> /// Stop sending future messages to the specified <see cref="P2PSession"/>. /// </summary> /// <param name="session"></param> public virtual void StopSending(P2PSession session) { Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, String.Format("P2PBridge {0} stop sending for {1}", this.ToString(), session.SessionId), GetType().Name); lock (stoppedSessions) { if (!stoppedSessions.Contains(session)) { stoppedSessions.Add(session); } else Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, "Session is already in stopped list", GetType().Name); } }
/// <summary> /// Send a P2P Message to the specified P2PSession. /// </summary> /// <param name="session"> /// The application layer, which is a <see cref="P2PSession"/> /// </param> /// <param name="remote"> /// he receiver <see cref="Contact"/> /// </param> /// <param name="remoteGuid"> /// A <see cref="Guid"/> /// </param> /// <param name="msg"> /// he <see cref="P2PMessage"/> to be sent. /// </param> /// <param name="ackTimeout"> /// The maximum time to wait for an ACK. <see cref="System.Int32"/> /// </param> /// <param name="ackHandler"> /// The <see cref="AckHandler"/> to handle the ACK. /// </param> public virtual void Send(P2PSession session, Contact remote, Guid remoteGuid, P2PMessage msg, int ackTimeout, AckHandler ackHandler) { if (remote == null) throw new ArgumentNullException("remote"); P2PMessage[] msgs = SetSequenceNumberAndRegisterAck(session, remote, msg, ackHandler, ackTimeout); if (session == null) { if (!IsOpen) { Trace.WriteLineIf(Settings.TraceSwitch.TraceError, "Send called with no session on a closed bridge", GetType().Name); return; } // Bypass queueing foreach (P2PMessage m in msgs) { SendOnePacket(null, remote, remoteGuid, m); } return; } if (!SuitableFor(session)) { Trace.WriteLineIf(Settings.TraceSwitch.TraceError, "Send called with a session this bridge is not suitable for", GetType().Name); return; } lock (sendQueues) { if (!sendQueues.ContainsKey(session)) sendQueues[session] = new P2PSendQueue(); } lock (sendQueues[session]) { foreach (P2PMessage m in msgs) sendQueues[session].Enqueue(remote, remoteGuid, m); } ProcessSendQueues(); }
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> /// /// </summary> /// <param name="session"></param> /// <param name="queue"></param> public virtual void AddQueue(P2PSession session, P2PSendQueue queue) { Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, String.Format("P2PBridge {0} received queue for session {1}", this.ToString(), session.SessionId), GetType().Name); if (sendQueues.ContainsKey(session)) { Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, "A queue is already present for this session, merging the queues", GetType().Name); lock (sendQueues[session]) { while (queue.Count > 0) sendQueues[session].Enqueue(queue.Dequeue()); } } else { lock (sendQueues) sendQueues[session] = queue; } ProcessSendQueues(); }
/// <summary> /// Send a P2P Message to the specified P2PSession. /// </summary> /// <param name="session"> /// The application layer, which is a <see cref="P2PSession"/>. /// </param> /// <param name="remote"> /// The receiver <see cref="Contact"/>. /// </param> /// <param name="remoteGuid"> /// A <see cref="Guid"/> /// </param> /// <param name="msg"> /// The <see cref="P2PMessage"/> to be sent. /// </param> public virtual void Send(P2PSession session, Contact remote, Guid remoteGuid, P2PMessage msg) { Send(session, remote, remoteGuid, msg, 0, null); }
internal bool HandleP2PSessionSignal(P2PBridge bridge, P2PMessage p2pMessage, SLPMessage slp, P2PSession session) { if (slp is SLPRequestMessage) { SLPRequestMessage slpRequest = slp as SLPRequestMessage; if (slpRequest.ContentType == "application/x-msnmsgr-sessionclosebody" && slpRequest.Method == "BYE") { if (p2pMessage.Version == P2PVersion.P2PV1) { P2PMessage byeAck = p2pMessage.CreateAcknowledgement(); byeAck.V1Header.Flags = P2PFlag.CloseSession; session.Send(byeAck); } else if (p2pMessage.Version == P2PVersion.P2PV2) { SLPRequestMessage slpMessage = new SLPRequestMessage(session.RemoteContactEPIDString, "BYE"); slpMessage.Target = session.RemoteContactEPIDString; slpMessage.Source = session.LocalContactEPIDString; slpMessage.Branch = session.Invitation.Branch; slpMessage.CallId = session.Invitation.CallId; slpMessage.ContentType = "application/x-msnmsgr-sessionclosebody"; slpMessage.BodyValues["SessionID"] = session.SessionId.ToString(System.Globalization.CultureInfo.InvariantCulture); session.Send(session.WrapSLPMessage(slpMessage)); } session.OnClosed(new ContactEventArgs(session.Remote)); return(true); } else { if (slpRequest.ContentType == "application/x-msnmsgr-transreqbody" || slpRequest.ContentType == "application/x-msnmsgr-transrespbody" || slpRequest.ContentType == "application/x-msnmsgr-transdestaddrupdate") { P2PSession.ProcessDirectInvite(slpRequest, nsMessageHandler, session); // Direct connection invite return(true); } } } else if (slp is SLPStatusMessage) { SLPStatusMessage slpStatus = slp as SLPStatusMessage; if (slpStatus.Code == 200) // OK { if (slpStatus.ContentType == "application/x-msnmsgr-transrespbody") { P2PSession.ProcessDirectInvite(slpStatus, nsMessageHandler, session); return(true); } else { if (session.Application != null) { session.OnActive(EventArgs.Empty); session.Application.Start(); return(true); } } } else if (slpStatus.Code == 603) // Decline { session.OnClosed(new ContactEventArgs(session.Remote)); return(true); } else if (slpStatus.Code == 500) // Internal Error { return(true); } } Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, String.Format("Unhandled SLP Message in session:---->>\r\n{0}", p2pMessage.ToString()), GetType().Name); session.OnError(EventArgs.Empty); return(true); }
/// <summary> /// Check if the session is ready to begin sending packets. /// </summary> /// <param name="session"></param> /// <returns></returns> public virtual bool Ready(P2PSession session) { lock (stoppedSessions) { if (queueSize == 0) return IsOpen && (!stoppedSessions.Contains(session)); lock (sendingQueues) { if (!sendingQueues.ContainsKey(session)) return IsOpen && SuitableFor(session) && (!stoppedSessions.Contains(session)); return IsOpen && (sendingQueues[session].Count < queueSize) && (!stoppedSessions.Contains(session)); } } }
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 override bool SuitableFor(P2PSession session) { return true; }
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; }
protected override void SendMultiPacket(P2PSession session, Contact remote, Guid remoteGuid, P2PMessage[] sendList) { if (remote == null) return; NSMessageProcessor nsmp = (NSMessageProcessor)NSMessageHandler.MessageProcessor; string to = ((int)remote.ClientType).ToString() + ":" + remote.Account; string from = ((int)NSMessageHandler.Owner.ClientType).ToString() + ":" + NSMessageHandler.Owner.Account; MultiMimeMessage mmMessage = new MultiMimeMessage(to, from); mmMessage.RoutingHeaders[MIMERoutingHeaders.From][MIMERoutingHeaders.EPID] = NSMessageHandler.MachineGuid.ToString("B").ToLowerInvariant(); mmMessage.RoutingHeaders[MIMERoutingHeaders.To][MIMERoutingHeaders.EPID] = remoteGuid.ToString("B").ToLowerInvariant(); mmMessage.RoutingHeaders[MIMERoutingHeaders.ServiceChannel] = "PE"; mmMessage.RoutingHeaders[MIMERoutingHeaders.Options] = "0"; mmMessage.ContentKeyVersion = "2.0"; mmMessage.ContentHeaders[MIMEContentHeaders.ContentType] = "application/x-msnmsgrp2p"; mmMessage.ContentHeaders[MIMEContentHeaders.ContentTransferEncoding] = "binary"; mmMessage.ContentHeaders[MIMEContentHeaders.MessageType] = MessageTypes.Data; List<string> bridgingOffsets = new List<string>(); List<object> userStates = new List<object>(); byte[] buffer = new byte[0]; foreach (P2PMessage p2pMessage in sendList) { SLPMessage slpMessage = p2pMessage.IsSLPData ? p2pMessage.InnerMessage as SLPMessage : null; if (slpMessage != null && ((slpMessage.ContentType == "application/x-msnmsgr-transreqbody" || slpMessage.ContentType == "application/x-msnmsgr-transrespbody" || slpMessage.ContentType == "application/x-msnmsgr-transdestaddrupdate"))) { SendOnePacket(session, remote, remoteGuid, p2pMessage); } else { bridgingOffsets.Add(buffer.Length.ToString()); buffer = NetworkMessage.AppendArray(buffer, p2pMessage.GetBytes(true)); int transId = nsmp.IncreaseTransactionID(); userStates.Add(transId); lock (p2pAckMessages) p2pAckMessages[transId] = new P2PMessageSessionEventArgs(p2pMessage, session); //mmMessage.ContentHeaders[MIMEContentHeaders.Pipe] = PackageNo.ToString(); } } if (buffer.Length > 0) { mmMessage.ContentHeaders[MIMEContentHeaders.BridgingOffsets] = String.Join(",", bridgingOffsets.ToArray()); mmMessage.InnerBody = buffer; int transId2 = nsmp.IncreaseTransactionID(); userStates.Add(transId2); NSMessage sdgPayload = new NSMessage("SDG"); sdgPayload.TransactionID = transId2; sdgPayload.InnerMessage = mmMessage; nsmp.Processor.Send(sdgPayload.GetBytes(), userStates.ToArray()); } }
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(); }
protected override void SendOnePacket(P2PSession session, Contact remote, Guid remoteGuid, P2PMessage p2pMessage) { if (remote == null) return; string to = ((int)remote.ClientType).ToString() + ":" + remote.Account; string from = ((int)NSMessageHandler.Owner.ClientType).ToString() + ":" + NSMessageHandler.Owner.Account; MultiMimeMessage mmMessage = new MultiMimeMessage(to, from); mmMessage.RoutingHeaders[MIMERoutingHeaders.From][MIMERoutingHeaders.EPID] = NSMessageHandler.MachineGuid.ToString("B").ToLowerInvariant(); mmMessage.RoutingHeaders[MIMERoutingHeaders.To][MIMERoutingHeaders.EPID] = remoteGuid.ToString("B").ToLowerInvariant(); mmMessage.RoutingHeaders[MIMERoutingHeaders.ServiceChannel] = "PE"; mmMessage.RoutingHeaders[MIMERoutingHeaders.Options] = "0"; mmMessage.ContentKeyVersion = "2.0"; SLPMessage slpMessage = p2pMessage.IsSLPData ? p2pMessage.InnerMessage as SLPMessage : null; if (slpMessage != null && ((slpMessage.ContentType == "application/x-msnmsgr-transreqbody" || slpMessage.ContentType == "application/x-msnmsgr-transrespbody" || slpMessage.ContentType == "application/x-msnmsgr-transdestaddrupdate"))) { mmMessage.ContentHeaders[MIMEContentHeaders.MessageType] = MessageTypes.SignalP2P; mmMessage.InnerBody = slpMessage.GetBytes(false); mmMessage.InnerMessage = slpMessage; } else { mmMessage.ContentHeaders[MIMEContentHeaders.ContentType] = "application/x-msnmsgrp2p"; mmMessage.ContentHeaders[MIMEContentHeaders.ContentTransferEncoding] = "binary"; mmMessage.ContentHeaders[MIMEContentHeaders.MessageType] = MessageTypes.Data; //mmMessage.ContentHeaders[MIMEContentHeaders.Pipe] = PackageNo.ToString(); mmMessage.ContentHeaders[MIMEContentHeaders.BridgingOffsets] = "0"; mmMessage.InnerBody = p2pMessage.GetBytes(true); mmMessage.InnerMessage = p2pMessage; } NSMessageProcessor nsmp = (NSMessageProcessor)NSMessageHandler.MessageProcessor; int transId = nsmp.IncreaseTransactionID(); lock (p2pAckMessages) p2pAckMessages[transId] = new P2PMessageSessionEventArgs(p2pMessage, session); NSMessage sdgPayload = new NSMessage("SDG"); sdgPayload.TransactionID = transId; sdgPayload.InnerMessage = mmMessage; nsmp.SendMessage(sdgPayload, sdgPayload.TransactionID); }
internal static void ProcessDirectInvite(SLPMessage slp, NSMessageHandler ns, P2PSession startupSession) { switch (slp.ContentType) { case "application/x-msnmsgr-transreqbody": ProcessDCReqInvite(slp, ns, startupSession); break; case "application/x-msnmsgr-transrespbody": ProcessDCRespInvite(slp, ns, startupSession); break; case "application/x-msnmsgr-transdestaddrupdate": ProcessDirectAddrUpdate(slp, ns, startupSession); break; } }
public override bool SuitableFor(P2PSession session) { if (base.SuitableFor(session) && session.RemoteContactEndPointID == RemoteEpId) { return true; } return false; }
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); }
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); }
protected override void SendMultiPacket(P2PSession session, Contact remote, Guid remoteGuid, P2PMessage[] sendList) { if (remote == null) { return; } NSMessageProcessor nsmp = (NSMessageProcessor)NSMessageHandler.MessageProcessor; string to = ((int)remote.ClientType).ToString() + ":" + remote.Account; string from = ((int)NSMessageHandler.Owner.ClientType).ToString() + ":" + NSMessageHandler.Owner.Account; MultiMimeMessage mmMessage = new MultiMimeMessage(to, from); mmMessage.RoutingHeaders[MIMERoutingHeaders.From][MIMERoutingHeaders.EPID] = NSMessageHandler.MachineGuid.ToString("B").ToLowerInvariant(); mmMessage.RoutingHeaders[MIMERoutingHeaders.To][MIMERoutingHeaders.EPID] = remoteGuid.ToString("B").ToLowerInvariant(); mmMessage.RoutingHeaders[MIMERoutingHeaders.ServiceChannel] = "PE"; mmMessage.RoutingHeaders[MIMERoutingHeaders.Options] = "0"; mmMessage.ContentKeyVersion = "2.0"; mmMessage.ContentHeaders[MIMEContentHeaders.ContentType] = "application/x-msnmsgrp2p"; mmMessage.ContentHeaders[MIMEContentHeaders.ContentTransferEncoding] = "binary"; mmMessage.ContentHeaders[MIMEContentHeaders.MessageType] = MessageTypes.Data; List <string> bridgingOffsets = new List <string>(); List <object> userStates = new List <object>(); byte[] buffer = new byte[0]; foreach (P2PMessage p2pMessage in sendList) { SLPMessage slpMessage = p2pMessage.IsSLPData ? p2pMessage.InnerMessage as SLPMessage : null; if (slpMessage != null && ((slpMessage.ContentType == "application/x-msnmsgr-transreqbody" || slpMessage.ContentType == "application/x-msnmsgr-transrespbody" || slpMessage.ContentType == "application/x-msnmsgr-transdestaddrupdate"))) { SendOnePacket(session, remote, remoteGuid, p2pMessage); } else { bridgingOffsets.Add(buffer.Length.ToString()); buffer = NetworkMessage.AppendArray(buffer, p2pMessage.GetBytes(true)); int transId = nsmp.IncreaseTransactionID(); userStates.Add(transId); lock (p2pAckMessages) p2pAckMessages[transId] = new P2PMessageSessionEventArgs(p2pMessage, session); //mmMessage.ContentHeaders[MIMEContentHeaders.Pipe] = PackageNo.ToString(); } } if (buffer.Length > 0) { mmMessage.ContentHeaders[MIMEContentHeaders.BridgingOffsets] = String.Join(",", bridgingOffsets.ToArray()); mmMessage.InnerBody = buffer; int transId2 = nsmp.IncreaseTransactionID(); userStates.Add(transId2); NSMessage sdgPayload = new NSMessage("SDG"); sdgPayload.TransactionID = transId2; sdgPayload.InnerMessage = mmMessage; nsmp.Processor.Send(sdgPayload.GetBytes(), userStates.ToArray()); } }
/// <summary> /// Continue to send future messages to the specified <see cref="P2PSession"/>. /// </summary> /// <param name="session"></param> public virtual void ResumeSending(P2PSession session) { Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, String.Format("P2PBridge {0} resume sending for {1}", this.ToString(), session.SessionId), GetType().Name); lock (stoppedSessions) { if (stoppedSessions.Contains(session)) { stoppedSessions.Remove(session); ProcessSendQueues(); } else Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, "Session not present in stopped list", GetType().Name); } }
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(); } } }
public override bool SuitableFor(P2PSession session) { return(true); }
internal bool HandleP2PSessionSignal(P2PBridge bridge, P2PMessage p2pMessage, SLPMessage slp, P2PSession session) { if (slp is SLPRequestMessage) { SLPRequestMessage slpRequest = slp as SLPRequestMessage; if (slpRequest.ContentType == "application/x-msnmsgr-sessionclosebody" && slpRequest.Method == "BYE") { if (p2pMessage.Version == P2PVersion.P2PV1) { P2PMessage byeAck = p2pMessage.CreateAcknowledgement(); byeAck.V1Header.Flags = P2PFlag.CloseSession; session.Send(byeAck); } else if (p2pMessage.Version == P2PVersion.P2PV2) { SLPRequestMessage slpMessage = new SLPRequestMessage(session.RemoteContactEPIDString, "BYE"); slpMessage.Target = session.RemoteContactEPIDString; slpMessage.Source = session.LocalContactEPIDString; slpMessage.Branch = session.Invitation.Branch; slpMessage.CallId = session.Invitation.CallId; slpMessage.ContentType = "application/x-msnmsgr-sessionclosebody"; slpMessage.BodyValues["SessionID"] = session.SessionId.ToString(System.Globalization.CultureInfo.InvariantCulture); session.Send(session.WrapSLPMessage(slpMessage)); } session.OnClosed(new ContactEventArgs(session.Remote)); return true; } else { if (slpRequest.ContentType == "application/x-msnmsgr-transreqbody" || slpRequest.ContentType == "application/x-msnmsgr-transrespbody" || slpRequest.ContentType == "application/x-msnmsgr-transdestaddrupdate") { P2PSession.ProcessDirectInvite(slpRequest, nsMessageHandler, session); // Direct connection invite return true; } } } else if (slp is SLPStatusMessage) { SLPStatusMessage slpStatus = slp as SLPStatusMessage; if (slpStatus.Code == 200) // OK { if (slpStatus.ContentType == "application/x-msnmsgr-transrespbody") { P2PSession.ProcessDirectInvite(slpStatus, nsMessageHandler, session); return true; } else { if (session.Application != null) { session.OnActive(EventArgs.Empty); session.Application.Start(); return true; } } } else if (slpStatus.Code == 603) // Decline { session.OnClosed(new ContactEventArgs(session.Remote)); return true; } else if (slpStatus.Code == 500) // Internal Error { return true; } } Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, String.Format("Unhandled SLP Message in session:---->>\r\n{0}", p2pMessage.ToString()), GetType().Name); session.OnError(EventArgs.Empty); return true; }
protected P2PApplication(P2PSession p2pSess) : this(p2pSess.Version, p2pSess.Remote, p2pSess.RemoteContactEndPointID) { P2PSession = p2pSess; // Register events Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo, "Application associated with session: " + p2pSess.SessionId, GetType().Name); }
public P2PSessionEventArgs(P2PSession session) { this.p2pSession = session; }
/// <summary> /// Move the specified <see cref="P2PSession"/> to the new <see cref="P2PBridge"/> specified. /// </summary> /// <param name="session"></param> /// <param name="newBridge"></param> public virtual void MigrateQueue(P2PSession session, P2PBridge newBridge) { Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, String.Format("P2PBridge {0} migrating session {1} queue to new bridge {2}", this.ToString(), session.SessionId, (newBridge != null) ? newBridge.ToString() : "null"), GetType().Name); P2PSendQueue newQueue = new P2PSendQueue(); lock (sendingQueues) { if (sendingQueues.ContainsKey(session)) { if (newBridge != null) { lock (sendingQueues[session]) { foreach (P2PSendItem item in sendingQueues[session]) newQueue.Enqueue(item); } } sendingQueues.Remove(session); } } lock (sendQueues) { if (sendQueues.ContainsKey(session)) { if (newBridge != null) { while (sendQueues[session].Count > 0) newQueue.Enqueue(sendQueues[session].Dequeue()); } sendQueues.Remove(session); } } lock (stoppedSessions) { if (stoppedSessions.Contains(session)) { stoppedSessions.Remove(session); } } if (newBridge != null) newBridge.AddQueue(session, newQueue); }