Beispiel #1
0
        internal bool HandleRAK(Contact source, Guid sourceGuid, P2PMessage msg)
        {
            bool requireAck = false;

            if (msg.Header.RequireAck)
            {
                requireAck = true;

                P2PMessage ack = msg.CreateAcknowledgement();

                if (ack.Header.RequireAck)
                {
                    // SYN
                    Send(null, source, sourceGuid, ack, DefaultTimeout, delegate(P2PMessage sync)
                    {
                        SyncId = sync.Header.AckIdentifier;

                        Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo,
                                          String.Format("SYNC completed for: {0}", this), GetType().Name);
                    });
                }
                else
                {
                    // ACK
                    Send(null, source, sourceGuid, ack);
                }
            }

            return(requireAck);
        }
        public virtual void SendMessage(P2PMessage msg, P2PMessageSessionEventArgs se)
        {
            // if it is a regular message convert it
            P2PDCMessage p2pMessage = msg as P2PDCMessage;

            if (p2pMessage == null)
            {
                p2pMessage = new P2PDCMessage(msg);
            }

            // prepare the message
            p2pMessage.PrepareMessage();

            // this is very bloated!
            Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, "Outgoing message:\r\n" + p2pMessage.ToDebugString(), GetType().Name);

            if (dcSocket != null)
            {
                Processor.SendSocketData(dcSocket, p2pMessage.GetBytes(), se);
            }
            else
            {
                Processor.Send(p2pMessage.GetBytes(), se);
            }
        }
Beispiel #3
0
        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;
        }
Beispiel #4
0
 public void Add(Contact remote, Guid remoteGuid, P2PMessage message)
 {
     lock (this)
     {
         base.Add(new P2PSendItem(remote, remoteGuid, message));
     }
 }
        private P2PSession FindSessionByExpectedIdentifier(P2PMessage p2pMessage)
        {
            if (p2pMessage.Version == P2PVersion.P2PV2)
            {
                foreach (P2PSession session in p2pV2Sessions)
                {
                    uint expected = session.RemoteIdentifier;

                    if (p2pMessage.Header.Identifier == expected)
                    {
                        return(session);
                    }
                }
            }
            else
            {
                foreach (P2PSession session in p2pV1Sessions)
                {
                    uint expected = session.RemoteIdentifier + 1;
                    if (expected == session.RemoteBaseIdentifier)
                    {
                        expected++;
                    }

                    if (p2pMessage.Header.Identifier == expected)
                    {
                        return(session);
                    }
                }
            }

            return(null);
        }
Beispiel #6
0
        public void ProcessP2PMessage(Contact source, Guid sourceGuid, P2PMessage p2pMessage)
        {
            // HANDLE RAK: RAKs are session independent and mustn't be quoted on bridges.
            bool requireAck = HandleRAK(source, sourceGuid, p2pMessage);

            // HANDLE ACK: ACK/NAK to our RAK message
            if (HandleACK(p2pMessage))
            {
                return;
            }

            // PASS TO P2PHandler
            if (nsMessageHandler.P2PHandler.ProcessP2PMessage(this, source, sourceGuid, p2pMessage))
            {
                return;
            }

            if (!requireAck)
            {
                // UNHANDLED P2P MESSAGE
                Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning,
                                  String.Format("*******Unhandled P2P message ****** \r\n{0}", p2pMessage.ToDebugString()), GetType().Name);

                // Keep RemoteID Synchronized, I think we must track remoteIdentifier here...
                // Send NAK??????
            }
        }
Beispiel #7
0
        internal bool SendDirectInvite()
        {
            // Skip if we're currently using a TCPBridge.
            if (Remote.DirectBridge != null && Remote.DirectBridge.IsOpen)
            {
                return(false);
            }

            int        netId;
            string     connectionType = ConnectionType(nsMessageHandler, out netId);
            P2PMessage p2pMessage     = new P2PMessage(Version);

            Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo,
                              String.Format("Connection type set to {0} for session {1}", connectionType, SessionId.ToString()));

            // Create the message
            SLPRequestMessage slpMessage = new SLPRequestMessage(RemoteContactEPIDString, MSNSLPRequestMethod.INVITE);

            slpMessage.Source      = LocalContactEPIDString;
            slpMessage.CSeq        = 0;
            slpMessage.CallId      = Invitation.CallId;
            slpMessage.MaxForwards = 0;
            slpMessage.ContentType = "application/x-msnmsgr-transreqbody";

            slpMessage.BodyValues["Bridges"]            = "TCPv1 SBBridge";
            slpMessage.BodyValues["Capabilities-Flags"] = "1";
            slpMessage.BodyValues["NetID"]             = netId.ToString(CultureInfo.InvariantCulture);
            slpMessage.BodyValues["Conn-Type"]         = connectionType;
            slpMessage.BodyValues["TCP-Conn-Type"]     = connectionType;
            slpMessage.BodyValues["UPnPNat"]           = "false";                                   // UPNP Enabled
            slpMessage.BodyValues["ICF"]               = (connectionType == "Firewall").ToString(); // Firewall enabled
            slpMessage.BodyValues["Nat-Trav-Msg-Type"] = "WLX-Nat-Trav-Msg-Direct-Connect-Req";

            // We support Hashed-Nonce ( 2 way handshake )
            Remote.GenerateNewDCKeys();
            slpMessage.BodyValues["Hashed-Nonce"] = Remote.dcLocalHashedNonce.ToString("B").ToUpper(CultureInfo.InvariantCulture);

            p2pMessage.InnerMessage = slpMessage;

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

            // These 3 step is very important...
            // 1- Stop sending for this session on sdgbridge until we receive a response to the direct invite or the timeout expires
            nsMessageHandler.SDGBridge.StopSending(this);
            // 2- Setup a dc timer.
            SetupDCTimer();
            // 3- Don't pass p2psession to the sdg bridge. Because, sdgbridge stopped this session.
            nsMessageHandler.SDGBridge.Send(null /*must be null to bypass queueing*/,
                                            Remote, RemoteContactEndPointID, p2pMessage);

            return(true);
        }
        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);
        }
Beispiel #9
0
        public void Send(P2PMessage p2pMessage, int ackTimeout, AckHandler ackHandler)
        {
            ResetTimeoutTimer();

            if (p2pBridge == null)
            {
                MigrateToOptimalBridge();
            }

            p2pBridge.Send(this, Remote, RemoteContactEndPointID, p2pMessage, ackTimeout, ackHandler);
        }
