Skip to content

Commit

Permalink
Merge pull request #2041 from MattGill98/PAYARA-2890-HTTP2-Server-Pus…
Browse files Browse the repository at this point in the history
…h-Issues-ee4j

HTTP/2 Server Push Issues
  • Loading branch information
arjantijms authored Apr 2, 2019
2 parents d1c4b52 + c762fcd commit 2dd28ae
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 100 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Copyright (c) 2014, 2019 Oracle and/or its affiliates and others.
* All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*
* Contributors:
* Payara Services - Separated out into new class file.
*/
package org.glassfish.grizzly.http2;

import java.util.List;

import org.glassfish.grizzly.Buffer;
import org.glassfish.grizzly.CompletionHandler;
import org.glassfish.grizzly.WriteResult;
import org.glassfish.grizzly.asyncqueue.AsyncQueueRecord;
import org.glassfish.grizzly.http2.frames.DataFrame;
import org.glassfish.grizzly.http2.frames.Http2Frame;
import org.glassfish.grizzly.http2.utils.ChunkedCompletionHandler;

public class Http2OutputQueueRecord extends AsyncQueueRecord<WriteResult> {

private final int streamId;

private ChunkedCompletionHandler chunkedCompletionHandler;
private final CompletionHandler<WriteResult> originalCompletionHandler;
private Buffer buffer;
private final boolean isLast;

private final boolean isZeroSizeData;

Http2OutputQueueRecord(final int streamId, final Buffer buffer,
final CompletionHandler<WriteResult> completionHandler, final boolean isLast) {
super(null, null, null);

this.streamId = streamId;
this.buffer = buffer;
this.isZeroSizeData = !buffer.hasRemaining();
this.originalCompletionHandler = completionHandler;
this.isLast = isLast;
}

@Override
public void notifyFailure(final Throwable e) {
final CompletionHandler<WriteResult> chLocal = getCompletionHandler();
if (chLocal != null) {
chLocal.failed(e);
}
}

@Override
public void recycle() {
}

@Override
public WriteResult getCurrentResult() {
return null;
}

CompletionHandler<WriteResult> getCompletionHandler() {
return chunkedCompletionHandler != null ? chunkedCompletionHandler : originalCompletionHandler;
}

boolean isZeroSizeData() {
return isZeroSizeData;
}

boolean isFinished() {
return buffer == null;
}

int serializeTo(final List<Http2Frame> frames, final int maxDataSize) {

final int recordSize = buffer.remaining();

if (recordSize <= maxDataSize) {
final DataFrame dataFrame = DataFrame.builder().streamId(streamId).data(buffer).endStream(isLast).build();

frames.add(dataFrame);

buffer = null;

return recordSize;
} else {
if (originalCompletionHandler != null && chunkedCompletionHandler == null) {
chunkedCompletionHandler = new ChunkedCompletionHandler(originalCompletionHandler);
}

if (chunkedCompletionHandler != null) {
chunkedCompletionHandler.incChunks();
}

final Buffer remainder = buffer.split(buffer.position() + maxDataSize);

final DataFrame dataFrame = DataFrame.builder().streamId(streamId).data(buffer).endStream(false).build();

frames.add(dataFrame);

buffer = remainder;

return maxDataSize;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2015, 2017 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2019 Oracle and/or its affiliates and others.
* All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand All @@ -12,6 +13,9 @@
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*
* Contributors:
* Payara Services - Fix to PUSH_PROMISE handling.
*/

package org.glassfish.grizzly.http2;
Expand Down Expand Up @@ -1036,10 +1040,10 @@ private void doPush(final FilterChainContext ctx, final PushEvent pushEvent) {
}
}
}
pushStream.onSendPushPromise();
http2Session.getOutputSink().writeDownStream(pushPromiseFrames);

} finally {
pushStream.onSendPushPromise();
http2Session.getDeflaterLock().unlock();
}
} finally {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2014, 2017 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2019 Oracle and/or its affiliates and others.
* All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand All @@ -12,6 +13,9 @@
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*
* Contributors:
* Payara Services - Moved internal OutputQueueRecord into new class.
*/

package org.glassfish.grizzly.http2;
Expand Down Expand Up @@ -52,7 +56,7 @@ public class Http2SessionOutputSink {
private static final int MAX_OUTPUT_QUEUE_SIZE = 65536;

// async output queue
private final TaskQueue<Http2SessionOutputSink.OutputQueueRecord> outputQueue =
private final TaskQueue<Http2OutputQueueRecord> outputQueue =
TaskQueue.createTaskQueue(new TaskQueue.MutableMaxQueueSize() {

@Override
Expand Down Expand Up @@ -182,7 +186,7 @@ protected void writeDataDownStream(final Http2Stream stream,
data = messageCloner.clone(http2Session.getConnection(), data);
}

final Http2SessionOutputSink.OutputQueueRecord record = new Http2SessionOutputSink.OutputQueueRecord(
final Http2OutputQueueRecord record = new Http2OutputQueueRecord(
stream.getId(), data,
completionHandler, isLast);

Expand Down Expand Up @@ -227,7 +231,7 @@ private void flushOutputQueue() {
while (availWindowSize > bytesToTransfer &&
queueSize > queueSizeToFree) {

final Http2SessionOutputSink.OutputQueueRecord record = outputQueue.poll();
final Http2OutputQueueRecord record = outputQueue.poll();

if (record == null) {
// keep this warning for now
Expand Down Expand Up @@ -315,98 +319,4 @@ public void close() {
outputQueue.onClose();
}

private static class OutputQueueRecord extends AsyncQueueRecord<WriteResult> {
private final int streamId;

private ChunkedCompletionHandler chunkedCompletionHandler;
private final CompletionHandler<WriteResult> originalCompletionHandler;
private Buffer buffer;
private final boolean isLast;

private final boolean isZeroSizeData;

public OutputQueueRecord(final int streamId,
final Buffer buffer,
final CompletionHandler<WriteResult> completionHandler,
final boolean isLast) {
super(null, null, null);

this.streamId = streamId;
this.buffer = buffer;
this.isZeroSizeData = !buffer.hasRemaining();
this.originalCompletionHandler = completionHandler;
this.isLast = isLast;
}

public CompletionHandler<WriteResult> getCompletionHandler() {
return chunkedCompletionHandler != null ?
chunkedCompletionHandler :
originalCompletionHandler;
}

@Override
public void notifyFailure(final Throwable e) {
final CompletionHandler<WriteResult> chLocal = getCompletionHandler();
if (chLocal != null) {
chLocal.failed(e);
}
}

@Override
public void recycle() {
}

@Override
public WriteResult getCurrentResult() {
return null;
}

private boolean isZeroSizeData() {
return isZeroSizeData;
}

private boolean isFinished() {
return buffer == null;
}

private int serializeTo(final List<Http2Frame> frames,
final int maxDataSize) {

final int recordSize = buffer.remaining();

if (recordSize <= maxDataSize) {
final DataFrame dataFrame = DataFrame.builder()
.streamId(streamId)
.data(buffer).endStream(isLast)
.build();

frames.add(dataFrame);

buffer = null;

return recordSize;
} else {
if (originalCompletionHandler != null && chunkedCompletionHandler == null) {
chunkedCompletionHandler = new ChunkedCompletionHandler(originalCompletionHandler);
}

if (chunkedCompletionHandler != null) {
chunkedCompletionHandler.incChunks();
}

final Buffer remainder = buffer.split(buffer.position() + maxDataSize);

final DataFrame dataFrame = DataFrame.builder()
.streamId(streamId)
.data(buffer).endStream(false)
.build();

frames.add(dataFrame);

buffer = remainder;

return maxDataSize;
}
}
}
}

0 comments on commit 2dd28ae

Please sign in to comment.