示例#1
0
        private void HandleGatewayTunnelRequest(
            II2NPHeader msg,
            IEnumerable <AesEGBuildRequestRecord> records,
            EGBuildRequestRecord myrec,
            BuildRequestRecord drec)
        {
            var tunnel   = new GatewayTunnel(drec);
            var replykey = drec.ReplyKey.Key.Clone();
            var replyiv  = drec.ReplyIV.Clone();

            tunnel.EstablishedTime.SetNow();

            var doaccept = AcceptingTunnels(drec);

            var response = doaccept ? BuildResponseRecord.RequestResponse.Accept : BuildResponseRecord.DefaultErrorReply;

            Logging.LogDebug(() => string.Format("HandleGatewayTunnelRequest {3}: {0} Gateway tunnel request: {1} for tunnel id {2}.",
                                                 tunnel.Destination.Id32Short,
                                                 response,
                                                 tunnel.ReceiveTunnelId,
                                                 tunnel.TunnelDebugTrace));
            TunnelProvider.UpdateTunnelBuildReply(records, myrec, replykey, replyiv, response);

            if (response == BuildResponseRecord.RequestResponse.Accept)
            {
                AddTunnel(tunnel);
                TunnelMgr.AddExternalTunnel(tunnel);
                AcceptedTunnelBuildRequest(drec);
            }
            TransportProvider.Send(tunnel.Destination, msg.Message);
        }
        private void HandleEndpointTunnelRequest(
            II2NPHeader msg,
            IEnumerable <AesEGBuildRequestRecord> records,
            EGBuildRequestRecord myrec,
            BuildRequestRecord drec)
        {
            var tunnel   = new EndpointTunnel(drec);
            var replykey = drec.ReplyKey.Key.Clone();
            var replyiv  = drec.ReplyIV.Clone();

            tunnel.EstablishedTime.SetNow();

            var doaccept = AcceptingTunnels(drec);

            var response = doaccept ? BuildResponseRecord.RequestResponse.Accept : BuildResponseRecord.DefaultErrorReply;

            DebugUtils.LogDebug(() => string.Format("HandleEndpointTunnelRequest {3}: {0} Endpoint tunnel request: {1} for tunnel id {2}.",
                                                    tunnel.Destination.Id32Short,
                                                    response,
                                                    tunnel.ReceiveTunnelId,
                                                    tunnel.TunnelDebugTrace));
            TunnelProvider.UpdateTunnelBuildReply(records, myrec, replykey, replyiv, response);

            var responsemessage = new VariableTunnelBuildReplyMessage(records.Select(r => new BuildResponseRecord(r)));
            var buildreplymsg   = new TunnelGatewayMessage(responsemessage.GetHeader16(tunnel.ResponseMessageId), tunnel.ResponseTunnelId);

            if (response == BuildResponseRecord.RequestResponse.Accept)
            {
                AddTunnel(tunnel);
                TunnelMgr.AddExternalTunnel(tunnel);
                AcceptedTunnelBuildRequest(drec);
            }
            TransportProvider.Send(tunnel.Destination, buildreplymsg);
        }
示例#3
0
        /*
         * Exploration
         *
         * Exploration is a special form of netdb lookup, where a router attempts to learn about new routers.
         * It does this by sending a floodfill router a I2NP DatabaseLookupMessage, looking for a random key.
         * As this lookup will fail, the floodfill would normally respond with a I2NP DatabaseSearchReplyMessage
         * containing hashes of floodfill routers close to the key. This would not be helpful, as the requesting
         * router probably already knows those floodfills, and it would be impractical to add ALL floodfill
         * routers to the "don't include" field of the lookup. For an exploration query, the requesting router
         * adds a router hash of all zeros to the "don't include" field of the DatabaseLookupMessage.
         *
         * The floodfill will then respond only with non-floodfill routers close to the requested key.
         *
         * https://geti2p.net/en/docs/how/network-database
         *
         *  11  => exploration lookup, return DatabaseSearchReplyMessage
         *          containing non-floodfill routers only (replaces an
         *          excludedPeer of all zeroes)
         * https://geti2p.net/spec/i2np#databaselookup
         */
        void ExplorationRouterLookup()
        {
            I2PIdentHash ident = new I2PIdentHash(true);

            var ff = NetDb.Inst.GetClosestFloodfill(ident, 10, null, false)
                     .Shuffle()
                     .Take(DatabaseLookupSelectFloodfillCount)
                     .ToArray();

            foreach (var oneff in ff)
            {
                var msg = new DatabaseLookupMessage(
                    ident,
                    RouterContext.Inst.MyRouterIdentity.IdentHash,
                    DatabaseLookupMessage.LookupTypes.Exploration,
                    new I2PIdentHash[] { new I2PIdentHash(false) });

#if LOG_ALL_IDENT_LOOKUPS
                Logging.Log("IdentResolver: Random router lookup " + ident.Id32Short + " sent to " + oneff.Id32Short);
#endif
                try
                {
                    TransportProvider.Send(oneff, msg);
                }
                catch (Exception ex)
                {
                    Logging.Log(ex);
                }
            }
        }
示例#4
0
        private bool HandleTunnelData(IEnumerable <TunnelDataMessage> msgs)
        {
            EncryptTunnelMessages(msgs);

#if LOG_ALL_TUNNEL_TRANSFER
            LogDataSent.Log(() => "PassthroughTunnel " + Destination.Id32Short + " TunnelData sent.");
#endif
            var dropped = 0;
            foreach (var one in msgs)
            {
                if (Limiter.DropMessage())
                {
                    ++dropped;
                    continue;
                }

                one.TunnelId = SendTunnelId;
                Bandwidth.DataSent(one.Payload.Length);
                TransportProvider.Send(Destination, one);
            }

#if LOG_ALL_TUNNEL_TRANSFER
            if (dropped > 0)
            {
                DebugUtils.LogDebug(() => string.Format("{0} bandwidth limit. {1} dropped messages. {2}", this, dropped, Bandwidth));
            }
#endif

            return(true);
        }
示例#5
0
        private void HandleTunnelData(List <TunnelDataMessage> msgs)
        {
            DecryptTunnelMessages(msgs);

            var newmsgs = Reassembler.Process(msgs);

            foreach (var one in newmsgs)
            {
                if (one.GetType() == typeof(TunnelMessageLocal))
                {
                    DebugUtils.Log("InboundTunnel " + TunnelDebugTrace + " TunnelData distributed Local :\r\n" + one.Header.ToString());
                    MessageReceived(((TunnelMessageLocal)one).Header);
                }
                else
                if (one.GetType() == typeof(TunnelMessageRouter))
                {
                    DebugUtils.Log("InboundTunnel " + TunnelDebugTrace + " TunnelData distributed Router :\r\n" + one.Header.ToString());
                    TransportProvider.Send(((TunnelMessageRouter)one).Destination, one.Header.Message);
                }
                else
                if (one.GetType() == typeof(TunnelMessageTunnel))
                {
                    var tone = (TunnelMessageTunnel)one;
                    DebugUtils.Log("InboundTunnel " + TunnelDebugTrace + " TunnelData distributed Tunnel :\r\n" + one.Header.ToString());
                    var gwmsg = new TunnelGatewayMessage(tone.Header, tone.Tunnel);
                    TransportProvider.Send(tone.Destination, gwmsg);
                }
                else
                {
                    DebugUtils.LogWarning("InboundTunnel " + TunnelDebugTrace + " TunnelData without routing rules:\r\n" + one.Header.ToString());
                }
            }
        }
示例#6
0
        public T GetTransportProvider <T>()
            where T : TransportProvider
        {
            T t;

            List <TransportProvider> .Enumerator enumerator = this.transportProviders.GetEnumerator();
            try
            {
                while (enumerator.MoveNext())
                {
                    TransportProvider current = enumerator.Current;
                    if (!(current is T))
                    {
                        continue;
                    }
                    t = (T)current;
                    return(t);
                }
                return(default(T));
            }
            finally
            {
                ((IDisposable)enumerator).Dispose();
            }
            return(t);
        }
示例#7
0
        public bool TryGetTransportProvider(ProtocolHeader header, out TransportProvider provider)
        {
            bool flag;

            if (this.TransportProviders.Count == 0)
            {
                throw new ArgumentException("TransportProviders");
            }
            provider = null;
            using (IEnumerator <TransportProvider> enumerator = this.TransportProviders.GetEnumerator())
            {
                while (enumerator.MoveNext())
                {
                    TransportProvider current = enumerator.Current;
                    if (current.ProtocolId != header.ProtocolId)
                    {
                        continue;
                    }
                    provider = current;
                    flag     = true;
                    return(flag);
                }
                provider = this.GetDefaultProvider();
                return(false);
            }
            return(flag);
        }