Beispiel #10
0
        public P2PAckMessageEventArgs(P2PMessage p2pMessage, AckHandler ackHandler, int timeoutSec)
            : base(p2pMessage)
        {
            this.ackHandler = ackHandler;
            this.deleteTick = timeoutSec;

            if (timeoutSec != 0)
            {
                AddSeconds(timeoutSec);
            }
        }
Beispiel #11
0
        public P2PAckMessageEventArgs(P2PMessage p2pMessage, AckHandler ackHandler, int timeoutSec)
            : base(p2pMessage)
        {
            this.ackHandler = ackHandler;
            this.deleteTick = timeoutSec;

            if (timeoutSec != 0)
            {
                AddSeconds(timeoutSec);
            }
        }
Beispiel #12
0
        /// <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);
            }
        }
Beispiel #13
0
        /// <summary>
        /// Creates an acknowledgement message to this message.
        /// </summary>
        /// <returns></returns>
        public virtual P2PMessage CreateAcknowledgement()
        {
            P2PMessage ack = new P2PMessage(Version);

            ack.Header = Header.CreateAck();

            if (Version == P2PVersion.P2PV1)
            {
                ack.Footer = Footer;                    //Keep the same as the message to acknowladge.
            }

            return(ack);
        }
Beispiel #14
0
        public P2PMessage(P2PMessage message)
            : this(message.Version)
        {
            Header.SessionId     = message.Header.SessionId;
            Header.Identifier    = message.Header.Identifier;
            Header.TotalSize     = message.Header.TotalSize;
            Header.MessageSize   = message.Header.MessageSize;
            Header.AckIdentifier = message.Header.AckIdentifier;

            if (message.Version == P2PVersion.P2PV1)
            {
                V1Header.Offset       = message.V1Header.Offset;
                V1Header.Flags        = message.V1Header.Flags;
                V1Header.AckSessionId = message.V1Header.AckSessionId;
                V1Header.AckTotalSize = message.V1Header.AckTotalSize;
            }
            else if (message.Version == P2PVersion.P2PV2)
            {
                V2Header.OperationCode = message.V2Header.OperationCode;
                V2Header.TFCombination = message.V2Header.TFCombination;
                V2Header.PackageNumber = message.V2Header.PackageNumber;
                V2Header.DataRemaining = message.V2Header.DataRemaining;

                if (message.V2Header.HeaderTLVs.Count > 0)
                {
                    foreach (KeyValuePair <byte, byte[]> keyvalue in message.V2Header.HeaderTLVs)
                    {
                        V2Header.HeaderTLVs[keyvalue.Key] = keyvalue.Value;
                    }
                }
                if (message.V2Header.DataPacketTLVs.Count > 0)
                {
                    foreach (KeyValuePair <byte, byte[]> keyvalue in message.V2Header.DataPacketTLVs)
                    {
                        V2Header.DataPacketTLVs[keyvalue.Key] = keyvalue.Value;
                    }
                }
            }

            if (message.InnerMessage != null)
            {
                InnerMessage = message.InnerMessage;
            }

            if (message.InnerBody != null)
            {
                InnerBody = message.InnerBody;
            }

            Footer = message.Footer;
        }
Beispiel #15
0
        public bool Contains(P2PMessage msg)
        {
            lock (this)
            {
                foreach (P2PSendItem item in this)
                {
                    if (item.P2PMessage == msg)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Beispiel #16
0
        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);
        }
Beispiel #17
0
        internal P2PMessage WrapSLPMessage(SLPMessage slpMessage)
        {
            P2PMessage p2pMessage = new P2PMessage(Version);

            p2pMessage.InnerMessage = slpMessage;

            if (Version == P2PVersion.P2PV2)
            {
                p2pMessage.V2Header.TFCombination = TFCombination.First;
                p2pMessage.V2Header.PackageNumber = ++Bridge.PackageNo;
            }
            else if (Version == P2PVersion.P2PV1)
            {
                p2pMessage.V1Header.Flags = P2PFlag.MSNSLPInfo;
            }

            return(p2pMessage);
        }
Beispiel #18
0
        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);
        }
Beispiel #19
0
        /// <summary>
        /// Closes the session.
        /// </summary>
        public void Close()
        {
            if (status == P2PSessionStatus.Closing)
            {
                Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning,
                                  String.Format("P2PSession {0} was already closing, forcing unclean closure", SessionId), GetType().Name);

                OnClosed(new ContactEventArgs(Local));
            }
            else
            {
                OnClosing(new ContactEventArgs(Local));

                SLPRequestMessage slpMessage = new SLPRequestMessage(RemoteContactEPIDString, "BYE");
                slpMessage.Target                  = RemoteContactEPIDString;
                slpMessage.Source                  = LocalContactEPIDString;
                slpMessage.Branch                  = invitation.Branch;
                slpMessage.CallId                  = invitation.CallId;
                slpMessage.MaxForwards             = 0;
                slpMessage.ContentType             = "application/x-msnmsgr-sessionclosebody";
                slpMessage.BodyValues["SessionID"] = SessionId.ToString(System.Globalization.CultureInfo.InvariantCulture);

                P2PMessage p2pMessage = new P2PMessage(Version);
                if (version == P2PVersion.P2PV1)
                {
                    p2pMessage.V1Header.Flags = P2PFlag.MSNSLPInfo;
                }
                else if (version == P2PVersion.P2PV2)
                {
                    p2pMessage.V2Header.OperationCode = (byte)OperationCode.RAK;
                    p2pMessage.V2Header.TFCombination = TFCombination.First;
                    p2pMessage.V2Header.PackageNumber = ++p2pBridge.PackageNo;
                }

                p2pMessage.InnerMessage = slpMessage;

                Send(p2pMessage, delegate(P2PMessage ack)
                {
                    OnClosed(new ContactEventArgs(Local));
                });
            }
        }
