示例#1
0
 /// <summary>
 /// Handles an incoming connection request.
 /// </summary>
 /// <param name="ep">The source of the request.</param>
 /// <param name="accept">A function to call to accept the connection request.</param>
 protected override void HandleConnection(ErebusEndpoint ep, Func <Stream> accept) => htsm.RunSafe(() =>
 {
     foreach (var h in htsm.RunSafe(() => invitationHandlers.ToArray()))
     {
         h(this, new SSMPInvitationReceivedEventArgs(ep.Address, () =>
         {
             Connected = true;
             var s     = accept();
             r         = new BinaryReader(s, Encoding.UTF8, true);
             w         = new BinaryWriter(s, Encoding.UTF8, true);
             return(this);
         }));
         if (Connected)
         {
             recvTask = recvProcess();
             return;
         }
     }
 });
示例#2
0
        /// <summary>
        /// Sends a connection request to the given destination on the given port.
        /// </summary>
        /// <param name="ep">The destination.</param>
        /// <returns>A stream for sending and receiving data over the connection, or null if the connection was denied.</returns>
        protected Stream RequestConnection(ErebusEndpoint ep)
        {
            Log.RecordEvent(this, $"Connecting to {ep}...", LogEntrySeverity.Info);
            ei.SendPacket(ep, new byte[] { 0 }.Concat(localId.ToByteArray()).ToArray());
            byte type = 0;

            byte[] recv = waitRecv12(ei, int.MaxValue, ep.Port, b =>
            {
                type = b;
                return(b == 1 || b == 2);
            }, localId);
            if (type == 2)
            {
                return(null);
            }
            remoteId = new Guid(recv);
            retrieveKeys(ep.Address);
            Log.RecordEvent(this, $"Connected to {ep} with local GUID {localId} and remote GUID {remoteId}", LogEntrySeverity.Info);
            Endpoint = ep;
            return(createStream(ep));
        }
示例#3
0
 /// <summary>
 /// Sends a packet to the specified destination on the specified port.
 /// </summary>
 /// <param name="ep">The destination of the packet.</param>
 /// <param name="data">The contents of the packet.</param>
 protected void SendPacket(ErebusEndpoint ep, byte[] data) => ei.SendPacket(ep, data);
