コード例 #1
0
 /// <summary>
 /// Extracts the Envelope's header.
 /// </summary>
 /// <param name="envelope">The <see cref="TransportEnvelope"/> to retrieve the header from.</param>
 /// <returns>The <see cref="ITransportEnvelopeHeader"/> belonging to the given <see cref="TransportEnvelope"/>.</returns>
 public ITransportEnvelopeHeader ExtractHeader(TransportEnvelope envelope)
 {
     return((new Converters.TypeSerializer <ITransportEnvelopeHeader>())
            .FromByteArray(TransportConfiguration.Compressor
                           .Decompress(TransportConfiguration.Encryptor
                                       .Decrypt(envelope.Header))));
 }
コード例 #2
0
        /// <summary>
        /// Takes an <see cref="TransportEnvelope"/> and sends it to the server.
        /// </summary>
        /// <param name="envelope">The <see cref="TransportEnvelope"/> to transmit to the server.</param>
        /// <param name="exception">Contains any exceptions encountered; otherwise <b>null</b>.</param>
        /// <returns><b>True</b> if successful; otherwise <b>false</b>.</returns>
        protected override bool PushEnvelopeToServer(TransportEnvelope envelope,
                                                     out Exception exception)
        {
            // ******** SEND ENVELOPE TO SERVER ********

            bool results = false;

            if (_ServiceProxy == null)
            {
                exception = new Exception("The client has been closed.");
            }
            else
            {
                exception = null;
                try
                {
                    _ServiceProxy.PushEnvelopeToServer(envelope);
                    results = true;
                }
                catch (Exception ex)
                {
                    DestroyConnection();
                    exception = new Exception($"Unable to establish connection with server at {Address}", ex);
                }
            }
            return(results);
        }
コード例 #3
0
        /// <summary>
        /// Transmits a <see cref="TransportEnvelope"/> to the <b>Actual Client</b>.
        /// </summary>
        /// <param name="envelope">A piece of an <see cref="IMessage"/> to be transmitted to the <b>Actual Client</b>.</param>
        public void PushEnvelopeToClient(TransportEnvelope envelope)
        {
            // ******** RECIEVED ENVELOPE FROM SERVER ********

            IMessage message = _TransporterController.AddEnvelopeFromTransport(envelope);

            if (message != null)
            {
                _MessageChannelAction(new MessageEventArgs(message));
            }
        }
コード例 #4
0
        /// <summary>
        /// Takes <see cref="TransportEnvelope"/>s and puts them together into a whole <see cref="IMessage"/>.
        /// </summary>
        /// <param name="envelope">The <see cref="TransportEnvelope"/> to process.</param>
        /// <returns>If enough chucks have arrived to create a whole message; then that message will be returned; otherwise, <b>null</b>.</returns>
        public IMessage AddEnvelopeFromTransport(TransportEnvelope envelope)
        {
            if (envelope == null)
            {
                throw new ArgumentNullException("envelope");
            }
            // update statistics
            lock (_SyncRootTransportStatistics)
            {
                _TransportStatistics.IncomingEnvelopes++;
                _TransportStatistics.IncomingBytes += (envelope.Header.Length + envelope.Payload.Length);
            }
            //
            envelope.HeaderActual = ExtractHeader(envelope);
            IMessage message = null;

            lock (_SyncRootEnvelopeCache)
            {
                // #### add envelope to proper group
                if (_EnvelopeCache.ContainsKey(envelope.HeaderActual.Id))
                {
                    // update existing group
                    _EnvelopeCache[envelope.HeaderActual.Id].Payload.Envelopes.Add(envelope);
                }
                else
                {
                    // create new group
                    var group = new TransportEnvelopeGroup(envelope.HeaderActual.Id, envelope.HeaderActual);
                    group.Envelopes.Add(envelope);
                    var cacheItem = new Cache.CacheItem <TransportEnvelopeGroup>(group,
                                                                                 new Cache.ValidateTime <TransportEnvelopeGroup>(DateTime.Now.Add(TransportConfiguration.EnvelopeCacheTimeLimit)));
                    _EnvelopeCache.AddItem(envelope.HeaderActual.Id, cacheItem);
                }

                // #### check for completed message
                string processedMessageId = "";
                foreach (var cacheItem in _EnvelopeCache.Items)
                {
                    var expectedTotal = cacheItem.Payload.Header.ChunkTotal;
                    var total         = cacheItem.Payload.Envelopes.Count;
                    if (expectedTotal == total)
                    {
                        processedMessageId = cacheItem.Payload.Id;
                        var worker = Common.ByteArrayHelper.RestoreByteArray(from x in cacheItem.Payload.Envelopes
                                                                             orderby x.HeaderActual.ChunkIndex ascending
                                                                             select x.Payload);
                        worker  = TransportConfiguration.Encryptor.Decrypt(worker);
                        worker  = TransportConfiguration.Compressor.Decompress(worker);
                        message = (new dodSON.Core.Converters.TypeSerializer <IMessage>()).FromByteArray(worker);
                        // update statistics
                        lock (_SyncRootTransportStatistics)
                        {
                            _TransportStatistics.IncomingMessages++;
                        }
                    }
                }
                // #### remove processed message
                if (_EnvelopeCache.ContainsKey(processedMessageId))
                {
                    _EnvelopeCache.RemoveItem(processedMessageId);
                }
                // courtesy purge
                _EnvelopeCache.Purge();

                // #### check if message has already been processed
                if (message != null)
                {
                    // #### primary gate --> cached message id
                    lock (_SyncRootSeenMessagesCache)
                    {
                        // check cache for seen message
                        if (_SeenMessagesCache.ContainsKey(message.Id))
                        {
                            // reset cached item
                            _SeenMessagesCache[message.Id].Validator.Reset();
                            // message stops here.
                            return(null);
                        }
                        // add message.Id to cache
                        _SeenMessagesCache.AddItem(message.Id, new Cache.CacheItem <string>(message.Id, new Cache.ValidateTime <string>(DateTime.Now + TransportConfiguration.SeenMessageCacheTimeLimit)));
                        // courtesy purge
                        _SeenMessagesCache.Purge();
                    }

                    // #### fail-safe gate --> server id list
                    // check if server id in ServerIds list
                    if (message.ServerIds.Split(',').Contains(TransportConfiguration.ServerId))
                    {
                        // message stops here.
                        return(null);
                    }
                    // add server id to ServerIds list
                    var comma = (message.ServerIds.Length == 0) ? "" : ",";
                    message.ServerIds += comma + TransportConfiguration.ServerId;
                }

                // #### allow message to continue...
                return(message);
            }
        }