Beispiel #20
0
        /// <summary>
        /// Sends invitation message if initiated locally. Sets remote identifiers after ack received.
        /// </summary>
        public void Invite()
        {
            if (status != P2PSessionStatus.WaitingForRemote)
            {
                Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning,
                                  String.Format("Invite called, but we're not waiting for the remote client (State {0})", status), GetType().Name);
            }
            else
            {
                // Get id from bridge....
                {
                    MigrateToOptimalBridge();
                    localBaseIdentifier = p2pBridge.SequenceId;
                    localIdentifier     = localBaseIdentifier;
                }

                P2PMessage p2pMessage = WrapSLPMessage(invitation);

                if (version == P2PVersion.P2PV2)
                {
                    if (p2pBridge.Synced == false)
                    {
                        p2pMessage.V2Header.OperationCode = (byte)(OperationCode.SYN | OperationCode.RAK);
                        p2pMessage.V2Header.AppendPeerInfoTLV();

                        Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo,
                                          String.Format("{0} invitation sending with SYN+RAK op...", SessionId), GetType().Name);
                    }
                }

                p2pMessage.InnerMessage = invitation;

                Send(p2pMessage, delegate(P2PMessage ack)
                {
                    remoteBaseIdentifier = ack.Header.Identifier;
                    remoteIdentifier     = remoteBaseIdentifier;

                    Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo,
                                      String.Format("{0} invitation sent with SYN+RAK op and received RemoteBaseIdentifier is: {1}", SessionId, remoteIdentifier), GetType().Name);
                });
            }
        }
Beispiel #21
0
        public P2PMessage[] CreateFromOffsets(long[] offsets, byte[] allData)
        {
            List <P2PMessage> messages = new List <P2PMessage>(offsets.Length);
            long offset = allData.Length;

            for (int i = offsets.Length - 1; i >= 0; i--)
            {
                P2PMessage m      = new P2PMessage(Version);
                long       length = offset - offsets[i];
                byte[]     part   = new byte[length];
                Array.Copy(allData, offsets[i], part, 0, length);
                m.ParseBytes(part);
                offset -= length;

                messages.Add(m);
            }
            messages.Reverse();

            return(messages.ToArray());
        }
Beispiel #22
0
        public static Guid CreateGuidFromData(P2PVersion ver, byte[] data)
        {
            Guid ret = Guid.Empty;

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

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

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

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

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

            return ret;
        }
Beispiel #23
0
        /// <summary>
        /// Rejects the received invitation.
        /// </summary>
        public void Decline()
        {
            if (status != P2PSessionStatus.WaitingForLocal)
            {
                Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning,
                                  String.Format("Declined called, but we're not waiting for the local client (State {0})", status), GetType().Name);
            }
            else
            {
                Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo, String.Format("{0} declined", SessionId), GetType().Name);

                SLPStatusMessage slpMessage = new SLPStatusMessage(RemoteContactEPIDString, 603, "Decline");
                slpMessage.Target                  = RemoteContactEPIDString;
                slpMessage.Source                  = LocalContactEPIDString;
                slpMessage.Branch                  = invitation.Branch;
                slpMessage.CallId                  = invitation.CallId;
                slpMessage.CSeq                    = 1;
                slpMessage.ContentType             = "application/x-msnmsgr-sessionreqbody";
                slpMessage.BodyValues["SessionID"] = SessionId.ToString(System.Globalization.CultureInfo.InvariantCulture);

                P2PMessage p2pMessage = new P2PMessage(Version);
                if (version == P2PVersion.P2PV1)
                {
                    p2pMessage.V1Header.Flags = P2PFlag.MSNSLPInfo;
                }
                else if (version == P2PVersion.P2PV2)
                {
                    p2pMessage.V2Header.OperationCode = (byte)OperationCode.RAK;
                    p2pMessage.V2Header.TFCombination = TFCombination.First;
                    p2pMessage.V2Header.PackageNumber = ++Bridge.PackageNo;
                }

                p2pMessage.InnerMessage = slpMessage;

                Send(p2pMessage);
                Close();
            }
        }
Beispiel #24
0
        public void Remove(P2PMessage msg)
        {
            lock (this)
            {
                P2PSendItem?removeItem = null;

                foreach (P2PSendItem item in this)
                {
                    if (item.P2PMessage == msg)
                    {
                        removeItem = item;
                        break;
                    }
                }

                if (removeItem != null)
                {
                    Remove(removeItem.Value);
                    return;
                }
            }

            throw new ArgumentException("msg not found in queue");
        }
Beispiel #25
0
        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());
            }
        }
Beispiel #26
0
 public void Enqueue(Contact remote, Guid remoteGuid, P2PMessage message)
 {
     base.Enqueue(new P2PSendItem(remote, remoteGuid, message));
 }
Beispiel #27
0
        /// <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();
        }
Beispiel #28
0
 public P2PDataMessage(P2PMessage copy)
     : base(copy)
 {
 }
Beispiel #29
0
        internal bool HandleRAK(Contact source, Guid sourceGuid, P2PMessage msg)
        {
            bool requireAck = false;

            if (msg.Header.RequireAck)
            {
                requireAck = true;

                P2PMessage ack = msg.CreateAcknowledgement();

                if (ack.Header.RequireAck)
                {
                    // SYN
                    Send(null, source, sourceGuid, ack, DefaultTimeout, delegate(P2PMessage sync)
                    {
                        SyncId = sync.Header.AckIdentifier;

                        Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo,
                            String.Format("SYNC completed for: {0}", this), GetType().Name);
                    });
                }
                else
                {
                    // ACK
                    Send(null, source, sourceGuid, ack);
                }
            }

            return requireAck;
        }
Beispiel #30
0
        private static void ProcessDCRespInvite(SLPMessage message, NSMessageHandler ns, P2PSession startupSession)
        {
            MimeDictionary bodyValues = message.BodyValues;

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

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

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

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

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

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

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

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

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

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

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

                    return;
                }
            }

            if (startupSession != null)
                startupSession.DirectNegotiationFailed();
        }
