/// <summary> /// When we receive a Confirmable response, we acknowledge it and it also /// counts as acknowledgment for the request. If the response is a duplicate, /// we stop it here and do not forward it to the upper layer. /// </summary> public override void ReceiveResponse(INextLayer nextLayer, Exchange exchange, Response response) { TransmissionContext ctx = (TransmissionContext)exchange.Remove(TransmissionContextKey); if (ctx != null) { exchange.CurrentRequest.IsAcknowledged = true; ctx.Cancel(); } if (response.Type == MessageType.CON && !exchange.Request.IsCancelled) { if (log.IsDebugEnabled) { log.Debug("Response is confirmable, send ACK."); } EmptyMessage ack = EmptyMessage.NewACK(response); SendEmptyMessage(nextLayer, exchange, ack); } if (response.Duplicate) { if (log.IsDebugEnabled) { log.Debug("Response is duplicate, ignore it."); } } else { base.ReceiveResponse(nextLayer, exchange, response); } }
/// <summary> /// When we receive a duplicate of a request, we stop it here and do not /// forward it to the upper layer. If the server has already sent a response, /// we send it again. If the request has only been acknowledged (but the ACK /// has gone lost or not reached the client yet), we resent the ACK. If the /// request has neither been responded, acknowledged or rejected yet, the /// server has not yet decided what to do with the request and we cannot do /// anything. /// </summary> public override void ReceiveRequest(INextLayer nextLayer, Exchange exchange, Request request) { if (request.Duplicate) { // Request is a duplicate, so resend ACK, RST or response if (exchange.CurrentResponse != null) { if (log.IsDebugEnabled) { log.Debug("Respond with the current response to the duplicate request"); } base.SendResponse(nextLayer, exchange, exchange.CurrentResponse); } else if (exchange.CurrentRequest != null) { if (exchange.CurrentRequest.IsAcknowledged) { if (log.IsDebugEnabled) { log.Debug("The duplicate request was acknowledged but no response computed yet. Retransmit ACK."); } EmptyMessage ack = EmptyMessage.NewACK(request); SendEmptyMessage(nextLayer, exchange, ack); } else if (exchange.CurrentRequest.IsRejected) { if (log.IsDebugEnabled) { log.Debug("The duplicate request was rejected. Reject again."); } EmptyMessage rst = EmptyMessage.NewRST(request); SendEmptyMessage(nextLayer, exchange, rst); } else { if (log.IsDebugEnabled) { log.Debug("The server has not yet decided what to do with the request. We ignore the duplicate."); } // The server has not yet decided, whether to acknowledge or // reject the request. We know for sure that the server has // received the request though and can drop this duplicate here. } } else { // Lost the current request. The server has not yet decided what to do. } } else { // Request is not a duplicate exchange.CurrentRequest = request; base.ReceiveRequest(nextLayer, exchange, request); } }
/// <summary> /// Accept this exchange and therefore the request. Only if the request's /// type was a <code>CON</code> and the request has not been acknowledged /// yet, it sends an ACK to the client. /// </summary> public virtual void SendAccept() { System.Diagnostics.Debug.Assert(_origin == Origin.Remote); if (_request.Type == MessageType.CON && !_request.IsAcknowledged) { _request.IsAcknowledged = true; EmptyMessage ack = EmptyMessage.NewACK(_request); _endpoint.SendEmptyMessage(this, ack); } }