コード例 #5
0
 private void InternalSendEnvelopeToClient(TransportEnvelope envelope, DataHolder registeredClient)
 {
     registeredClient.CallbackClient.PushEnvelopeToClient(envelope);
     registeredClient.LastUsed = DateTime.Now;
 }
コード例 #6
0
        /// <summary>
        /// Transmits the <see cref="TransportEnvelope"/> to the server.
        /// </summary>
        /// <param name="envelope">The <see cref="TransportEnvelope"/> to send to the server.</param>
        public void PushEnvelopeToServer(TransportEnvelope envelope)
        {
            // ******** RECIEVED ENVELOPE FROM CLIENT ********

            if (envelope != null)
            {
                System.Threading.Tasks.Task.Run(() =>
                {
                    // extract header, update stats
                    ITransportEnvelopeHeader header = null;
                    lock (_SyncRootTransporterController)
                    {
                        TransporterController.TransportStatisticsLive.IncomingEnvelopes++;
                        TransporterController.TransportStatisticsLive.IncomingBytes += (envelope.Header.Length + envelope.Payload.Length);
                        header = TransporterController.ExtractHeader(envelope);
                    }
                    // get list of registered clients
                    List <KeyValuePair <string, DataHolder> > workerList = null;
                    var removableClients = new List <string>();
                    lock (_SyncRootRegisteredCallbackClients)
                    {
                        workerList = new List <KeyValuePair <string, DataHolder> >(_RegisteredCallbackClients);
                    }
                    // send envelope to each registered client, that will accept it
                    System.Threading.Tasks.Parallel.ForEach(workerList, new Action <KeyValuePair <string, DataHolder> >(
                                                                (x) =>
                    {
                        try
                        {
                            // handle type-based traffic filtering
                            if (CanSendEnvelope(header, x.Value.ClientConfiguration, OverrideTypesFilter))
                            {
                                lock (_SyncRootTransporterController)
                                {
                                    TransporterController.TransportStatisticsLive.OutgoingEnvelopes++;
                                    TransporterController.TransportStatisticsLive.OutgoingBytes += (envelope.Header.Length + envelope.Payload.Length);
                                }
                                InternalSendEnvelopeToClient(envelope, x.Value);
                            }
                            else
                            {
                            }
                        }
                        catch
                        {
                            removableClients.Add(x.Value.ClientConfiguration.Id);
                        }
                    }));
                    // **** unregister unresponsive clients
                    foreach (var clientId in removableClients)
                    {
                        if (clientId != null)
                        {
                            lock (_SyncRootRegisteredCallbackClients)
                            {
                                if (_RegisteredCallbackClients.ContainsKey(clientId))
                                {
                                    _RegisteredCallbackClients.Remove(clientId);
                                }
                            }
                        }
                    }
                });
            }
            else
            {
                // TODO: A null envelope? what could have caused this and what should I do about it?
            }
        }