Beispiel #31
0
        /// <summary>
        /// Split big P2PMessages to transport over sb or dc.
        /// </summary>
        /// <param name="maxSize"></param>
        /// <returns></returns>
        public P2PMessage[] SplitMessage(int maxSize)
        {
            uint payloadMessageSize = 0;

            if (Version == P2PVersion.P2PV1)
            {
                payloadMessageSize = V1Header.MessageSize;
            }

            if (Version == P2PVersion.P2PV2)
            {
                payloadMessageSize = (uint)V2Header.MessageSize - (uint)V2Header.DataPacketHeaderLength;
            }

            if (payloadMessageSize <= maxSize)
            {
                return new P2PMessage[] { this }
            }
            ;

            List <P2PMessage> chunks = new List <P2PMessage>();

            byte[] totalMessage = (InnerBody != null)
                ? InnerBody
                : InnerMessage.GetBytes();

            long offset = 0;

            if (Version == P2PVersion.P2PV1)
            {
                while (offset < totalMessage.LongLength)
                {
                    P2PMessage chunkMessage = new P2PMessage(Version);
                    uint       messageSize  = (uint)Math.Min((uint)maxSize, (totalMessage.LongLength - offset));
                    byte[]     chunk        = new byte[messageSize];
                    Buffer.BlockCopy(totalMessage, (int)offset, chunk, 0, (int)messageSize);

                    chunkMessage.V1Header.Flags         = V1Header.Flags;
                    chunkMessage.V1Header.AckIdentifier = V1Header.AckIdentifier;
                    chunkMessage.V1Header.AckTotalSize  = V1Header.AckTotalSize;
                    chunkMessage.V1Header.Identifier    = V1Header.Identifier;
                    chunkMessage.V1Header.SessionId     = V1Header.SessionId;
                    chunkMessage.V1Header.TotalSize     = V1Header.TotalSize;
                    chunkMessage.V1Header.Offset        = (ulong)offset;
                    chunkMessage.V1Header.MessageSize   = messageSize;
                    chunkMessage.InnerBody = chunk;

                    chunkMessage.V1Header.AckSessionId = V1Header.AckSessionId;

                    chunkMessage.Footer = Footer;

                    chunkMessage.PrepareMessage();
                    chunks.Add(chunkMessage);

                    offset += messageSize;
                }
            }


            if (Version == P2PVersion.P2PV2)
            {
                uint nextId = Header.Identifier;

                long dataRemain = (long)V2Header.DataRemaining;
                while (offset < totalMessage.LongLength)
                {
                    P2PMessage chunkMessage = new P2PMessage(Version);
                    int        maxDataSize  = maxSize;

                    if (offset == 0 && V2Header.HeaderTLVs.Count > 0)
                    {
                        foreach (KeyValuePair <byte, byte[]> keyvalue in V2Header.HeaderTLVs)
                        {
                            chunkMessage.V2Header.HeaderTLVs[keyvalue.Key] = keyvalue.Value;
                        }

                        maxDataSize = maxSize - chunkMessage.V2Header.HeaderLength;
                    }


                    uint dataSize = (uint)Math.Min((uint)maxDataSize, (totalMessage.LongLength - offset));

                    byte[] chunk = new byte[dataSize];
                    Buffer.BlockCopy(totalMessage, (int)offset, chunk, 0, (int)dataSize);

                    if (offset == 0)
                    {
                        chunkMessage.V2Header.OperationCode = V2Header.OperationCode;
                    }

                    chunkMessage.V2Header.SessionId     = V2Header.SessionId;
                    chunkMessage.V2Header.TFCombination = V2Header.TFCombination;
                    chunkMessage.V2Header.PackageNumber = V2Header.PackageNumber;

                    if (totalMessage.LongLength + dataRemain - (dataSize + offset) > 0)
                    {
                        chunkMessage.V2Header.DataRemaining = (ulong)(totalMessage.LongLength + dataRemain - (dataSize + offset));
                    }

                    if ((offset != 0) &&
                        TFCombination.First == (V2Header.TFCombination & TFCombination.First))
                    {
                        chunkMessage.V2Header.TFCombination = (TFCombination)(V2Header.TFCombination - TFCombination.First);
                    }

                    chunkMessage.InnerBody         = chunk;
                    chunkMessage.Header.Identifier = nextId;
                    nextId += chunkMessage.Header.MessageSize;

                    chunks.Add(chunkMessage);

                    offset += dataSize;
                }
            }

            return(chunks.ToArray());
        }
Beispiel #32
0
 /// <summary>
 /// Sends a P2P message.
 /// </summary>
 /// <param name="p2pMessage"></param>
 public void SendMessage(P2PMessage p2pMessage)
 {
     SendMessage(p2pMessage, 0, null);
 }
Beispiel #33
0
        /// <summary>
        /// Sends a message with the specified <see cref="P2PMessage"/> and <see cref="AckHandler"/>.
        /// </summary>
        public virtual void SendMessage(P2PMessage p2pMessage, int ackTimeout, AckHandler ackHandler)
        {
            Debug.Assert(p2pMessage.Version == version);

            p2pMessage.Header.SessionId = p2pSession.SessionId;

            // If not an ack, set the footer (p2pv1 only)
            if (p2pMessage.Version == P2PVersion.P2PV1 && (p2pMessage.V1Header.Flags & P2PFlag.Acknowledgement) != P2PFlag.Acknowledgement)
                p2pMessage.Footer = ApplicationId;

            p2pSession.Send(p2pMessage, ackTimeout, ackHandler);
        }
Beispiel #34
0
        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;
        }
Beispiel #35
0
 protected abstract void SendOnePacket(P2PSession session, Contact remote, Guid remoteGuid, P2PMessage msg);
Beispiel #36
0
        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);
        }
Beispiel #37
0
        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);
        }
Beispiel #38
0
        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);
        }
Beispiel #39
0
        internal bool SendDirectInvite()
        {
            // Skip if we're currently using a TCPBridge.
            if (Remote.DirectBridge != null && Remote.DirectBridge.IsOpen)
                return false;

            int netId;
            string connectionType = ConnectionType(nsMessageHandler, out netId);
            P2PMessage p2pMessage = new P2PMessage(Version);

            Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo,
                String.Format("Connection type set to {0} for session {1}", connectionType, SessionId.ToString()));

            // Create the message
            SLPRequestMessage slpMessage = new SLPRequestMessage(RemoteContactEPIDString, MSNSLPRequestMethod.INVITE);
            slpMessage.Source = LocalContactEPIDString;
            slpMessage.CSeq = 0;
            slpMessage.CallId = Invitation.CallId;
            slpMessage.MaxForwards = 0;
            slpMessage.ContentType = "application/x-msnmsgr-transreqbody";

            slpMessage.BodyValues["Bridges"] = "TCPv1 SBBridge";
            slpMessage.BodyValues["Capabilities-Flags"] = "1";
            slpMessage.BodyValues["NetID"] = netId.ToString(CultureInfo.InvariantCulture);
            slpMessage.BodyValues["Conn-Type"] = connectionType;
            slpMessage.BodyValues["TCP-Conn-Type"] = connectionType;
            slpMessage.BodyValues["UPnPNat"] = "false"; // UPNP Enabled
            slpMessage.BodyValues["ICF"] = (connectionType == "Firewall").ToString(); // Firewall enabled
            slpMessage.BodyValues["Nat-Trav-Msg-Type"] = "WLX-Nat-Trav-Msg-Direct-Connect-Req";

            // We support Hashed-Nonce ( 2 way handshake )
            Remote.GenerateNewDCKeys();
            slpMessage.BodyValues["Hashed-Nonce"] = Remote.dcLocalHashedNonce.ToString("B").ToUpper(CultureInfo.InvariantCulture);

            p2pMessage.InnerMessage = slpMessage;

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

            // These 3 step is very important...
            // 1- Stop sending for this session on sdgbridge until we receive a response to the direct invite or the timeout expires
            nsMessageHandler.SDGBridge.StopSending(this);
            // 2- Setup a dc timer.
            SetupDCTimer();
            // 3- Don't pass p2psession to the sdg bridge. Because, sdgbridge stopped this session.
            nsMessageHandler.SDGBridge.Send(null /*must be null to bypass queueing*/,
                Remote, RemoteContactEndPointID, p2pMessage);

            return true;
        }