示例#4
0
        static internal void HandlePacket(Packet packet, ErebusInstance instance)
        {
            try {
                if (packet.Data.Length == 0)
                {
                    Log.RecordEvent(typeof(BCPProtocolBase), $"BCP packet from {packet.Source} is empty.", LogEntrySeverity.Error);
                    return;
                }
                switch (packet.Data[0])
                {
                case 0:
                    ErebusEndpoint ep = new ErebusEndpoint(packet.Source, packet.Port);
                    if (packet.Data.Length != 17)
                    {
                        Log.RecordEvent(typeof(BCPProtocolBase), $"BCP connection request packet from {ep} is an invalid size!", LogEntrySeverity.Warning);
                    }
                    BCPProtocolBase p;
                    try
                    {
                        p          = ptsm.RunSafe(() => protocols[packet.Port])(instance);
                        p.remoteId = new Guid(packet.Data.Skip(1).ToArray());
                    }
                    catch (KeyNotFoundException)
                    {
                        Log.RecordEvent(typeof(BCPProtocolBase), $"No protocol is associated with port {packet.Port}!", LogEntrySeverity.Warning);
                        instance.SendPacket(ep, new byte[] { 2 }.Concat(packet.Data.Skip(1)).ToArray());
                        return;
                    }
                    try
                    {
                        bool accepted = false;
                        p.Endpoint = ep;
                        p.HandleConnection(ep, () =>
                        {
                            accepted = true;
                            instance.SendPacket(ep, new byte[] { 1 }.Concat(p.remoteId.ToByteArray()).Concat(p.localId.ToByteArray()).ToArray());
                            Log.RecordEvent(p, $"Connected to {ep} with local GUID {p.localId} and remote GUID {p.remoteId}", LogEntrySeverity.Info);
                            p.retrieveKeys(packet.Source);
                            return(p.createStream(ep));
                        });
                        if (!accepted)
                        {
                            instance.SendPacket(ep, new byte[] { 2 }.Concat(p.remoteId.ToByteArray()).ToArray());
                        }
                    }
                    catch (Exception e)
                    {
                        Log.RecordEvent(typeof(BCPProtocolBase), $"Error calling connection handler on {p.GetType()}: {e.Message}", LogEntrySeverity.Error);
                    }
                    break;

                case 3:
                    var i = itsm.RunSafe(() => instanceData[instance]);
                    i.TSM.RunSafe(() =>
                    {
                        Guid id   = new Guid(packet.Data.Range(1, 16).ToArray());
                        ulong pos = BitConverter.ToUInt64(packet.Data.Range(17, 8).ToArray(), 0);
                        var data  = packet.Data.Skip(25).ToArray();
                        var cp    = i.CurrentPositions[id];
                        if (pos < cp)
                        {
                            Log.RecordEvent(typeof(BCPProtocolBase), "BCP packet received for known data.", LogEntrySeverity.Warning);
                        }
                        else
                        {
                            var oflow    = i.Overflow3[id];
                            var newOflow = new byte?[Math.Max((int)((ulong)data.Length + pos - cp), oflow.Length)];
                            Array.Copy(oflow, newOflow, oflow.Length);
                            Array.Copy(data.Cast <byte?>().ToArray(), 0, newOflow, (int)(pos - cp), data.Length);
                            i.Overflow3[id] = newOflow;
                            refresh3(i, id, packet.Port);
                        }
                    });
                    break;

                default:
                    var itm = itsm.RunSafe(() => instanceData[instance]);
                    itm.TSM.RunSafe(() =>
                    {
                        var data = packet.Data.Skip(17).ToArray();
                        foreach (var c in (from d in itm.Callbacks12 where d.Item1 == packet.Port && d.Item3 == new Guid(packet.Data.Range(1, 16).ToArray()) && d.Item4(packet.Data[0]) select d).ToArray())
                        {
                            itm.Callbacks12.Remove(c);
                            c.Item5(data.Range(0, Math.Min(data.Length, c.Item2)).ToArray());
                            if (c.Item2 <= data.Length)
                            {
                                data = data.Skip(c.Item2).ToArray();
                            }
                            else
                            {
                                data = new byte[0];
                            }
                            if (data.Length == 0)
                            {
                                break;
                            }
                        }
                        if (data.Length != 0)
                        {
                            itm.Overflow12.AddLast(new Tuple <ushort, byte, Guid, byte[]>(packet.Port, packet.Data[0], new Guid(packet.Data.Range(1, 16).ToArray()), data));
                        }
                    });
                    break;
                }
            }
            catch (Exception e)
            {
                Log.RecordEvent(typeof(BCPProtocolBase), $"Exception in BCP main packet handler: {e.Message}", LogEntrySeverity.Error);
            }
        }
示例#5
0
 /// <summary>
 /// Handles an incoming connection request.
 /// </summary>
 /// <param name="ep">The source of the request.</param>
 /// <param name="accept">A function to call to accept the request and retrieve a stream for communication.</param>
 abstract protected void HandleConnection(ErebusEndpoint ep, Func <Stream> accept);
示例#6
0
 Stream createStream(ErebusEndpoint ep) => new EncryptionNegotiator().Negotiate(new BCPStream(data => stsm.RunSafe(() =>
 {
     ei.SendPacket(ep, new byte[] { 3 }.Concat(remoteId.ToByteArray()).Concat(BitConverter.GetBytes(sendPos)).Concat(data).ToArray());
     sendPos += (ulong)data.Length;
 }), l => waitRecv3(ei, l, ep.Port, localId), myKey, otherKey));