Ejemplo n.º 1
0
        /// <inheritdoc/>
        public void AddObserveRelation(ObserveRelation relation)
        {
            ObserveRelation old = null;

            _observeRelations.AddOrUpdate(relation.Key, relation, (k, v) =>
            {
                old = v;
                return(relation);
            });

            if (old != null)
            {
                old.Cancel();
                if (log.IsDebugEnabled)
                {
                    log.Debug("Replacing observe relation between " + relation.Key + " and resource " + Uri);
                }
            }
            else
            {
                if (log.IsDebugEnabled)
                {
                    log.Debug("Successfully established observe relation between " + relation.Key + " and resource " + Uri);
                }
            }
        }
Ejemplo n.º 2
0
 /// <inheritdoc/>
 public override void ReceiveEmptyMessage(INextLayer nextLayer, Exchange exchange, EmptyMessage message)
 {
     // NOTE: We could also move this into the MessageObserverAdapter from
     // sendResponse into the method rejected().
     if (message.Type == MessageType.RST && exchange.Origin == Origin.Remote)
     {
         // The response has been rejected
         ObserveRelation relation = exchange.Relation;
         if (relation != null)
         {
             relation.Cancel();
         } // else there was no observe relation ship and this layer ignores the rst
     }
     base.ReceiveEmptyMessage(nextLayer, exchange, message);
 }
        private void CheckForObserveOption(Exchange exchange, IResource resource)
        {
            Request request = exchange.Request;

            if (request.Method != Method.GET)
            {
                return;
            }

            System.Net.EndPoint source = request.Source;
            Int32?obs = request.Observe;

            if (obs.HasValue && resource.Observable)
            {
                if (obs == 0)
                {
                    // Requests wants to observe and resource allows it :-)
                    if (log.IsDebugEnabled)
                    {
                        log.Debug("Initiate an observe relation between " + source + " and resource " + resource.Uri);
                    }
                    ObservingEndpoint remote   = _observeManager.FindObservingEndpoint(source);
                    ObserveRelation   relation = new ObserveRelation(_config, remote, resource, exchange);
                    remote.AddObserveRelation(relation);
                    exchange.Relation = relation;
                    // all that's left is to add the relation to the resource which
                    // the resource must do itself if the response is successful
                }
                else if (obs == 1)
                {
                    ObserveRelation relation = _observeManager.GetRelation(source, request.Token);
                    if (relation != null)
                    {
                        relation.Cancel();
                    }
                }
            }
        }
Ejemplo n.º 4
0
        /// <inheritdoc/>
        public override void SendResponse(INextLayer nextLayer, Exchange exchange, Response response)
        {
            ObserveRelation relation = exchange.Relation;

            if (relation != null && relation.Established)
            {
                if (exchange.Request.IsAcknowledged || exchange.Request.Type == MessageType.NON)
                {
                    // Transmit errors as CON
                    if (!Code.IsSuccess(response.Code))
                    {
                        if (log.IsDebugEnabled)
                        {
                            log.Debug("Response has error code " + response.Code + " and must be sent as CON");
                        }
                        response.Type = MessageType.CON;
                        relation.Cancel();
                    }
                    else
                    {
                        // Make sure that every now and than a CON is mixed within
                        if (relation.Check())
                        {
                            if (log.IsDebugEnabled)
                            {
                                log.Debug("The observe relation check requires the notification to be sent as CON");
                            }
                            response.Type = MessageType.CON;
                        }
                        else
                        {
                            // By default use NON, but do not override resource decision
                            if (response.Type == MessageType.Unknown)
                            {
                                response.Type = MessageType.NON;
                            }
                        }
                    }
                }

                // This is a notification
                response.Last = false;

                /*
                 * The matcher must be able to find the NON notifications to remove
                 * them from the exchangesByID map
                 */
                if (response.Type == MessageType.NON)
                {
                    relation.AddNotification(response);
                }

                /*
                 * Only one Confirmable message is allowed to be in transit. A CON
                 * is in transit as long as it has not been acknowledged, rejected,
                 * or timed out. All further notifications are postponed here. If a
                 * former CON is acknowledged or timeouts, it starts the freshest
                 * notification (In case of a timeout, it keeps the retransmission
                 * counter). When a fresh/younger notification arrives but must be
                 * postponed we forget any former notification.
                 */
                if (response.Type == MessageType.CON)
                {
                    PrepareSelfReplacement(nextLayer, exchange, response);
                }

                // The decision whether to postpone this notification or not and the
                // decision which notification is the freshest to send next must be
                // synchronized
                lock (exchange)
                {
                    Response current = relation.CurrentControlNotification;
                    if (current != null && IsInTransit(current))
                    {
                        if (log.IsDebugEnabled)
                        {
                            log.Debug("A former notification is still in transit. Postpone " + response);
                        }
                        // use the same ID
                        response.ID = current.ID;
                        relation.NextControlNotification = response;
                        return;
                    }
                    else
                    {
                        relation.CurrentControlNotification = response;
                        relation.NextControlNotification    = null;
                    }
                }
            }
            // else no observe was requested or the resource does not allow it
            base.SendResponse(nextLayer, exchange, response);
        }