Beispiel #40
0
 /// <summary>
 /// Copy constructor. Creates a shallow copy of the properties of the P2PMessage.
 /// </summary>
 /// <param name="message"></param>
 public P2PDCMessage(P2PMessage message)
     : base(message)
 {
 }
Beispiel #41
0
        private static void ProcessDCReqInvite(SLPMessage message, NSMessageHandler ns, P2PSession startupSession)
        {
            if (startupSession != null && startupSession.Bridge != null &&
                startupSession.Bridge is TCPv1Bridge)
            {
                return; // We are using a dc bridge already. Don't allow second one.
            }

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

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

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

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

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

                P2PVersion ver = message.P2PVersion;

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

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

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

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

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

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

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

                if (startupSession != null)
                {
                    startupSession.SetupDCTimer();
                    startupSession.Bridge.Send(null, startupSession.Remote, startupSession.RemoteContactEndPointID, p2pMessage);
                }
                else
                {
                    ns.SDGBridge.Send(null, remote, remoteGuid, p2pMessage);
                }
            }
            else
            {
                if (startupSession != null)
                    startupSession.DirectNegotiationFailed();
            }
        }
Beispiel #42
0
        public P2PMessage(P2PMessage message)
            : this(message.Version)
        {
            Header.SessionId = message.Header.SessionId;
            Header.Identifier = message.Header.Identifier;
            Header.TotalSize = message.Header.TotalSize;
            Header.MessageSize = message.Header.MessageSize;
            Header.AckIdentifier = message.Header.AckIdentifier;

            if (message.Version == P2PVersion.P2PV1)
            {
                V1Header.Offset = message.V1Header.Offset;
                V1Header.Flags = message.V1Header.Flags;
                V1Header.AckSessionId = message.V1Header.AckSessionId;
                V1Header.AckTotalSize = message.V1Header.AckTotalSize;
            }
            else if (message.Version == P2PVersion.P2PV2)
            {
                V2Header.OperationCode = message.V2Header.OperationCode;
                V2Header.TFCombination = message.V2Header.TFCombination;
                V2Header.PackageNumber = message.V2Header.PackageNumber;
                V2Header.DataRemaining = message.V2Header.DataRemaining;

                if (message.V2Header.HeaderTLVs.Count > 0)
                {
                    foreach (KeyValuePair<byte, byte[]> keyvalue in message.V2Header.HeaderTLVs)
                    {
                        V2Header.HeaderTLVs[keyvalue.Key] = keyvalue.Value;
                    }
                }
                if (message.V2Header.DataPacketTLVs.Count > 0)
                {
                    foreach (KeyValuePair<byte, byte[]> keyvalue in message.V2Header.DataPacketTLVs)
                    {
                        V2Header.DataPacketTLVs[keyvalue.Key] = keyvalue.Value;
                    }
                }
            }

            if (message.InnerMessage != null)
                InnerMessage = message.InnerMessage;

            if (message.InnerBody != null)
                InnerBody = message.InnerBody;

            Footer = message.Footer;
        }
Beispiel #43
0
 protected virtual void SendMultiPacket(P2PSession session, Contact remote, Guid remoteGuid, P2PMessage[] sendList)
 {
     foreach (P2PMessage p2pMessage in sendList)
     {
         SendOnePacket(session, remote, remoteGuid, p2pMessage);
     }
 }
Beispiel #44
0
 protected override void SendOnePacket(P2PSession session, Contact remote, Guid remoteGuid, P2PMessage msg)
 {
     directConnection.SendMessage(msg, new P2PMessageSessionEventArgs(msg, session));
 }
Beispiel #45
0
 public void Send(P2PMessage p2pMessage, AckHandler ackHandler)
 {
     Send(p2pMessage, P2PBridge.DefaultTimeout, ackHandler);
 }
Beispiel #46
0
 protected override void SendOnePacket(P2PSession session, Contact remote, Guid remoteGuid, P2PMessage msg)
 {
     directConnection.SendMessage(msg, new P2PMessageSessionEventArgs(msg, session));
 }
Beispiel #47
0
 /// <summary>
 /// Copy constructor. Creates a shallow copy of the properties of the P2PMessage.
 /// </summary>
 /// <param name="message"></param>
 public P2PDCMessage(P2PMessage message)
     : base(message)
 {
 }