示例#8
0
        private bool HandleReceiveQueue()
        {
            II2NPHeader16[] messages = null;

            lock ( ReceiveQueue )
            {
                if (ReceiveQueue.Count == 0)
                {
                    return(true);
                }

                var msgs    = new List <II2NPHeader16>();
                int dropped = 0;
                foreach (var msg in ReceiveQueue)
                {
                    if (Limiter.DropMessage())
                    {
                        ++dropped;
                        continue;
                    }

                    msgs.Add((II2NPHeader16)msg);
                }
                messages = msgs.ToArray();

#if LOG_ALL_TUNNEL_TRANSFER
                if (dropped > 0)
                {
                    if (FilterMessageTypes.Update(new HashedItemGroup(Destination, 0x63e9)))
                    {
                        Logging.LogDebug(() => string.Format("{0} bandwidth limit. {1} dropped messages. {2}", this, dropped, Bandwidth));
                    }
                }
#endif
            }

            if (messages == null || messages.Length == 0)
            {
                return(true);
            }

            var tdata = TunnelDataMessage.MakeFragments(messages.Select(msg => (TunnelMessage)(new TunnelMessageLocal(msg))), SendTunnelId);

            EncryptTunnelMessages(tdata);

#if LOG_ALL_TUNNEL_TRANSFER
            if (FilterMessageTypes.Update(new HashedItemGroup(Destination, 0x17f3)))
            {
                Logging.Log("GatewayTunnel " + Destination.Id32Short + ": TunnelData sent.");
            }
#endif
            foreach (var tdmsg in tdata)
            {
                Bandwidth.DataSent(tdmsg.Payload.Length);
                TransportProvider.Send(Destination, tdmsg);
            }
            return(true);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="BoardingJourneyCard" /> class.
 /// </summary>
 protected BoardingJourneyCard()
 {
     id                = "000000";
     transport         = null;
     seat              = "";
     departureDate     = DateTime.Now;
     arrivalDate       = DateTime.Now;
     transportProvider = null;
     owner             = null;
     denied            = false;
     valid             = false;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="BoardingJourneyCard" /> class.
 /// </summary>
 /// <param name="id">The id.</param>
 /// <param name="seat">The seat.</param>
 /// <param name="departureDate">The departure date.</param>
 /// <param name="arrivalDate">The arrival date.</param>
 /// <param name="client">The client.</param>
 /// <param name="transportProvider">The transport company.</param>
 protected BoardingJourneyCard(String id, String seat, DateTime departureDate, DateTime arrivalDate,
                               BoardingJourneyCardOwner client, TransportProvider transportProvider)
 {
     this.id                = id;
     this.seat              = seat;
     this.departureDate     = departureDate;
     this.arrivalDate       = arrivalDate;
     this.owner             = client;
     this.transportProvider = transportProvider;
     denied = false;
     valid  = false;
 }
示例#11
0
        public RpcServer()
        {
            _cacheContainer = new ServerCacheContainer();

            _localCacheService = new LocalCacheService(_section, _cacheContainer);

            _serializer = SerializerFactory.GetSerializer(_section.Serializer);

            _transportProvider = new TransportProvider(_cacheContainer, _serializer);

            _acceptor = _transportProvider.GetAcceptor();
        }
示例#12
0
        // Constructor
        public TransportClient(TransportProvider provider)
        {
            #region Contracts

            if (provider == null)
            {
                throw new ArgumentNullException();
            }

            #endregion

            // Default
            _provider = provider;
        }
示例#13
0
        public ProtocolHeader GetSupportedHeader(ProtocolHeader requestedHeader)
        {
            AmqpVersion       amqpVersion;
            TransportProvider transportProvider = null;

            if (!this.TryGetTransportProvider(requestedHeader, out transportProvider))
            {
                return(this.GetDefaultHeader());
            }
            if (transportProvider.TryGetVersion(requestedHeader.Version, out amqpVersion))
            {
                return(requestedHeader);
            }
            return(new ProtocolHeader(transportProvider.ProtocolId, transportProvider.DefaultVersion));
        }
示例#14
0
        private void SendUpdate(I2PIdentHash ff, uint token)
        {
            // If greater than zero, a DeliveryStatusMessage
            // is requested with the Message ID set to the value of the Reply Token.
            // A floodfill router is also expected to flood the data to the closest floodfill peers
            // if the token is greater than zero.
            // https://geti2p.net/spec/i2np#databasestore

            var ds = new DatabaseStoreMessage(
                RouterContext.Inst.MyRouterInfo,
                token,
                RouterContext.Inst.MyRouterInfo.Identity.IdentHash,
                0);

            TransportProvider.Send(ff, ds);
        }
示例#15
0
        public AbstractConsumer(IMessageHandler handler, ClientCacheContainer cacheContainer, ILoadBalance loadBalance, ISerializer serializer)
        {
            _handler = handler;

            _handler.Recieved += Message_Recieved;

            _cacheContainer = cacheContainer;

            _loadBalance = loadBalance;

            _serializer = serializer;

            _transportProvider = new TransportProvider(_cacheContainer, serializer);

            _connector = _transportProvider.GetConnector(_handler);
        }
        public FluentRecordBase AddTransportProvider(
            )
        {
            //
            // DEPENDENCIES
            _servTP = container.GetRequiredService <ITransportProvidersService>();

            //
            // ARRANGE
            _tp = (TransportProvider)Records.transportProvider.Clone();

            //
            // ACT
            _servTP.Create(_tp, _user);
            return(this);
        }
示例#17
0
        private void HandleEndpointTunnelRequest(
            II2NPHeader msg,
            TunnelBuildRequestDecrypt decrypt)
        {
            var config = new TunnelConfig(
                TunnelConfig.TunnelDirection.Inbound,
                TunnelConfig.TunnelPool.External,
                new TunnelInfo(new List <HopInfo>
            {
                new HopInfo(
                    RouterContext.Inst.MyRouterIdentity,
                    new I2PTunnelId())
            }
                               ));

            var tunnel = new EndpointTunnel(this, config, decrypt.Decrypted);

            tunnel.EstablishedTime.SetNow();

            var doaccept = AcceptingTunnels(decrypt.Decrypted);

            var response = doaccept
                    ? BuildResponseRecord.RequestResponse.Accept
                    : BuildResponseRecord.DefaultErrorReply;

            Logging.LogDebug($"HandleEndpointTunnelRequest {tunnel.TunnelDebugTrace}: " +
                             $"{tunnel.Destination.Id32Short} Endpoint tunnel request: {response} " +
                             $"for tunnel id {tunnel.ReceiveTunnelId}.");

            var newrecords = decrypt.CreateTunnelBuildReplyRecords(response);

            var responsemessage = new VariableTunnelBuildReplyMessage(
                newrecords.Select(r => new BuildResponseRecord(r)),
                tunnel.ResponseMessageId);

            var buildreplymsg = new TunnelGatewayMessage(
                responsemessage,
                tunnel.ResponseTunnelId);

            if (response == BuildResponseRecord.RequestResponse.Accept)
            {
                RunningEndpointTunnels[tunnel] = 1;
                TunnelMgr.AddTunnel(tunnel);
                AcceptedTunnelBuildRequest(decrypt.Decrypted);
            }
            TransportProvider.Send(tunnel.Destination, buildreplymsg);
        }
示例#18
0
        // Methods
        public void Attach(TransportHandler handler)
        {
            #region Contracts

            if (handler == null)
            {
                throw new ArgumentNullException();
            }

            #endregion

            // Attach
            handler.Attach(_provider);

            // Provider
            _provider = handler;
        }
示例#19
0
        private TransportProvider GetDefaultProvider()
        {
            TransportProvider transportProvider = null;

            if (this.RequireSecureTransport)
            {
                transportProvider = this.GetTransportProvider <TlsTransportProvider>();
            }
            else if (this.AllowAnonymousConnection)
            {
                transportProvider = this.GetTransportProvider <AmqpTransportProvider>();
            }
            else
            {
                transportProvider = this.GetTransportProvider <SaslTransportProvider>();
            }
            return(transportProvider);
        }
        public void TestInitialize()
        {
            _savedTransportProvider = new TransportProvider();
            _fakeTransportProvider  = new TransportProvider()
            {
                active           = true,
                defaultAttribute = true,
                ID      = 1,
                key     = "asdf",
                text_EN = "asdf"
            };
            _fakeTransportProviders = new List <TransportProvider>();
            _fakeTransportProviders.Add(new TransportProvider()
            {
                active           = true,
                defaultAttribute = true,
                ID      = 2,
                key     = "dth",
                text_EN = "wert"
            });

            _transportProvidersServ = new Mock <ITransportProvidersService>();
            _transportProvidersServ.Setup(s => s.GetMany(It.IsAny <Func <TransportProvider, bool> >()))
            .Returns(_fakeTransportProviders.AsQueryable);
            _transportProvidersServ.Setup(s => s.Get(1))
            .Returns(_fakeTransportProvider);
            _transportProvidersServ.Setup(s => s.Get(1000))
            .Returns((TransportProvider)null);
            _transportProvidersServ.Setup(s => s.Create(It.IsAny <TransportProvider>(), It.IsAny <string>()))
            .Returns(_fakeTransportProvider);
            _transportProvidersServ.Setup(s => s.Save(It.Is <TransportProvider>(r => r.ID == 1), It.IsAny <string>()))
            .Callback((TransportProvider tp, string user) => _savedTransportProvider = tp);
            _transportProvidersServ.Setup(s => s.Delete(1, It.IsAny <string>()))
            .Verifiable();

            var mapperConfig = new MapperConfiguration(config =>
            {
                config.ConfigureApi();
            });

            _mapper = mapperConfig.CreateMapper();

            _controller = new TransportProvidersController(_transportProvidersServ.Object, _mapper);
        }
示例#21
0
        public FluentRecordBase AddTransportProvider(
            )
        {
            //
            // DEPENDENCIES
            if (_servTP == null)
            {
                AddServTransportProvider();
            }

            //
            // ARRANGE
            _tp = (TransportProvider)Records.transportProvider.Clone();

            //
            // ACT
            _servTP.Create(_tp, _user);
            return(this);
        }
示例#22
0
        private void SendUpdateTunnelReply(I2PIdentHash ff, uint token)
        {
            // If greater than zero, a DeliveryStatusMessage
            // is requested with the Message ID set to the value of the Reply Token.
            // A floodfill router is also expected to flood the data to the closest floodfill peers
            // if the token is greater than zero.
            // https://geti2p.net/spec/i2np#databasestore

            var replytunnel = TunnelProvider.Inst.GetInboundTunnel(true);
            var ds          = new DatabaseStoreMessage(RouterContext.Inst.MyRouterInfo,
                                                       token, replytunnel.Destination, replytunnel.ReceiveTunnelId);

            lock ( OutstandingRequests )
            {
                OutstandingRequests[token] = new FFUpdateRequestInfo(ff);
            }

            TransportProvider.Send(ff, ds);
        }
示例#23
0
        internal static void HandleDatabaseStore(DatabaseStoreMessage ds)
        {
            if (ds.RouterInfo == null && ds.LeaseSet == null)
            {
                throw new ArgumentException("DatabaseStore without Router or Lease info!");
            }

            if (ds.RouterInfo != null)
            {
#if LOG_ALL_TUNNEL_TRANSFER
                //Logging.Log( "HandleDatabaseStore: DatabaseStore RouterInfo" + ds.ToString() );
#endif
                NetDb.Inst.AddRouterInfo(ds.RouterInfo);
            }
            else
            {
#if LOG_ALL_TUNNEL_TRANSFER
                //Logging.Log( "HandleDatabaseStore: DatabaseStore LeaseSet" + ds.ToString() );
#endif
                NetDb.Inst.AddLeaseSet(ds.LeaseSet);
            }

            if (ds.ReplyToken != 0)
            {
                if (ds.ReplyTunnelId != 0)
                {
                    var outtunnel = TunnelProvider.Inst.GetEstablishedOutboundTunnel(true);
                    if (outtunnel != null)
                    {
                        outtunnel.Send(new TunnelMessageRouter(
                                           (new TunnelGatewayMessage(
                                                new DeliveryStatusMessage(ds.ReplyToken),
                                                ds.ReplyTunnelId)),
                                           ds.ReplyGateway));
                    }
                }
                else
                {
                    TransportProvider.Send(ds.ReplyGateway,
                                           new DeliveryStatusMessage(ds.ReplyToken));
                }
            }
        }
示例#24
0
文件: Router.cs 项目: itfenom/i2p-cs
        /// <summary>
        /// Start the router with the current RouterContext settings.
        /// </summary>
        public static void Start()
        {
            lock ( StartedLock )
            {
                if (Started)
                {
                    return;
                }

                try
                {
                    var rci = RouterContext.Inst;
                    NetDb.Start();

                    Logging.Log("I: " + RouterContext.Inst.MyRouterInfo.ToString());
                    Logging.Log("Published: " + RouterContext.Inst.Published.ToString());

                    Logging.Log("Connecting...");
                    TransportProvider.Start();
                    TunnelProvider.Start();

                    ClientMgr        = new ClientTunnelProvider(TunnelProvider.Inst);
                    ExplorationMgr   = new ExplorationTunnelProvider(TunnelProvider.Inst);
                    TransitTunnelMgr = new TransitTunnelProvider(TunnelProvider.Inst);

                    Worker = new Thread(Run)
                    {
                        Name         = "Router",
                        IsBackground = true
                    };
                    Worker.Start();

                    NetDb.Inst.IdentHashLookup.LeaseSetReceived += IdentHashLookup_LeaseSetReceived;
                    NetDb.Inst.IdentHashLookup.LookupFailure    += IdentHashLookup_LookupFailure;

                    Started = true;
                }
                catch (Exception ex)
                {
                    Logging.Log(ex);
                }
            }
        }
示例#25
0
        private void SendRIDatabaseLookup(I2PIdentHash ident, IdentUpdateRequestInfo info)
        {
            var ff = NetDb.Inst.GetClosestFloodfill(
                ident,
                10 + 3 * info.Retries,
                info.AlreadyQueried,
                false);

            if (!ff.Any())
            {
                Logging.Log($"IdentResolver: failed to find a floodfill router to lookup ({ident}): ");
                return;
            }

            ff.Shuffle();
            ff = ff.Take(DatabaseLookupSelectFloodfillCount).ToArray();

            foreach (var oneff in ff)
            {
                try
                {
                    var msg = new DatabaseLookupMessage(
                        ident,
                        RouterContext.Inst.MyRouterIdentity.IdentHash,
                        DatabaseLookupMessage.LookupTypes.RouterInfo);

                    TransportProvider.Send(oneff, msg);
#if LOG_ALL_IDENT_LOOKUPS
                    Logging.Log($"IdentResolver: RouterInfo query {msg.Key.Id32Short} sent to {oneff.Id32Short}");
#endif
                }
                catch (Exception ex)
                {
                    Logging.Log("SendRIDatabaseLookup", ex);
                }
            }

            foreach (var f in ff)
            {
                info.AlreadyQueried.Add(f);
            }
        }
示例#26
0
文件: Router.cs 项目: kyapp69/i2p-cs
        public static void Start()
        {
            if (Started)
            {
                return;
            }

            var rci = RouterContext.Inst;

            NetDb.Start();

            Logging.Log("I: " + RouterContext.Inst.MyRouterInfo.ToString());
            Logging.Log("Published: " + RouterContext.Inst.Published.ToString());

            Logging.Log("Connecting...");
            TransportProvider.Start();
            TunnelProvider.Start();

            Started = true;
        }
示例#27
0
        // Methods
        public void Attach(TransportProvider provider)
        {
            #region Contracts

            if (provider == null)
            {
                throw new ArgumentNullException();
            }

            #endregion

            // Require
            if (_provider != null)
            {
                throw new InvalidOperationException();
            }

            // Provider
            _provider = provider;
        }
示例#28
0
        private bool CreateTunnelMessageFragments(IEnumerable <TunnelMessage> messages)
        {
            var data = TunnelDataMessage.MakeFragments(messages, SendTunnelId);

            var encr = OutboundGatewayDecrypt(data);

            foreach (var msg in encr)
            {
#if LOG_ALL_TUNNEL_TRANSFER
                if (FilterMessageTypes.Update(new HashedItemGroup((int)msg.MessageType, 0x4272)))
                {
                    Logging.LogDebug($"OutboundTunnel: Send {NextHop.Id32Short} : {msg}");
                }
#endif
                Bandwidth.DataSent(msg.Payload.Length);
                TransportProvider.Send(NextHop, msg);
            }

            return(true);
        }
示例#29
0
        public ProtocolHeader GetSupportedHeader(ProtocolHeader requestedHeader)
        {
            // Protocol id negotiation
            TransportProvider provider = null;

            if (!this.TryGetTransportProvider(requestedHeader, out provider))
            {
                return(this.GetDefaultHeader());
            }

            // Protocol version negotiation
            AmqpVersion version;

            if (!provider.TryGetVersion(requestedHeader.Version, out version))
            {
                return(new ProtocolHeader(provider.ProtocolId, provider.DefaultVersion));
            }

            return(requestedHeader);
        }
示例#30
0
        public bool TryGetTransportProvider(ProtocolHeader header, out TransportProvider provider)
        {
            if (this.TransportProviders.Count == 0)
            {
                throw new ArgumentException("TransportProviders");
            }

            provider = null;
            foreach (TransportProvider transportProvider in this.TransportProviders)
            {
                if (transportProvider.ProtocolId == header.ProtocolId)
                {
                    provider = transportProvider;
                    return(true);
                }
            }

            // Not found. Return the preferred one based on settings
            provider = this.GetDefaultProvider();
            return(false);
        }
示例#31
0
        /// <summary>
        /// Initiate method for asynchronous receive operation of payload data.
        /// </summary>
        private void ReceivePayloadAsync(TransportProvider<TlsSocket> client)
        {
            // Initialize bytes received.
            client.BytesReceived = 0;

            // Initiate receiving.
            if (m_payloadAware)
            {
                // Payload boundaries are to be preserved.
                client.SetReceiveBuffer(m_payloadMarker.Length + Payload.LengthSegment);
                ReceivePayloadAwareAsync(client, true);
            }
            else
            {
                // Payload boundaries are not to be preserved.
                client.SetReceiveBuffer(ReceiveBufferSize);
                ReceivePayloadUnawareAsync(client);
            }
        }
示例#32
0
文件: TcpServer.cs 项目: avs009/gsf
        /// <summary>
        /// Initiate method for asynchronous receive operation of payload data.
        /// </summary>
        private void ReceivePayloadAsync(TransportProvider<Socket> worker)
        {
            // Initialize pointers.
            worker.ReceiveBufferOffset = 0;
            worker.ReceiveBufferLength = -1;

            // Initiate receiving.
            if (m_payloadAware)
            {
                // Payload boundaries are to be preserved.
                worker.ReceiveBuffer = new byte[m_payloadMarker.Length + Payload.LengthSegment];
                ReceivePayloadAwareAsync(worker);
            }
            else
            {
                // Payload boundaries are not to be preserved.
                worker.ReceiveBuffer = new byte[ReceiveBufferSize];
                ReceivePayloadUnawareAsync(worker);
            }
        }
示例#33
0
文件: SslServer.cs 项目: avs009/gsf
        /// <summary>
        /// Processes the termination of client.
        /// </summary>
        private void TerminateConnection(TransportProvider<SslStream> client, bool raiseEvent)
        {
            client.Reset();

            if (raiseEvent)
                OnClientDisconnected(client.ID);

            m_tcpClients.TryRemove(client.ID, out client);
        }
示例#34
0
文件: TcpServer.cs 项目: rmc00/gsf
        /// <summary>
        /// Callback method for asynchronous accept operation.
        /// </summary>
        private void ProcessAccept()
        {
            TransportProvider<Socket> client = new TransportProvider<Socket>();
            SocketAsyncEventArgs receiveArgs = null;
            TcpClientInfo clientInfo;

            try
            {
                if (CurrentState == ServerState.NotRunning)
                    return;

                if (m_acceptArgs.SocketError != SocketError.Success)
                {
                    // Error is unrecoverable.
                    // We need to make sure to restart the
                    // server before we throw the error.
                    SocketError error = m_acceptArgs.SocketError;
                    ThreadPool.QueueUserWorkItem(state => ReStart());
                    throw new SocketException((int)error);
                }

                // Process the newly connected client.
                client.Provider = m_acceptArgs.AcceptSocket;

                // Set up SocketAsyncEventArgs for receive operations.
                receiveArgs = FastObjectFactory<SocketAsyncEventArgs>.CreateObjectFunction();
                receiveArgs.Completed += ReceiveHandler;

                // Return to accepting new connections.
                m_acceptArgs.AcceptSocket = null;

                if (!m_tcpServer.AcceptAsync(m_acceptArgs))
                {
                    ThreadPool.QueueUserWorkItem(state => ProcessAccept());
                }

#if !MONO
                // Authenticate the connected client Windows credentials.
                if (m_integratedSecurity)
                {
                    NetworkStream socketStream = null;
                    NegotiateStream authenticationStream = null;
                    try
                    {
                        socketStream = new NetworkStream(client.Provider);
                        authenticationStream = new NegotiateStream(socketStream);
                        authenticationStream.AuthenticateAsServer();

                        if (authenticationStream.RemoteIdentity is WindowsIdentity)
                            Thread.CurrentPrincipal = new WindowsPrincipal((WindowsIdentity)authenticationStream.RemoteIdentity);
                    }
                    finally
                    {
                        if (socketStream != null)
                            socketStream.Dispose();

                        if (authenticationStream != null)
                            authenticationStream.Dispose();
                    }
                }
#endif

                if (MaxClientConnections != -1 && ClientIDs.Length >= MaxClientConnections)
                {
                    // Reject client connection since limit has been reached.
                    TerminateConnection(client, receiveArgs, false);
                }
                else
                {
                    // We can proceed further with receiving data from the client.
                    clientInfo = new TcpClientInfo()
                    {
                        Client = client,
                        SendArgs = FastObjectFactory<SocketAsyncEventArgs>.CreateObjectFunction(),
                        SendLock = new SpinLock(),
                        SendQueue = new ConcurrentQueue<TcpServerPayload>()
                    };

                    // Set up socket args.
                    client.SetSendBuffer(SendBufferSize);
                    clientInfo.SendArgs.Completed += m_sendHandler;
                    clientInfo.SendArgs.SetBuffer(client.SendBuffer, 0, client.SendBufferSize);

                    m_clientInfoLookup.TryAdd(client.ID, clientInfo);

                    OnClientConnected(client.ID);

                    if (!m_payloadAware)
                    {
                        receiveArgs.UserToken = client;
                    }
                    else
                    {
                        EventArgs<TransportProvider<Socket>, bool> userToken = ReusableObjectPool<EventArgs<TransportProvider<Socket>, bool>>.Default.TakeObject();
                        userToken.Argument1 = client;
                        receiveArgs.UserToken = userToken;
                    }

                    ReceivePayloadAsync(client, receiveArgs);
                }
            }
            catch (Exception ex)
            {
                // Notify of the exception.
                if ((object)client.Provider != null)
                {
                    string clientAddress = ((IPEndPoint)client.Provider.RemoteEndPoint).Address.ToString();
                    string errorMessage = string.Format("Unable to accept connection to client [{0}]: {1}", clientAddress, ex.Message);
                    OnClientConnectingException(new Exception(errorMessage, ex));
                }

                if ((object)receiveArgs != null)
                {
                    TerminateConnection(client, receiveArgs, false);
                }
            }
        }
示例#35
0
文件: TcpServer.cs 项目: avs009/gsf
 /// <summary>
 /// Callback method for asynchronous accept operation.
 /// </summary>
 private void AcceptAsyncCallback(IAsyncResult asyncResult)
 {
     TransportProvider<Socket> tcpClient = new TransportProvider<Socket>();
     try
     {
         // Return to accepting new connections.
         m_tcpServer.BeginAccept(AcceptAsyncCallback, null);
         // Process the newly connected client.
         tcpClient.Secretkey = SharedSecret;
         tcpClient.Provider = m_tcpServer.EndAccept(asyncResult);
         if (MaxClientConnections != -1 && ClientIDs.Length >= MaxClientConnections)
         {
             // Reject client connection since limit has been reached.
             TerminateConnection(tcpClient, false);
         }
         else
         {
             // We can proceed further with receiving data from the client.
             if (Handshake)
             {
                 // Handshaking must be performed. 
                 ReceiveHandshakeAsync(tcpClient);
             }
             else
             {
                 // No handshaking to be performed.
                 lock (m_tcpClients)
                 {
                     m_tcpClients.Add(tcpClient.ID, tcpClient);
                 }
                 OnClientConnected(tcpClient.ID);
                 ReceivePayloadAsync(tcpClient);
             }
         }
     }
     catch
     {
         // Server socket has been terminated.
         m_tcpServer.Close();
         OnServerStopped();
     }
 }
示例#36
0
        /// <summary>
        /// Processes the termination of client.
        /// </summary>
        private void TerminateConnection(TransportProvider<TlsSocket> client, bool raiseEvent)
        {
            TlsClientInfo clientInfo;

            client.Reset();

            if (raiseEvent)
                OnClientDisconnected(client.ID);

            m_clientInfoLookup.TryRemove(client.ID, out clientInfo);
        }
示例#37
0
        /// <summary>
        /// Callback method for asynchronous accept operation.
        /// </summary>
        private void ProcessAccept(SocketAsyncEventArgs acceptArgs)
        {
            TransportProvider<TlsSocket> client = new TransportProvider<TlsSocket>();
            IPEndPoint remoteEndPoint = null;
            NetworkStream netStream;

            try
            {
                if (CurrentState == ServerState.NotRunning)
                    return;

                // If acceptArgs was disposed, m_acceptArgs will either
                // be null or another instance of SocketAsyncEventArgs.
                // This check will tell us whether it's been disposed.
                if ((object)acceptArgs != m_acceptArgs)
                    return;

                if (acceptArgs.SocketError != SocketError.Success)
                {
                    // Error is unrecoverable.
                    // We need to make sure to restart the
                    // server before we throw the error.
                    SocketError error = acceptArgs.SocketError;
                    ThreadPool.QueueUserWorkItem(state => ReStart());
                    throw new SocketException((int)error);
                }

                // Get the remote end point in case we need to display useful error messages
                remoteEndPoint = acceptArgs.AcceptSocket.RemoteEndPoint as IPEndPoint;

                if (MaxClientConnections != -1 && ClientIDs.Length >= MaxClientConnections)
                {
                    // Reject client connection since limit has been reached.
                    TerminateConnection(client, false);
                }
                else
                {
                    // Process the newly connected client.
                    LoadTrustedCertificates();
                    netStream = new NetworkStream(acceptArgs.AcceptSocket);

                    client.Provider = new TlsSocket
                    {
                        Socket = acceptArgs.AcceptSocket,
                        SslStream = new SslStream(netStream, false, m_remoteCertificateValidationCallback ?? CertificateChecker.ValidateRemoteCertificate, m_localCertificateSelectionCallback)
                    };

                    client.Provider.Socket.ReceiveBufferSize = ReceiveBufferSize;
                    client.Provider.SslStream.BeginAuthenticateAsServer(m_certificate, m_requireClientCertificate, m_enabledSslProtocols, m_checkCertificateRevocation, ProcessTlsAuthentication, client);
                }

                // Return to accepting new connections.
                acceptArgs.AcceptSocket = null;

                if (!m_tlsServer.AcceptAsync(acceptArgs))
                {
                    ThreadPool.QueueUserWorkItem(state => ProcessAccept(acceptArgs));
                }
            }
            catch (ObjectDisposedException)
            {
                // m_acceptArgs may be disposed while in the middle of accepting a connection
            }
            catch (Exception ex)
            {
                // Notify of the exception.
                if ((object)remoteEndPoint != null)
                {
                    string clientAddress = remoteEndPoint.Address.ToString();
                    string errorMessage = $"Unable to accept connection to client [{clientAddress}]: {ex.Message}";
                    OnClientConnectingException(new Exception(errorMessage, ex));
                }

                TerminateConnection(client, false);
            }
        }
示例#38
0
文件: UdpServer.cs 项目: avs009/gsf
        /// <summary>
        /// Callback method for asynchronous receive operation of handshake data.
        /// </summary>
        private void ReceiveHandshakeAsyncCallback(IAsyncResult asyncResult)
        {
            TransportProvider<Socket> udpServer = (TransportProvider<Socket>)asyncResult.AsyncState;
            // Received handshake data from client so we'll process it.
            try
            {
                // Update statistics and pointers.
                EndPoint client = Transport.CreateEndPoint(string.Empty, 0);
                udpServer.Statistics.UpdateBytesReceived(udpServer.Provider.EndReceiveFrom(asyncResult, ref client));
                udpServer.ReceiveBufferLength = udpServer.Statistics.LastBytesReceived;

                // Process the received handshake message.
                Payload.ProcessReceived(ref udpServer.ReceiveBuffer, ref udpServer.ReceiveBufferOffset, ref udpServer.ReceiveBufferLength, Encryption, SharedSecret, Compression);

                HandshakeMessage handshake = new HandshakeMessage();
                if (handshake.Initialize(udpServer.ReceiveBuffer, udpServer.ReceiveBufferOffset, udpServer.ReceiveBufferLength) != -1)
                {
                    // Received handshake message is parsed successfully.
                    if (handshake.ID != Guid.Empty)
                    {
                        // Create a random socket and connect it to the client.
                        TransportProvider<Socket> udpClient = new TransportProvider<Socket>();
                        udpClient.ReceiveBuffer = new byte[ReceiveBufferSize];
                        udpClient.Secretkey = SharedSecret;
                        udpClient.Provider = Transport.CreateSocket(m_configData["interface"], 0, ProtocolType.Udp);
                        udpClient.Provider.Connect(client);

                        // Authentication is successful; respond to the handshake.
                        udpClient.ID = handshake.ID;
                        handshake.ID = this.ServerID;
                        if (SecureSession)
                        {
                            // Create a secret key for ciphering client data.
                            udpClient.Secretkey = Guid.NewGuid().ToString();
                            handshake.Secretkey = udpClient.Secretkey;
                        }

                        // Prepare binary image of handshake response to be transmitted.
                        udpClient.SendBuffer = handshake.BinaryImage;
                        udpClient.SendBufferOffset = 0;
                        udpClient.SendBufferLength = udpClient.SendBuffer.Length;
                        Payload.ProcessTransmit(ref udpClient.SendBuffer, ref udpClient.SendBufferOffset, ref udpClient.SendBufferLength, Encryption, SharedSecret, Compression);

                        // Transmit the prepared and processed handshake response message.
                        udpClient.Provider.SendTo(udpClient.SendBuffer, udpClient.Provider.RemoteEndPoint);

                        // Handshake process is complete and client is considered connected.
                        lock (m_udpClients)
                        {
                            m_udpClients.Add(udpClient.ID, udpClient);
                        }
                        OnClientConnected(udpClient.ID);

                        try
                        {
                            ReceivePayloadOneAsync(udpClient);
                        }
                        catch
                        {
                            // Receive will fail if client disconnected before handshake is complete.
                            TerminateConnection(udpClient, true);
                        }
                    }
                    else
                    {
                        // Validation during handshake failed.
                        OnHandshakeProcessUnsuccessful();
                    }
                }
                else
                {
                    // Handshake message could not be parsed.
                    OnHandshakeProcessUnsuccessful();
                }

                // Resume receiving of client handshake messages.
                ReceiveHandshakeAsync(udpServer);
            }
            catch
            {
                // Server socket has been terminated.
                udpServer.Reset();
                OnServerStopped();
            }
        }
示例#39
0
文件: UdpServer.cs 项目: avs009/gsf
 /// <summary>
 /// Initiate method for asynchronous receive operation of payload data from any endpoint.
 /// </summary>
 private void ReceivePayloadAnyAsync(TransportProvider<Socket> worker)
 {
     worker.Provider.BeginReceiveFrom(worker.ReceiveBuffer,
                                      worker.ReceiveBufferOffset,
                                      worker.ReceiveBuffer.Length,
                                      SocketFlags.None,
                                      ref m_udpClientEndPoint,
                                      ReceivePayloadAnyAsyncCallback,
                                      worker);
 }
示例#40
0
文件: UdpServer.cs 项目: avs009/gsf
        /// <summary>
        /// Starts the <see cref="UdpServer"/> synchronously and begins accepting client connections asynchronously.
        /// </summary>
        /// <exception cref="InvalidOperationException">Attempt is made to <see cref="Start()"/> the <see cref="UdpServer"/> when it is running.</exception>
        public override void Start()
        {
            if (CurrentState == ServerState.NotRunning)
            {
                // Initialize if unitialized.
                Initialize();
                // Create end-point for receiving data.
                m_udpClientEndPoint = Transport.CreateEndPoint(string.Empty, 0);
                // Bind server socket to local end-point.
                m_udpServer = new TransportProvider<Socket>();
                m_udpServer.ID = this.ServerID;
                m_udpServer.ReceiveBuffer = new byte[ReceiveBufferSize];
                m_udpServer.Provider = Transport.CreateSocket(m_configData["interface"], int.Parse(m_configData["port"]), ProtocolType.Udp);
                // Notify that the server has been started successfully.
                OnServerStarted();

                if (Handshake)
                {
                    // Listen for incoming data if server endpoint is bound to a local interface.
                    m_receivedGoodbye = DoGoodbyeCheck;
                    if (m_udpServer.Provider.LocalEndPoint != null)
                        ReceiveHandshakeAsync(m_udpServer);
                }
                else
                {
                    // Listen for incoming data if server endpoint is bound to a local interface.
                    m_receivedGoodbye = NoGoodbyeCheck;
                    if (m_udpServer.Provider.LocalEndPoint != null)
                        ReceivePayloadAnyAsync(m_udpServer);

                    // When handshake is not to be performed, we process the static list to clients.
                    foreach (string clientString in m_configData["clients"].Replace(" ", "").Split(','))
                    {
                        try
                        {
                            Match endpoint = Regex.Match(clientString, Transport.EndpointFormatRegex);
                            if (endpoint != Match.Empty)
                            {
                                TransportProvider<Socket> udpClient = new TransportProvider<Socket>();
                                udpClient.Secretkey = SharedSecret;
                                udpClient.ReceiveBuffer = new byte[ReceiveBufferSize];
                                udpClient.Provider = Transport.CreateSocket(m_configData["interface"], 0, ProtocolType.Udp);
                                // Disable SocketError.ConnectionReset exception from being thrown when the enpoint is not listening.
                                udpClient.Provider.IOControl(SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);
                                // Connect socket to the client endpoint so communication on the socket is restricted to a single endpoint.
                                udpClient.Provider.Connect(Transport.CreateEndPoint(endpoint.Groups["host"].Value, int.Parse(endpoint.Groups["port"].Value)));

                                lock (m_udpClients)
                                {
                                    m_udpClients.Add(udpClient.ID, udpClient);
                                }
                                OnClientConnected(udpClient.ID);

                                ReceivePayloadOneAsync(udpClient);
                            }
                        }
                        catch
                        {
                            // Ignore invalid client entries.
                        }
                    }
                }
            }
            else
            {
                throw new InvalidOperationException("Server is currently running");
            }
        }
示例#41
0
文件: UdpServer.cs 项目: avs009/gsf
 /// <summary>
 /// Initiate method for asynchronous receive operation of handshake data.
 /// </summary>
 private void ReceiveHandshakeAsync(TransportProvider<Socket> worker)
 {
     // Receive data asynchronously.
     EndPoint client = Transport.CreateEndPoint(string.Empty, 0);
     worker.Provider.BeginReceiveFrom(worker.ReceiveBuffer,
                                      worker.ReceiveBufferOffset,
                                      worker.ReceiveBuffer.Length,
                                      SocketFlags.None,
                                      ref client,
                                      ReceiveHandshakeAsyncCallback,
                                      worker);
 }
示例#42
0
        private TransportProvider<EndPoint> AddUdpClient(EndPoint udpClientEndPoint)
        {
            TransportProvider<EndPoint> udpClient = new TransportProvider<EndPoint>();
            IPEndPoint udpClientIPEndPoint = udpClientEndPoint as IPEndPoint;
            UdpClientInfo udpClientInfo;

            // Set up client
            udpClient.SetReceiveBuffer(ReceiveBufferSize);
            udpClient.SetSendBuffer(SendBufferSize);
            udpClient.Provider = udpClientIPEndPoint;

            // If the IP specified for the client is a multicast IP, subscribe to the specified multicast group.
            if ((object)udpClientIPEndPoint != null && Transport.IsMulticastIP(udpClientIPEndPoint.Address))
            {
                SocketOptionLevel level = udpClientIPEndPoint.AddressFamily == AddressFamily.InterNetworkV6 ? SocketOptionLevel.IPv6 : SocketOptionLevel.IP;
                string multicastSource;

                if (m_configData.TryGetValue("multicastSource", out multicastSource))
                {
                    IPAddress sourceAddress = IPAddress.Parse(multicastSource);
                    IPAddress localAddress = (udpClientIPEndPoint.AddressFamily == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any);

                    if (sourceAddress.AddressFamily != udpClientIPEndPoint.AddressFamily)
                        throw new InvalidOperationException($"Source address \"{sourceAddress}\" is not in the same IP format as server address \"{udpClientIPEndPoint.Address}\"");

                    if (localAddress.AddressFamily != udpClientIPEndPoint.AddressFamily)
                        throw new InvalidOperationException($"Local address \"{localAddress}\" is not in the same IP format as server address \"{udpClientIPEndPoint.Address}\"");

                    using (BlockAllocatedMemoryStream membershipAddresses = new BlockAllocatedMemoryStream())
                    {
                        byte[] serverAddressBytes = udpClientIPEndPoint.Address.GetAddressBytes();
                        byte[] sourceAddressBytes = sourceAddress.GetAddressBytes();
                        byte[] localAddressBytes = localAddress.GetAddressBytes();

                        membershipAddresses.Write(serverAddressBytes, 0, serverAddressBytes.Length);
                        membershipAddresses.Write(sourceAddressBytes, 0, sourceAddressBytes.Length);
                        membershipAddresses.Write(localAddressBytes, 0, localAddressBytes.Length);

                        udpClient.MulticastMembershipAddresses = membershipAddresses.ToArray();
                    }

                    // Execute multicast subscribe for specific source
                    m_udpServer.Provider.SetSocketOption(level, SocketOptionName.AddSourceMembership, udpClient.MulticastMembershipAddresses);
                    m_udpServer.Provider.SetSocketOption(level, SocketOptionName.MulticastTimeToLive, int.Parse(m_configData["multicastTimeToLive"]));
                }
                else
                {
                    // Execute multicast subscribe for any source
                    m_udpServer.Provider.SetSocketOption(level, SocketOptionName.AddMembership, new MulticastOption(udpClientIPEndPoint.Address));
                    m_udpServer.Provider.SetSocketOption(level, SocketOptionName.MulticastTimeToLive, int.Parse(m_configData["multicastTimeToLive"]));
                }
            }

            // Create client info object
            udpClientInfo = new UdpClientInfo
            {
                Client = udpClient,
                SendArgs = FastObjectFactory<SocketAsyncEventArgs>.CreateObjectFunction(),
                SendLock = new object(),
                SendQueue = new ConcurrentQueue<UdpServerPayload>()
            };

            udpClientInfo.DumpPayloadsOperation = new ShortSynchronizedOperation(() =>
            {
                UdpServerPayload payload;

                // Check to see if the client has reached the maximum send queue size.
                if (m_maxSendQueueSize > 0 && udpClientInfo.SendQueue.Count >= m_maxSendQueueSize)
                {
                    for (int i = 0; i < m_maxSendQueueSize; i++)
                    {
                        if (udpClientInfo.SendQueue.TryDequeue(out payload))
                        {
                            payload.WaitHandle.Set();
                            payload.WaitHandle.Dispose();
                            payload.WaitHandle = null;
                        }
                    }

                    throw new InvalidOperationException($"Client {udpClientInfo.Client.ID} connected to UDP server reached maximum send queue size. {m_maxSendQueueSize} payloads dumped from the queue.");
                }
            }, ex => OnSendClientDataException(udpClientInfo.Client.ID, ex));

            // Set up SocketAsyncEventArgs
            udpClientInfo.SendArgs.RemoteEndPoint = udpClient.Provider;
            udpClientInfo.SendArgs.SetBuffer(udpClient.SendBuffer, 0, udpClient.SendBufferSize);
            udpClientInfo.SendArgs.Completed += m_sendHandler;

            // Add new client to the lookup
            m_clientInfoLookup.TryAdd(udpClient.ID, udpClientInfo);
            OnClientConnected(udpClient.ID);

            return udpClient;
        }
示例#43
0
文件: UdpServer.cs 项目: rmc00/gsf
        /// <summary>
        /// Starts the <see cref="UdpServer"/> synchronously and begins accepting client connections asynchronously.
        /// </summary>
        /// <exception cref="InvalidOperationException">Attempt is made to <see cref="Start()"/> the <see cref="UdpServer"/> when it is running.</exception>
        public override void Start()
        {
            if (CurrentState == ServerState.NotRunning)
            {
                int maxSendQueueSize;

                // Initialize if unitialized
                if (!Initialized)
                    Initialize();

                // Overwrite config file if max send queue size exists in connection string.
                if (m_configData.ContainsKey("maxSendQueueSize") && int.TryParse(m_configData["maxSendQueueSize"], out maxSendQueueSize))
                    m_maxSendQueueSize = maxSendQueueSize;

                // Bind server socket to local end-point
                m_udpServer = new TransportProvider<Socket>();
                m_udpServer.SetReceiveBuffer(ReceiveBufferSize);
                m_udpServer.Provider = Transport.CreateSocket(m_configData["interface"], int.Parse(m_configData["port"]), ProtocolType.Udp, m_ipStack, m_allowDualStackSocket);

                // Disable SocketError.ConnectionReset exception from being thrown when the endpoint is not listening
                m_udpServer.Provider.IOControl(SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);

                // Notify that the server has been started successfully
                OnServerStarted();

                if ((object)m_udpServer.Provider.LocalEndPoint != null)
                {
                    m_receiveArgs = FastObjectFactory<SocketAsyncEventArgs>.CreateObjectFunction();
                    m_receiveArgs.SocketFlags = SocketFlags.None;
                    m_receiveArgs.Completed += m_receiveHandler;
                    ReceivePayloadAsync(m_receiveArgs);
                }

                // We process the static list to clients.
                foreach (string clientString in m_configData["clients"].Replace(" ", "").Split(','))
                {
                    try
                    {
                        Match endpoint = Regex.Match(clientString, Transport.EndpointFormatRegex);

                        if (endpoint != Match.Empty)
                        {
                            UdpClientInfo clientInfo;
                            TransportProvider<EndPoint> udpClient = new TransportProvider<EndPoint>();
                            IPEndPoint clientEndpoint = Transport.CreateEndPoint(endpoint.Groups["host"].Value, int.Parse(endpoint.Groups["port"].Value), m_ipStack);

                            udpClient.SetReceiveBuffer(ReceiveBufferSize);
                            udpClient.SetSendBuffer(SendBufferSize);
                            udpClient.Provider = clientEndpoint;

                            // If the IP specified for the client is a multicast IP, subscribe to the specified multicast group.
                            if (Transport.IsMulticastIP(clientEndpoint.Address))
                            {
                                string multicastSource;

                                if (m_configData.TryGetValue("multicastSource", out multicastSource))
                                {
                                    IPAddress sourceAddress = IPAddress.Parse(multicastSource);
                                    IPAddress localAddress = (clientEndpoint.AddressFamily == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any);

                                    if (sourceAddress.AddressFamily != clientEndpoint.AddressFamily)
                                        throw new InvalidOperationException(string.Format("Source address \"{0}\" is not in the same IP format as server address \"{1}\"", sourceAddress, clientEndpoint.Address));

                                    if (localAddress.AddressFamily != clientEndpoint.AddressFamily)
                                        throw new InvalidOperationException(string.Format("Local address \"{0}\" is not in the same IP format as server address \"{1}\"", localAddress, clientEndpoint.Address));

                                    MemoryStream membershipAddresses = new MemoryStream();

                                    byte[] serverAddressBytes = clientEndpoint.Address.GetAddressBytes();
                                    byte[] sourceAddressBytes = sourceAddress.GetAddressBytes();
                                    byte[] localAddressBytes = localAddress.GetAddressBytes();

                                    membershipAddresses.Write(serverAddressBytes, 0, serverAddressBytes.Length);
                                    membershipAddresses.Write(sourceAddressBytes, 0, sourceAddressBytes.Length);
                                    membershipAddresses.Write(localAddressBytes, 0, localAddressBytes.Length);

                                    udpClient.MulticastMembershipAddresses = membershipAddresses.ToArray();

                                    // Execute multicast subscribe for specific source
                                    SocketOptionLevel level = clientEndpoint.AddressFamily == AddressFamily.InterNetworkV6 ? SocketOptionLevel.IPv6 : SocketOptionLevel.IP;
                                    m_udpServer.Provider.SetSocketOption(level, SocketOptionName.AddSourceMembership, udpClient.MulticastMembershipAddresses);
                                    m_udpServer.Provider.SetSocketOption(level, SocketOptionName.MulticastTimeToLive, int.Parse(m_configData["multicastTimeToLive"]));
                                }
                                else
                                {
                                    // Execute multicast subscribe for any source
                                    SocketOptionLevel level = clientEndpoint.AddressFamily == AddressFamily.InterNetworkV6 ? SocketOptionLevel.IPv6 : SocketOptionLevel.IP;
                                    m_udpServer.Provider.SetSocketOption(level, SocketOptionName.AddMembership, new MulticastOption(clientEndpoint.Address));
                                    m_udpServer.Provider.SetSocketOption(level, SocketOptionName.MulticastTimeToLive, int.Parse(m_configData["multicastTimeToLive"]));
                                }
                            }

                            clientInfo = new UdpClientInfo()
                            {
                                Client = udpClient,
                                SendArgs = FastObjectFactory<SocketAsyncEventArgs>.CreateObjectFunction(),
                                SendLock = new SpinLock(),
                                SendQueue = new ConcurrentQueue<UdpServerPayload>()
                            };

                            clientInfo.SendArgs.RemoteEndPoint = udpClient.Provider;
                            clientInfo.SendArgs.SetBuffer(udpClient.SendBuffer, 0, udpClient.SendBufferSize);
                            clientInfo.SendArgs.Completed += m_sendHandler;

                            m_clientInfoLookup.TryAdd(udpClient.ID, clientInfo);
                            OnClientConnected(udpClient.ID);
                        }
                    }
                    catch (Exception ex)
                    {
                        string errorMessage = string.Format("Unable to connect to client {0}: {1}", clientString, ex.Message);
                        OnClientConnectingException(new Exception(errorMessage, ex));
                    }
                }
            }
            else
            {
                throw new InvalidOperationException("Server is currently running");
            }
        }
示例#44
0
文件: SslServer.cs 项目: avs009/gsf
        /// <summary>
        /// Callback method for asynchronous accept operation.
        /// </summary>
        private void ProcessAccept()
        {
            TransportProvider<SslStream> client = new TransportProvider<SslStream>();
            IPEndPoint remoteEndPoint = null;
            NetworkStream netStream;

            Tuple<TransportProvider<SslStream>, IPEndPoint> asyncState;

            try
            {
                if (CurrentState == ServerState.NotRunning)
                    return;

                if (m_acceptArgs.SocketError != SocketError.Success)
                {
                    // Error is unrecoverable.
                    // We need to make sure to restart the
                    // server before we throw the error.
                    SocketError error = m_acceptArgs.SocketError;
                    ThreadPool.QueueUserWorkItem(state => ReStart());
                    throw new SocketException((int)error);
                }

                // Process the newly connected client.
                remoteEndPoint = m_acceptArgs.AcceptSocket.RemoteEndPoint as IPEndPoint;
                netStream = new NetworkStream(m_acceptArgs.AcceptSocket);
                client.Provider = new SslStream(netStream, false, m_remoteCertificateValidationCallback, m_localCertificateSelectionCallback);

                asyncState = new Tuple<TransportProvider<SslStream>, IPEndPoint>(client, remoteEndPoint);
                client.Provider.BeginAuthenticateAsServer(m_certificate, true, m_enabledSslProtocols, m_checkCertificateRevocation, ProcessAuthenticate, asyncState);

                // Return to accepting new connections.
                m_acceptArgs.AcceptSocket = null;

                if (!m_tcpServer.AcceptAsync(m_acceptArgs))
                {
                    ThreadPool.QueueUserWorkItem(state => ProcessAccept());
                }
            }
            catch (Exception ex)
            {
                // Notify of the exception.
                if ((object)remoteEndPoint != null)
                {
                    string clientAddress = remoteEndPoint.Address.ToString();
                    string errorMessage = string.Format("Unable to accept connection to client [{0}]: {1}", clientAddress, ex.Message);
                    OnClientConnectingException(new Exception(errorMessage, ex));
                }

                TerminateConnection(client, false);
            }
        }
示例#45
0
 /// <summary>
 /// Initiate method for asynchronous receive operation of payload data in "payload-aware" mode.
 /// </summary>
 private void ReceivePayloadAwareAsync(TransportProvider<TlsSocket> client, bool waitingForHeader)
 {
     client.Provider.SslStream.BeginRead(client.ReceiveBuffer,
                                         client.BytesReceived,
                                         client.ReceiveBufferSize - client.BytesReceived,
                                         ProcessReceivePayloadAware,
                                         new Tuple<Guid, bool>(client.ID, waitingForHeader));
 }
示例#46
0
文件: UdpServer.cs 项目: avs009/gsf
        /// <summary>
        /// Callback method for asynchronous receive operation of payload data from any endpoint.
        /// </summary>
        private void ReceivePayloadAnyAsyncCallback(IAsyncResult asyncResult)
        {
            TransportProvider<Socket> udpServer = (TransportProvider<Socket>)asyncResult.AsyncState;
            try
            {
                // Update statistics and pointers.
                udpServer.Statistics.UpdateBytesReceived(udpServer.Provider.EndReceiveFrom(asyncResult, ref m_udpClientEndPoint));
                udpServer.ReceiveBufferLength = udpServer.Statistics.LastBytesReceived;

                // Get a local copy of all connected clients.
                TransportProvider<Socket>[] clients = null;
                lock (m_udpClients)
                {
                    clients = new TransportProvider<Socket>[m_udpClients.Count];
                    m_udpClients.Values.CopyTo(clients, 0);
                }

                // Search connected clients for a client connected to the end-point from where this data is received.
                foreach (TransportProvider<Socket> client in clients)
                {
                    if (client.Provider.RemoteEndPoint.Equals(m_udpClientEndPoint))
                    {
                        // Found a match, notify of data.
                        OnReceiveClientDataComplete(client.ID, udpServer.ReceiveBuffer, udpServer.ReceiveBufferLength);
                        break;
                    }
                }

                // Resume receive operation on the server socket.
                ReceivePayloadAnyAsync(udpServer);
            }
            catch
            {
                // Server socket has been terminated.
                udpServer.Reset();
                OnServerStopped();
            }
        }
示例#47
0
 /// <summary>
 /// Initiate method for asynchronous receive operation of payload data in "payload-unaware" mode.
 /// </summary>
 private void ReceivePayloadUnawareAsync(TransportProvider<TlsSocket> client)
 {
     client.Provider.SslStream.BeginRead(client.ReceiveBuffer,
                                         0,
                                         client.ReceiveBufferSize,
                                         ProcessReceivePayloadUnaware,
                                         client);
 }
示例#48
0
文件: UdpServer.cs 项目: avs009/gsf
 /// <summary>
 /// Initiate method for asynchronous receive operation of payload data from a single endpoint.
 /// </summary>
 private void ReceivePayloadOneAsync(TransportProvider<Socket> worker)
 {
     EndPoint client = worker.Provider.RemoteEndPoint;
     if (ReceiveTimeout == -1)
     {
         // Wait for data indefinitely.
         worker.Provider.BeginReceiveFrom(worker.ReceiveBuffer,
                                          worker.ReceiveBufferOffset,
                                          worker.ReceiveBuffer.Length,
                                          SocketFlags.None,
                                          ref client,
                                          ReceivePayloadOneAsyncCallback,
                                          worker);
     }
     else
     {
         // Wait for data with a timeout.
         worker.WaitAsync(ReceiveTimeout,
                          ReceivePayloadOneAsyncCallback,
                          worker.Provider.BeginReceiveFrom(worker.ReceiveBuffer,
                                                           worker.ReceiveBufferOffset,
                                                           worker.ReceiveBuffer.Length,
                                                           SocketFlags.None,
                                                           ref client,
                                                           ReceivePayloadOneAsyncCallback,
                                                           worker));
     }
 }
示例#49
0
        /// <summary>
        /// Gets the <see cref="TransportProvider{TlsSocket}"/> object associated with the specified client ID.
        /// </summary>
        /// <param name="clientID">ID of the client.</param>
        /// <param name="tlsClient">The TLS client.</param>
        /// <returns>An <see cref="TransportProvider{TlsSocket}"/> object.</returns>
        /// <exception cref="InvalidOperationException">Client does not exist for the specified <paramref name="clientID"/>.</exception>
        public bool TryGetClient(Guid clientID, out TransportProvider<TlsSocket> tlsClient)
        {
            TlsClientInfo clientInfo;
            bool clientExists = m_clientInfoLookup.TryGetValue(clientID, out clientInfo);

            if (clientExists)
                tlsClient = clientInfo.Client;
            else
                tlsClient = null;

            return clientExists;
        }
示例#50
0
文件: UdpServer.cs 项目: avs009/gsf
 /// <summary>
 /// Delegate that gets called to verify client disconnect when <see cref="ServerBase.Handshake"/> is turned off.
 /// </summary>
 private bool NoGoodbyeCheck(TransportProvider<Socket> client)
 {
     return false;
 }
示例#51
0
        /// <summary>
        /// Starts the <see cref="UdpServer"/> synchronously and begins accepting client connections asynchronously.
        /// </summary>
        /// <exception cref="InvalidOperationException">Attempt is made to <see cref="Start()"/> the <see cref="UdpServer"/> when it is running.</exception>
        public override void Start()
        {
            if (CurrentState == ServerState.NotRunning)
            {
                ClientIdentificationMode clientIdentificationMode;
                int maxSendQueueSize;

                // Initialize if uninitialized
                if (!Initialized)
                    Initialize();

                // Overwrite config file if client identification mode exists in connection string.
                if (m_configData.ContainsKey("identifyClientsBy") && Enum.TryParse(m_configData["identifyClientsBy"], true, out clientIdentificationMode))
                    m_clientIdentificationMode = clientIdentificationMode;

                // Overwrite config file if client end points are dynamic
                if (m_configData.ContainsKey("dynamicClientEndPoints"))
                    m_dynamicClientEndPoints = m_configData["dynamicClientEndPoints"].ParseBoolean();

                // Overwrite config file if max send queue size exists in connection string.
                if (m_configData.ContainsKey("maxSendQueueSize") && int.TryParse(m_configData["maxSendQueueSize"], out maxSendQueueSize))
                    m_maxSendQueueSize = maxSendQueueSize;

                // Bind server socket to local end-point
                m_udpServer = new TransportProvider<Socket>();
                m_udpServer.SetReceiveBuffer(ReceiveBufferSize);
                m_udpServer.Provider = Transport.CreateSocket(m_configData["interface"], int.Parse(m_configData["port"]), ProtocolType.Udp, m_ipStack, m_allowDualStackSocket);
                m_udpServer.Provider.ReceiveBufferSize = ReceiveBufferSize;

                // Disable SocketError.ConnectionReset exception from being thrown when the endpoint is not listening
		// Fix MONO bug with SIO_UDP_CONNRESET
                try
                {
                    m_udpServer.Provider.IOControl(SIO_UDP_CONNRESET, new[] { Convert.ToByte(false) }, null);
                }
                catch
                {
                }

                // Notify that the server has been started successfully
                OnServerStarted();

                if ((object)m_udpServer.Provider.LocalEndPoint != null)
                {
                    m_receiveArgs = FastObjectFactory<SocketAsyncEventArgs>.CreateObjectFunction();
                    m_receiveArgs.SocketFlags = SocketFlags.None;
                    m_receiveArgs.Completed += m_receiveHandler;
                    ReceivePayloadAsync(m_receiveArgs);
                }

                // Determine whether we have a static or dynamic client list
                m_dynamicClientList = !m_configData.ContainsKey("clients");

                if (m_dynamicClientList)
                {
                    m_dynamicClientEndPoints = true;
                }
                else
                {
                    // We process the static list of clients.
                    foreach (string clientString in m_configData["clients"].Replace(" ", "").Split(','))
                    {
                        try
                        {
                            Match endpoint = Regex.Match(clientString, Transport.EndpointFormatRegex);
                            int port;

                            if (endpoint != Match.Empty)
                                AddUdpClient(endpoint.Groups["host"].Value, int.Parse(endpoint.Groups["port"].Value));
                            else if (int.TryParse(clientString, out port))
                                AddUdpClient(null, port);
                            else
                                AddUdpClient(clientString, 0);
                        }
                        catch (Exception ex)
                        {
                            string errorMessage = $"Unable to connect to client {clientString}: {ex.Message}";
                            OnClientConnectingException(new Exception(errorMessage, ex));
                        }
                    }
                }
            }
            else
            {
                throw new InvalidOperationException("Server is currently running");
            }
        }
示例#52
0
文件: UdpServer.cs 项目: avs009/gsf
        /// <summary>
        /// Delegate that gets called to verify client disconnect when <see cref="ServerBase.Handshake"/> is turned on.
        /// </summary>
        private bool DoGoodbyeCheck(TransportProvider<Socket> client)
        {
            // Process data received in the buffer.
            int offset = client.ReceiveBufferOffset;
            int length = client.ReceiveBufferLength;
            byte[] buffer = client.ReceiveBuffer.BlockCopy(0, length);
            Payload.ProcessReceived(ref buffer, ref offset, ref length, Encryption, client.Secretkey, Compression);

            // Check if data is for goodbye message.
            return (new GoodbyeMessage().Initialize(buffer, offset, length) != -1);
        }
示例#53
0
文件: TcpServer.cs 项目: rmc00/gsf
        /// <summary>
        /// Processes the termination of client.
        /// </summary>
        private void TerminateConnection(TransportProvider<Socket> client, SocketAsyncEventArgs args, bool raiseEvent)
        {
            TcpClientInfo clientInfo;

            try
            {
                if (m_clientInfoLookup.TryRemove(client.ID, out clientInfo))
                {
                    client.Reset();
                    clientInfo.SendArgs.Dispose();
                }

                if (raiseEvent)
                    OnClientDisconnected(client.ID);
            }
            finally
            {
                DisposeReceiveArgs(args);
            }
        }
示例#54
0
文件: TcpServer.cs 项目: avs009/gsf
        /// <summary>
        /// Processes the termination of client.
        /// </summary>
        private void TerminateConnection(TransportProvider<Socket> client, bool raiseEvent)
        {
            client.Reset();
            if (raiseEvent)
                OnClientDisconnected(client.ID);

            lock (m_tcpClients)
            {
                if (m_tcpClients.ContainsKey(client.ID))
                    m_tcpClients.Remove(client.ID);
            }
        }
示例#55
0
文件: TcpServer.cs 项目: avs009/gsf
 /// <summary>
 /// Initiate method for asynchronous receive operation of handshake data.
 /// </summary>
 private void ReceiveHandshakeAsync(TransportProvider<Socket> worker)
 {
     // Prepare buffer used for receiving data.
     worker.ReceiveBufferOffset = 0;
     worker.ReceiveBufferLength = -1;
     worker.ReceiveBuffer = new byte[ReceiveBufferSize];
     // Receive data asynchronously with a timeout.
     worker.WaitAsync(HandshakeTimeout,
                      ReceiveHandshakeAsyncCallback,
                      worker.Provider.BeginReceive(worker.ReceiveBuffer,
                                                   worker.ReceiveBufferOffset,
                                                   worker.ReceiveBuffer.Length,
                                                   SocketFlags.None,
                                                   ReceiveHandshakeAsyncCallback,
                                                   worker));
 }
示例#56
0
 public CustomTransportListener(ConnectionListener listener, TransportProvider provider)
 {
     this.Listener = listener;
     this.provider = provider;
 }
示例#57
0
文件: TcpServer.cs 项目: avs009/gsf
        /// <summary>
        /// Initiate method for asynchronous receive operation of payload data in "payload-unaware" mode.
        /// </summary>
        private void ReceivePayloadUnawareAsync(TransportProvider<Socket> worker)
        {
            if (ReceiveTimeout == -1)
            {
                // Wait for data indefinitely.
                worker.Provider.BeginReceive(worker.ReceiveBuffer,
                                             worker.ReceiveBufferOffset,
                                             worker.ReceiveBuffer.Length - worker.ReceiveBufferOffset,
                                             SocketFlags.None,
                                             ReceivePayloadUnawareAsyncCallback,
                                             worker);
            }
            else
            {
                // Wait for data with a timeout.
                worker.WaitAsync(ReceiveTimeout,
                                 ReceivePayloadUnawareAsyncCallback,
                                 worker.Provider.BeginReceive(worker.ReceiveBuffer,
                                                              worker.ReceiveBufferOffset,
                                                              worker.ReceiveBuffer.Length - worker.ReceiveBufferOffset,
                                                              SocketFlags.None,
                                                              ReceivePayloadUnawareAsyncCallback,
                                                              worker));

            }
        }
示例#58
0
文件: UdpServer.cs 项目: rmc00/gsf
        /// <summary>
        /// Gets the <see cref="TransportProvider{EndPoint}"/> object associated with the specified client ID.
        /// </summary>
        /// <param name="clientID">ID of the client.</param>
        /// <param name="udpClient">The UDP client.</param>
        /// <returns>An <see cref="TransportProvider{EndPoint}"/> object.</returns>
        /// <exception cref="InvalidOperationException">Client does not exist for the specified <paramref name="clientID"/>.</exception>
        public bool TryGetClient(Guid clientID, out TransportProvider<EndPoint> udpClient)
        {
            UdpClientInfo clientInfo;
            bool clientExists;

            clientExists = m_clientInfoLookup.TryGetValue(clientID, out clientInfo);

            if (clientExists)
                udpClient = clientInfo.Client;
            else
                udpClient = null;

            return clientExists;
        }
示例#59
0
文件: TcpClient.cs 项目: rmc00/gsf
        /// <summary>
        /// Initializes a new instance of the <see cref="TcpClient"/> class.
        /// </summary>
        /// <param name="connectString">Connect string of the <see cref="TcpClient"/>. See <see cref="DefaultConnectionString"/> for format.</param>
        public TcpClient(string connectString)
            : base(TransportProtocol.Tcp, connectString)
        {
            m_sendLock = new SpinLock();
            m_sendQueue = new ConcurrentQueue<TcpClientPayload>();
            m_payloadAware = DefaultPayloadAware;
            m_payloadMarker = Payload.DefaultMarker;
            m_integratedSecurity = DefaultIntegratedSecurity;
            m_allowDualStackSocket = DefaultAllowDualStackSocket;
            m_maxSendQueueSize = DefaultMaxSendQueueSize;
            m_tcpClient = new TransportProvider<Socket>();

            m_connectHandler = (o, args) => ProcessConnect();
            m_sendHandler = (o, args) => ProcessSend();
            m_receivePayloadAwareHandler = (o, args) => ProcessReceivePayloadAware();
            m_receivePayloadUnawareHandler = (o, args) => ProcessReceivePayloadUnaware();
        }
示例#60
0
文件: ZeroMQServer.cs 项目: rmc00/gsf
 /// <summary>
 /// Gets the <see cref="TransportProvider{Socket}"/> object associated with the specified client ID.
 /// </summary>
 /// <param name="clientID">ID of the client.</param>
 /// <param name="clientInfo">Client information.</param>
 /// <returns><c>true</c> if client exists; otherwise, <c>false</c>.</returns>
 public bool TryGetClient(Guid clientID, out TransportProvider<DateTime> clientInfo)
 {
     return m_clientInfoLookup.TryGetValue(clientID, out clientInfo);
 }