internal bool CheckSLPMessage(P2PBridge bridge, Contact source, Guid sourceGuid, P2PMessage msg, SLPMessage slp) { string src = source.Account.ToLowerInvariant(); string target = nsMessageHandler.Owner.Account; if (slp.FromEmailAccount.ToLowerInvariant() != src) { Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, String.Format("Received message from '{0}', differing from source '{1}'", slp.Source, src), GetType().Name); return false; } else if (slp.ToEmailAccount.ToLowerInvariant() != target) { Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, String.Format("Received P2P message intended for '{0}', not us '{1}'", slp.Target, target), GetType().Name); if (slp.FromEmailAccount == target) { Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, "We received a message from ourselves?", GetType().Name); } else { SendSLPStatus(bridge, msg, source, sourceGuid, 404, "Not Found"); } return false; } return true; }
internal bool CheckSLPMessage(P2PBridge bridge, Contact source, Guid sourceGuid, P2PMessage msg, SLPMessage slp) { string src = source.Account.ToLowerInvariant(); string target = nsMessageHandler.Owner.Account; if (slp.FromEmailAccount.ToLowerInvariant() != src) { Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, String.Format("Received message from '{0}', differing from source '{1}'", slp.Source, src), GetType().Name); return(false); } else if (slp.ToEmailAccount.ToLowerInvariant() != target) { Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, String.Format("Received P2P message intended for '{0}', not us '{1}'", slp.Target, target), GetType().Name); if (slp.FromEmailAccount == target) { Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, "We received a message from ourselves?", GetType().Name); } else { SendSLPStatus(bridge, msg, source, sourceGuid, 404, "Not Found"); } return(false); } return(true); }
/// <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); } }
/// <summary> /// /// </summary> /// <param name="bridge"></param> /// <param name="p2pMessage"></param> /// <returns></returns> public bool ProcessP2PData(P2PBridge bridge, P2PMessage p2pMessage) { ResetTimeoutTimer(); // Keep track of the remote identifier remoteIdentifier = (p2pMessage.Version == P2PVersion.P2PV2) ? p2pMessage.Header.Identifier + p2pMessage.Header.MessageSize : p2pMessage.Header.Identifier; if (status == P2PSessionStatus.Closed || status == P2PSessionStatus.Error) { Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, String.Format("P2PSession {0} received message whilst in '{1}' state", sessionId, status), GetType().Name); return(false); } if (p2pApplication == null) { Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, String.Format("P2PSession {0}: Received message for P2P app, but it's either been disposed or not created", sessionId), GetType().Name); return(false); } else { // Application data if (p2pMessage.Header.MessageSize > 0 && p2pMessage.Header.SessionId > 0) { bool reset = false; byte[] appData = new byte[0]; if (p2pMessage.Header.MessageSize == 4 && BitUtility.ToInt32(p2pMessage.InnerBody, 0, true) == 0) { reset = true; } else { appData = new byte[p2pMessage.InnerBody.Length]; Buffer.BlockCopy(p2pMessage.InnerBody, 0, appData, 0, appData.Length); } if (p2pMessage.Version == P2PVersion.P2PV2 && (TFCombination.First == (p2pMessage.V2Header.TFCombination & TFCombination.First))) { reset = true; } return(p2pApplication.ProcessData(bridge, appData, reset)); } return(false); } }
private void BridgeClosed(object sender, EventArgs args) { P2PBridge bridge = sender as P2PBridge; if (!bridges.Contains(bridge)) { Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, "Closed bridge not found in list", GetType().Name); return; } bridges.Remove(bridge); }
internal void SendSLPStatus(P2PBridge bridge, P2PMessage msg, Contact dest, Guid destGuid, int code, string phrase) { string target = dest.Account.ToLowerInvariant(); if (msg.Version == P2PVersion.P2PV2) { target += ";" + destGuid.ToString("B"); } SLPMessage slp = new SLPStatusMessage(target, code, phrase); if (msg.IsSLPData) { SLPMessage msgSLP = msg.InnerMessage as SLPMessage; slp.Branch = msgSLP.Branch; slp.CallId = msgSLP.CallId; slp.Source = msgSLP.Target; slp.ContentType = msgSLP.ContentType; if (msgSLP.BodyValues.ContainsKey("SessionID")) { slp.BodyValues["SessionID"] = msgSLP.BodyValues["SessionID"]; } } else { slp.ContentType = "null"; } P2PMessage response = new P2PMessage(msg.Version); response.InnerMessage = slp; if (msg.Version == P2PVersion.P2PV1) { response.V1Header.Flags = P2PFlag.MSNSLPInfo; } else if (msg.Version == P2PVersion.P2PV2) { response.V2Header.OperationCode = (byte)OperationCode.None; response.V2Header.TFCombination = TFCombination.First; } bridge.Send(null, dest, destGuid, response); }
private void Migrate(P2PBridge newBridge) { Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, String.Format("P2PSession {0} migrating from bridge {1} to {2}", sessionId, (p2pBridge != null) ? p2pBridge.ToString() : "null", (newBridge != null) ? newBridge.ToString() : "null"), GetType().Name); if (p2pBridge != null) { p2pBridge.BridgeOpened -= BridgeOpened; p2pBridge.BridgeSynced -= BridgeSynced; p2pBridge.BridgeClosed -= BridgeClosed; p2pBridge.BridgeSent -= BridgeSent; p2pBridge.MigrateQueue(this, newBridge); } p2pBridge = newBridge; if (p2pBridge != null) { p2pBridge.BridgeOpened += BridgeOpened; p2pBridge.BridgeSynced += BridgeSynced; p2pBridge.BridgeClosed += BridgeClosed; p2pBridge.BridgeSent += BridgeSent; if (localIdentifier == 0) { localBaseIdentifier = p2pBridge.SequenceId; localIdentifier = localBaseIdentifier; } else { p2pBridge.SequenceId = localIdentifier; } if ((directNegotiationTimer != null) & (p2pBridge is TCPv1Bridge)) { DirectNegotiationSuccessful(); } } }
/// <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 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); }
public override bool ProcessData(P2PBridge bridge, byte[] data, bool reset) { Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, "DATA RECEIVED: " + P2PMessage.DumpBytes(data, 128, true), GetType().Name); return true; }
public override bool ProcessData(P2PBridge bridge, byte[] data, bool reset) { if (sending) { // We are sender but remote client want to kill me :) return false; } if (reset) { // Data prep or TFCombination.First objStream.SetLength(0); } if (data.Length > 0) { objStream.Write(data, 0, data.Length); Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, String.Format("Received {0} / {1}", objStream.Length, msnObject.Size), GetType().Name); if (objStream.Length == msnObject.Size) { // Finished transfer byte[] allData = new byte[msnObject.Size]; objStream.Seek(0, SeekOrigin.Begin); objStream.Read(allData, 0, allData.Length); string dataSha = Convert.ToBase64String(new SHA1Managed().ComputeHash(allData)); if (dataSha != msnObject.Sha) { Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, "Object hash doesn't match data hash, data invalid", GetType().Name); return false; } MemoryStream ms = new MemoryStream(allData); ms.Position = 0; // Data CHECKSUM is ok, update MsnObject if (msnObject.ObjectType == MSNObjectType.UserDisplay) { DisplayImage newDisplayImage = new DisplayImage(Remote.Account.ToLowerInvariant(), ms); Remote.SetDisplayImageAndFireDisplayImageChangedEvent(newDisplayImage); msnObject = newDisplayImage; } else if (msnObject.ObjectType == MSNObjectType.Scene) { SceneImage newSceneImage = new SceneImage(Remote.Account.ToLowerInvariant(), ms); Remote.SetSceneImageAndFireSceneImageChangedEvent(newSceneImage); msnObject = newSceneImage; } else if (msnObject.ObjectType == MSNObjectType.Emoticon) { ((Emoticon)msnObject).Image = Image.FromStream(objStream); } else if (msnObject.ObjectType == MSNObjectType.Wink) { Stream s = ((Wink)msnObject).OpenStream(); s.Write(allData, 0, allData.Length); } objStream.Close(); OnTransferFinished(EventArgs.Empty); if (P2PSession != null) P2PSession.Close(); // Send first BYE } } return true; }
/// <summary> /// /// </summary> /// <param name="bridge"></param> /// <param name="data"></param> /// <param name="reset"></param> /// <returns></returns> public abstract bool ProcessData(P2PBridge bridge, byte[] data, bool reset);
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; }
internal void SendSLPStatus(P2PBridge bridge, P2PMessage msg, Contact dest, Guid destGuid, int code, string phrase) { string target = dest.Account.ToLowerInvariant(); if (msg.Version == P2PVersion.P2PV2) { target += ";" + destGuid.ToString("B"); } SLPMessage slp = new SLPStatusMessage(target, code, phrase); if (msg.IsSLPData) { SLPMessage msgSLP = msg.InnerMessage as SLPMessage; slp.Branch = msgSLP.Branch; slp.CallId = msgSLP.CallId; slp.Source = msgSLP.Target; slp.ContentType = msgSLP.ContentType; if (msgSLP.BodyValues.ContainsKey("SessionID")) { slp.BodyValues["SessionID"] = msgSLP.BodyValues["SessionID"]; } } else slp.ContentType = "null"; P2PMessage response = new P2PMessage(msg.Version); response.InnerMessage = slp; if (msg.Version == P2PVersion.P2PV1) { response.V1Header.Flags = P2PFlag.MSNSLPInfo; } else if (msg.Version == P2PVersion.P2PV2) { response.V2Header.OperationCode = (byte)OperationCode.None; response.V2Header.TFCombination = TFCombination.First; } bridge.Send(null, dest, destGuid, response); }
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; }
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> /// 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); }
public override bool ProcessData(P2PBridge bridge, byte[] data, bool reset) { if (_sending) { // We are sender but remote client want to kill me :) return false; } if (reset) { _dataStream.SetLength(0); } if (data.Length > 0) _dataStream.Write(data, 0, data.Length); OnProgressed(EventArgs.Empty); if (_dataStream.Length == (long)_context.FileSize) { // Finished transfer OnTransferFinished(EventArgs.Empty); P2PSession.Close(); } return true; }
private void Migrate(P2PBridge newBridge) { Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, String.Format("P2PSession {0} migrating from bridge {1} to {2}", sessionId, (p2pBridge != null) ? p2pBridge.ToString() : "null", (newBridge != null) ? newBridge.ToString() : "null"), GetType().Name); if (p2pBridge != null) { p2pBridge.BridgeOpened -= BridgeOpened; p2pBridge.BridgeSynced -= BridgeSynced; p2pBridge.BridgeClosed -= BridgeClosed; p2pBridge.BridgeSent -= BridgeSent; p2pBridge.MigrateQueue(this, newBridge); } p2pBridge = newBridge; if (p2pBridge != null) { p2pBridge.BridgeOpened += BridgeOpened; p2pBridge.BridgeSynced += BridgeSynced; p2pBridge.BridgeClosed += BridgeClosed; p2pBridge.BridgeSent += BridgeSent; if (localIdentifier == 0) { localBaseIdentifier = p2pBridge.SequenceId; localIdentifier = localBaseIdentifier; } else { p2pBridge.SequenceId = localIdentifier; } if ((directNegotiationTimer != null) & (p2pBridge is TCPv1Bridge)) DirectNegotiationSuccessful(); } }
/// <summary> /// /// </summary> /// <param name="bridge"></param> /// <param name="p2pMessage"></param> /// <returns></returns> public bool ProcessP2PData(P2PBridge bridge, P2PMessage p2pMessage) { ResetTimeoutTimer(); // Keep track of the remote identifier remoteIdentifier = (p2pMessage.Version == P2PVersion.P2PV2) ? p2pMessage.Header.Identifier + p2pMessage.Header.MessageSize : p2pMessage.Header.Identifier; if (status == P2PSessionStatus.Closed || status == P2PSessionStatus.Error) { Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, String.Format("P2PSession {0} received message whilst in '{1}' state", sessionId, status), GetType().Name); return false; } if (p2pApplication == null) { Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning, String.Format("P2PSession {0}: Received message for P2P app, but it's either been disposed or not created", sessionId), GetType().Name); return false; } else { // Application data if (p2pMessage.Header.MessageSize > 0 && p2pMessage.Header.SessionId > 0) { bool reset = false; byte[] appData = new byte[0]; if (p2pMessage.Header.MessageSize == 4 && BitUtility.ToInt32(p2pMessage.InnerBody, 0, true) == 0) { reset = true; } else { appData = new byte[p2pMessage.InnerBody.Length]; Buffer.BlockCopy(p2pMessage.InnerBody, 0, appData, 0, appData.Length); } if (p2pMessage.Version == P2PVersion.P2PV2 && (TFCombination.First == (p2pMessage.V2Header.TFCombination & TFCombination.First))) { reset = true; } return p2pApplication.ProcessData(bridge, appData, reset); } 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(); } }