Beispiel #48
0
        /// <summary>
        /// Buffers incompleted P2PMessage SLP messages. Ignores data and control messages. 
        /// </summary>
        /// <param name="p2pMessage"></param>
        /// <returns>
        /// true if the P2PMessage is buffering (not completed) or invalid packet received;
        /// false if the p2p message fully buffered or no need to buffer.
        /// </returns>
        public bool BufferMessage(ref P2PMessage p2pMessage)
        {
            // P2PV1 and P2PV2 check
            if (p2pMessage.Header.MessageSize == 0 || // Ack message or Unsplitted
                p2pMessage.Header.SessionId > 0) // Data message
            {
                return false; // No need to buffer
            }

            // P2PV2 pooling
            if (p2pMessage.Version == P2PVersion.P2PV2)
            {
                if ((p2pMessage.V2Header.TFCombination == TFCombination.First && p2pMessage.V2Header.DataRemaining == 0) || // Unsplitted SLP message or data preparation message
                    (p2pMessage.V2Header.TFCombination > TFCombination.First)) // Data message
                {
                    return false; // No need to buffer
                }

                // First splitted SLP message.
                if (p2pMessage.V2Header.TFCombination == TFCombination.First &&
                    p2pMessage.V2Header.DataRemaining > 0)
                {
                    P2PMessage totalMessage = new P2PMessage(p2pMessage); // Copy it
                    ulong totalSize = (ulong)(p2pMessage.V2Header.MessageSize - p2pMessage.V2Header.DataPacketHeaderLength) +
                        p2pMessage.V2Header.DataRemaining;

                    totalMessage.InnerBody = new byte[totalSize]; // Allocate buffer as needed
                    Array.Copy(p2pMessage.InnerBody, 0, totalMessage.InnerBody, (long)0, (long)p2pMessage.InnerBody.Length);

                    lock (incompletedP2PV2Messages)
                        incompletedP2PV2Messages[p2pMessage.V2Header.Identifier + p2pMessage.V2Header.MessageSize] = totalMessage;

                    return true; // Buffering
                }

                // Other splitted SLP messages
                if (p2pMessage.V2Header.TFCombination == TFCombination.None)
                {
                    lock (incompletedP2PV2Messages)
                    {
                        if (incompletedP2PV2Messages.ContainsKey(p2pMessage.V2Header.Identifier))
                        {
                            if (incompletedP2PV2Messages[p2pMessage.V2Header.Identifier].V2Header.PackageNumber == p2pMessage.V2Header.PackageNumber)
                            {
                                P2PMessage totalMessage = incompletedP2PV2Messages[p2pMessage.V2Header.Identifier];
                                ulong dataSize = Math.Min(((ulong)(p2pMessage.V2Header.MessageSize - p2pMessage.V2Header.DataPacketHeaderLength)), totalMessage.V2Header.DataRemaining);
                                ulong offSet = ((ulong)totalMessage.InnerBody.LongLength) - totalMessage.V2Header.DataRemaining;

                                // Check range and buffer overflow...
                                if (((p2pMessage.V2Header.DataRemaining + (ulong)dataSize) == totalMessage.V2Header.DataRemaining) &&
                                    (ulong)(dataSize + offSet + p2pMessage.V2Header.DataRemaining) == (ulong)totalMessage.InnerBody.LongLength)
                                {
                                    Array.Copy(p2pMessage.InnerBody, 0, totalMessage.InnerBody, (long)offSet, (long)dataSize);
                                    uint originalIdentifier = p2pMessage.V2Header.Identifier;
                                    uint newIdentifier = p2pMessage.V2Header.Identifier + p2pMessage.V2Header.MessageSize;

                                    totalMessage.V2Header.DataRemaining = p2pMessage.V2Header.DataRemaining;
                                    totalMessage.V2Header.Identifier = newIdentifier;

                                    if (originalIdentifier != newIdentifier)
                                    {
                                        incompletedP2PV2Messages.Remove(originalIdentifier);
                                    }

                                    // Don't debug p2p inner packet (SLP) here.
                                    Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo,
                                        " Buffering splitted SLP message! DataRemaining:" + totalMessage.V2Header.DataRemaining +
                                        " NewIdentifier: " + newIdentifier);

                                    if (p2pMessage.V2Header.DataRemaining > 0)
                                    {
                                        // Don't debug p2p packet here. Because it hasn't completed yet and SLPMessage.Parse() fails...
                                        incompletedP2PV2Messages[newIdentifier] = totalMessage;
                                        return true; // Buffering
                                    }
                                    else // Last part
                                    {
                                        totalMessage.InnerBody = totalMessage.InnerBody; // Refresh... DataRemaining=0 deletes data headers.
                                        totalMessage.V2Header.Identifier = newIdentifier - totalMessage.Header.MessageSize;

                                        Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo,
                                            "A splitted message was combined :\r\n" +
                                            totalMessage.ToDebugString());

                                        p2pMessage = totalMessage;
                                        return false; // We have the whole message
                                    }
                                }
                            }

                            // Invalid packet received!!! Ignore and delete it...
                            incompletedP2PV2Messages.Remove(p2pMessage.V2Header.Identifier);

                            Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning,
                                "INVALID P2PV2 PACKET received!!! Ignored and deleted:\r\n" +
                                p2pMessage.ToDebugString());
                        }
                    }
                }
            }
            else // P2PV1 pooling
            {
                if ((p2pMessage.V1Header.MessageSize == p2pMessage.V1Header.TotalSize) || // Whole data
                    ((p2pMessage.V1Header.Flags & P2PFlag.Data) == P2PFlag.Data)) // Data message
                {
                    return false; // No need to buffer
                }

                lock (incompletedP2PV1Messages)
                {
                    if (false == incompletedP2PV1Messages.ContainsKey(p2pMessage.Header.Identifier))
                    {
                        byte[] totalPayload = new byte[p2pMessage.V1Header.TotalSize];
                        Array.Copy(p2pMessage.InnerBody, 0, totalPayload, (long)p2pMessage.V1Header.Offset, (long)p2pMessage.V1Header.MessageSize);
                        P2PMessage copyMessage = new P2PMessage(p2pMessage);

                        copyMessage.InnerBody = totalPayload;
                        copyMessage.V1Header.Offset = p2pMessage.V1Header.Offset + p2pMessage.V1Header.MessageSize;

                        incompletedP2PV1Messages[p2pMessage.Header.Identifier] = copyMessage;
                        return true; // Buffering
                    }

                    P2PMessage totalMessage = incompletedP2PV1Messages[p2pMessage.Header.Identifier];
                    if (p2pMessage.V1Header.TotalSize == totalMessage.V1Header.TotalSize &&
                        (p2pMessage.V1Header.Offset + p2pMessage.V1Header.MessageSize) <= totalMessage.Header.TotalSize)
                    {
                        Array.Copy(p2pMessage.InnerBody, 0, totalMessage.InnerBody, (long)p2pMessage.V1Header.Offset, (long)p2pMessage.V1Header.MessageSize);
                        totalMessage.V1Header.Offset = p2pMessage.V1Header.Offset + p2pMessage.V1Header.MessageSize;

                        // Last packet
                        if (totalMessage.V1Header.Offset == p2pMessage.V1Header.TotalSize)
                        {
                            totalMessage.V1Header.Offset = 0;
                            incompletedP2PV1Messages.Remove(p2pMessage.Header.Identifier);

                            p2pMessage = totalMessage;
                            return false; // We have the whole message
                        }

                        return true; // Buffering
                    }

                    // Invalid packet received!!! Ignore and delete it...
                    incompletedP2PV1Messages.Remove(p2pMessage.Header.Identifier);

                    Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning,
                        "INVALID P2PV1 PACKET received!!! Ignored and deleted:\r\n" +
                        p2pMessage.ToDebugString());
                }
            }

            return true; // Invalid packet, don't kill me.
        }
