package org.webpieces.httpcommon.impl; import static org.webpieces.httpcommon.impl.Stream.StreamStatus.IDLE; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.webpieces.httpcommon.api.RequestId; import org.webpieces.httpcommon.api.ResponseId; import org.webpieces.httpcommon.api.ResponseListener; import org.webpieces.httpcommon.api.exceptions.RstStreamError; import org.webpieces.httpparser.api.dto.HttpRequest; import org.webpieces.httpparser.api.dto.HttpResponse; import com.webpieces.http2parser.api.dto.lib.Http2ErrorCode; import com.webpieces.http2parser.api.dto.lib.PriorityDetails; class Stream { private static final Logger log = LoggerFactory.getLogger(Stream.class); enum StreamStatus { IDLE, RESERVED_LOCAL, RESERVED_REMOTE, OPEN, HALF_CLOSED_LOCAL, HALF_CLOSED_REMOTE, CLOSED } private HttpRequest request; private HttpResponse response; // Only used for client private ResponseListener responseListener; private int streamId; private boolean hasContentLengthHeader = false; private long contentLengthHeaderValue; private long currentDataLength = 0; private List<String> trailerHeaders = new ArrayList<>(); private boolean trailerEnabled; int getStreamId() { return streamId; } RequestId getRequestId() { return new RequestId(streamId); } ResponseId getResponseId() { return new ResponseId(streamId); } void setStreamId(int streamId) { this.streamId = streamId; } public void setRequest(HttpRequest request) { this.request = request; } public void setResponse(HttpResponse response) { this.response = response; } void setResponseListener(ResponseListener responseListener) { this.responseListener = responseListener; } private StreamStatus status = IDLE; private PriorityDetails priorityDetails; public PriorityDetails getPriorityDetails() { return priorityDetails; } void setPriorityDetails(PriorityDetails priorityDetails) { this.priorityDetails = priorityDetails; } public boolean isStreamDependencyIsExclusive() { return priorityDetails.isStreamDependencyIsExclusive(); } public int getStreamDependency() { return priorityDetails.getStreamDependency(); } public short getWeight() { return priorityDetails.getWeight(); } StreamStatus getStatus() { return status; } void setStatus(StreamStatus status) { log.info("{}: {} -> {}", streamId, this.status, status); this.status = status; } public HttpRequest getRequest() { return request; } public HttpResponse getResponse() { return response; } ResponseListener getResponseListener() { return responseListener; } void setContentLengthHeaderValue(long contentLengthHeaderValue) { this.hasContentLengthHeader = true; this.contentLengthHeaderValue = contentLengthHeaderValue; } /* Return false if we have a problem and should throw */ void checkAgainstContentLength(int dataLength, boolean isComplete) { currentDataLength += dataLength; if ((isComplete && currentDataLength != contentLengthHeaderValue) || (currentDataLength > contentLengthHeaderValue)) throw new RstStreamError(Http2ErrorCode.PROTOCOL_ERROR, streamId); } void addTrailerHeader(String header) { trailerEnabled = true; trailerHeaders.add(header); } boolean isTrailerEnabled() { return trailerEnabled; } public List<String> getTrailerHeaders() { return trailerHeaders; } }