Beispiel #49
0
 public P2PSendItem(Contact remote, Guid remoteGuid, P2PMessage message)
 {
     Remote     = remote;
     RemoteGuid = remoteGuid;
     P2PMessage = message;
 }
Beispiel #50
0
 public P2PMessageEventArgs(P2PMessage p2pMessage)
 {
     this.p2pMessage = p2pMessage;
 }
Beispiel #51
0
        internal bool HandleACK(P2PMessage p2pMessage)
        {
            bool isAckOrNak = false;

            if (p2pMessage.Header.IsAcknowledgement || p2pMessage.Header.IsNegativeAck)
            {
                P2PAckMessageEventArgs e = null;
                uint ackNakId = 0;
                isAckOrNak = true;

                if (p2pMessage.Version == P2PVersion.P2PV1)
                {
                    lock (ackHandlersV1)
                    {
                        if (ackHandlersV1.ContainsKey(p2pMessage.Header.AckIdentifier))
                        {
                            ackNakId = p2pMessage.Header.AckIdentifier;
                            e = ackHandlersV1[ackNakId];
                            ackHandlersV1.Remove(ackNakId);
                        }
                    }
                }
                else if (p2pMessage.Version == P2PVersion.P2PV2)
                {
                    lock (ackHandlersV2)
                    {
                        if (ackHandlersV2.ContainsKey(p2pMessage.Header.AckIdentifier))
                        {
                            ackNakId = p2pMessage.Header.AckIdentifier;
                            e = ackHandlersV2[ackNakId];
                            ackHandlersV2.Remove(ackNakId);
                        }
                        else if (ackHandlersV2.ContainsKey(p2pMessage.V2Header.NakIdentifier))
                        {
                            ackNakId = p2pMessage.V2Header.NakIdentifier;
                            e = ackHandlersV2[ackNakId];
                            ackHandlersV2.Remove(ackNakId);
                        }
                    }
                }

                if (ackNakId == 0)
                {
                    Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning,
                        String.Format("!!!!!! No AckHandler registered for ack/nak {0}:\r\n{1}", p2pMessage.Header.AckIdentifier, p2pMessage.ToDebugString()), GetType().Name);
                }
                else
                {
                    if (e != null && e.AckHandler != null)
                    {
                        e.AckHandler(p2pMessage);
                    }
                    else
                    {
                        Trace.WriteLineIf(Settings.TraceSwitch.TraceWarning,
                            String.Format("!!!!!! No AckHandler pair for ack {0}\r\n{1}", ackNakId, p2pMessage.ToDebugString()), GetType().Name);
                    }
                }
            }

            return isAckOrNak;
        }
Beispiel #52
0
        public override void Start()
        {
            base.Start();

            if (Sending)
            {
                ushort packNum = ++base.P2PSession.Bridge.PackageNo;

                // Data prep
                P2PDataMessage prepData = new P2PDataMessage(P2PVersion);
                prepData.WritePreparationBytes();

                if (P2PVersion == P2PVersion.P2PV2)
                {
                    prepData.V2Header.TFCombination = TFCombination.First;
                }

                SendMessage(prepData);

                Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose,
                    "Data prep sent. Sending whole data...", GetType().Name);

                // All chunks
                byte[] allData = new byte[msnObject.Size];
                lock (objStream)
                {
                    using (Stream s = objStream)
                    {
                        s.Position = 0;
                        s.Read(allData, 0, allData.Length);
                    }
                }

                P2PDataMessage msg = new P2PDataMessage(P2PVersion);
                if (P2PVersion == P2PVersion.P2PV1)
                {
                    msg.V1Header.Flags = P2PFlag.Data;
                    msg.V1Header.AckSessionId = (uint)new Random().Next(50, int.MaxValue);
                }
                else if (P2PVersion == P2PVersion.P2PV2)
                {
                    msg.V2Header.TFCombination = TFCombination.MsnObject | TFCombination.First;
                    msg.V2Header.PackageNumber = packNum;
                }

                msg.InnerBody = allData;

                if (P2PVersion == P2PVersion.P2PV1)
                {
                    // Object transfer must be finish in MaxTimeout seconds. (p2pv1)
                    // Because ack is received after transfer finished.
                    SendMessage(msg, P2PBridge.MaxTimeout, delegate(P2PMessage ack)
                    {
                        OnTransferFinished(EventArgs.Empty);
                        // Close after remote client sends BYE.
                    });
                }
                else
                {
                    SendMessage(msg, 0, null);

                    // Register the ACKHandler
                    P2PMessage rak = new P2PMessage(P2PVersion);
                    SendMessage(rak, P2PBridge.DefaultTimeout, delegate(P2PMessage ack)
                    {
                        OnTransferFinished(EventArgs.Empty);
                        // Close after remote client sends BYE.
                    });
                }
            }
            else
            {
                objStream = new MemoryStream();
            }
        }
Beispiel #53
0
        /// <summary>
        /// Creates an acknowledgement message to this message.
        /// </summary>
        /// <returns></returns>
        public virtual P2PMessage CreateAcknowledgement()
        {
            P2PMessage ack = new P2PMessage(Version);
            ack.Header = Header.CreateAck();

            if (Version == P2PVersion.P2PV1)
            {
                ack.Footer = Footer;                    //Keep the same as the message to acknowladge.

            }

            return ack;
        }
        public virtual void SendMessage(P2PMessage msg, P2PMessageSessionEventArgs se)
        {
            // if it is a regular message convert it
            P2PDCMessage p2pMessage = msg as P2PDCMessage;
            if (p2pMessage == null)
            {
                p2pMessage = new P2PDCMessage(msg);
            }

            // prepare the message
            p2pMessage.PrepareMessage();

            // this is very bloated!
            Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, "Outgoing message:\r\n" + p2pMessage.ToDebugString(), GetType().Name);

            if (dcSocket != null)
                Processor.SendSocketData(dcSocket, p2pMessage.GetBytes(), se);
            else
                Processor.Send(p2pMessage.GetBytes(), se);
        }
        private void OnSDGDataMessageReceived(MultiMimeMessage multiMimeMessage, Contact sender, Contact by, RoutingInfo routingInfo)
        {
            Guid senderEPID = routingInfo.SenderEndPointID;
            P2PVersion p2pVer = senderEPID == Guid.Empty ? P2PVersion.P2PV1 : P2PVersion.P2PV2;

            string[] offsets = multiMimeMessage.ContentHeaders.ContainsKey(MIMEContentHeaders.BridgingOffsets) ?
                multiMimeMessage.ContentHeaders[MIMEContentHeaders.BridgingOffsets].ToString().Split(',') :
                new string[] { "0" };
            List<long> offsetList = new List<long>();
            foreach (string os in offsets)
            {
                offsetList.Add(long.Parse(os));
            }

            P2PMessage p2pData = new P2PMessage(p2pVer);
            P2PMessage[] p2pDatas = p2pData.CreateFromOffsets(offsetList.ToArray(), multiMimeMessage.InnerBody);

            if (multiMimeMessage.ContentHeaders.ContainsKey(MIMEContentHeaders.Pipe))
            {
                SDGBridge.PackageNo = ushort.Parse(multiMimeMessage.ContentHeaders[MIMEContentHeaders.Pipe]);
            }

            foreach (P2PMessage m in p2pDatas)
            {
                SDGBridge.ProcessP2PMessage(sender, senderEPID, m);
            }
        }
Beispiel #56
0
        public P2PMessage[] CreateFromOffsets(long[] offsets, byte[] allData)
        {
            List<P2PMessage> messages = new List<P2PMessage>(offsets.Length);
            long offset = allData.Length;
            for (int i = offsets.Length - 1; i >= 0; i--)
            {
                P2PMessage m = new P2PMessage(Version);
                long length = offset - offsets[i];
                byte[] part = new byte[length];
                Array.Copy(allData, offsets[i], part, 0, length);
                m.ParseBytes(part);
                offset -= length;

                messages.Add(m);
            }
            messages.Reverse();

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

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

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

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

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

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

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

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

                    return(true);
                }

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

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

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

                // Keep track of theremoteIdentifier

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

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

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

            return(false);
        }
Beispiel #58
0
 public P2PDataMessage(P2PMessage copy)
     : base(copy)
 {
 }
Beispiel #59
0
        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;
        }
Beispiel #60
0
        /// <summary>
        /// Split big P2PMessages to transport over sb or dc.
        /// </summary>
        /// <param name="maxSize"></param>
        /// <returns></returns>
        public P2PMessage[] SplitMessage(int maxSize)
        {
            uint payloadMessageSize = 0;

            if (Version == P2PVersion.P2PV1)
            {
                payloadMessageSize = V1Header.MessageSize;
            }

            if (Version == P2PVersion.P2PV2)
            {
                payloadMessageSize = (uint)V2Header.MessageSize - (uint)V2Header.DataPacketHeaderLength;
            }

            if (payloadMessageSize <= maxSize)
                return new P2PMessage[] { this };

            List<P2PMessage> chunks = new List<P2PMessage>();
            byte[] totalMessage = (InnerBody != null)
                ? InnerBody
                : InnerMessage.GetBytes();

            long offset = 0;

            if (Version == P2PVersion.P2PV1)
            {
                while (offset < totalMessage.LongLength)
                {
                    P2PMessage chunkMessage = new P2PMessage(Version);
                    uint messageSize = (uint)Math.Min((uint)maxSize, (totalMessage.LongLength - offset));
                    byte[] chunk = new byte[messageSize];
                    Buffer.BlockCopy(totalMessage, (int)offset, chunk, 0, (int)messageSize);

                    chunkMessage.V1Header.Flags = V1Header.Flags;
                    chunkMessage.V1Header.AckIdentifier = V1Header.AckIdentifier;
                    chunkMessage.V1Header.AckTotalSize = V1Header.AckTotalSize;
                    chunkMessage.V1Header.Identifier = V1Header.Identifier;
                    chunkMessage.V1Header.SessionId = V1Header.SessionId;
                    chunkMessage.V1Header.TotalSize = V1Header.TotalSize;
                    chunkMessage.V1Header.Offset = (ulong)offset;
                    chunkMessage.V1Header.MessageSize = messageSize;
                    chunkMessage.InnerBody = chunk;

                    chunkMessage.V1Header.AckSessionId = V1Header.AckSessionId;

                    chunkMessage.Footer = Footer;

                    chunkMessage.PrepareMessage();
                    chunks.Add(chunkMessage);

                    offset += messageSize;
                }
            }

            if (Version == P2PVersion.P2PV2)
            {
                uint nextId = Header.Identifier;
                long dataRemain = (long)V2Header.DataRemaining;
                while (offset < totalMessage.LongLength)
                {
                    P2PMessage chunkMessage = new P2PMessage(Version);
                    int maxDataSize = maxSize;

                    if (offset == 0 && V2Header.HeaderTLVs.Count > 0)
                    {
                        foreach (KeyValuePair<byte, byte[]> keyvalue in V2Header.HeaderTLVs)
                        {
                            chunkMessage.V2Header.HeaderTLVs[keyvalue.Key] = keyvalue.Value;
                        }

                        maxDataSize = maxSize - chunkMessage.V2Header.HeaderLength;
                    }

                    uint dataSize = (uint)Math.Min((uint)maxDataSize, (totalMessage.LongLength - offset));

                    byte[] chunk = new byte[dataSize];
                    Buffer.BlockCopy(totalMessage, (int)offset, chunk, 0, (int)dataSize);

                    if (offset == 0)
                    {
                        chunkMessage.V2Header.OperationCode = V2Header.OperationCode;
                    }

                    chunkMessage.V2Header.SessionId = V2Header.SessionId;
                    chunkMessage.V2Header.TFCombination = V2Header.TFCombination;
                    chunkMessage.V2Header.PackageNumber = V2Header.PackageNumber;

                    if (totalMessage.LongLength + dataRemain - (dataSize + offset) > 0)
                    {
                        chunkMessage.V2Header.DataRemaining = (ulong)(totalMessage.LongLength + dataRemain - (dataSize + offset));
                    }

                    if ((offset != 0) &&
                        TFCombination.First == (V2Header.TFCombination & TFCombination.First))
                    {
                        chunkMessage.V2Header.TFCombination = (TFCombination)(V2Header.TFCombination - TFCombination.First);
                    }

                    chunkMessage.InnerBody = chunk;
                    chunkMessage.Header.Identifier = nextId;
                    nextId += chunkMessage.Header.MessageSize;

                    chunks.Add(chunkMessage);

                    offset += dataSize;
                }
            }

            return chunks.ToArray();
        }