Merge branch 'master' of ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project

This commit is contained in:
Jan Bartel 2012-12-22 15:13:49 +11:00
commit c7b6ed72e8
70 changed files with 2246 additions and 1359 deletions

View File

@ -24,7 +24,6 @@ import java.nio.channels.AsynchronousCloseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
@ -42,6 +41,7 @@ import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.util.BlockingArrayQueue;
import org.eclipse.jetty.util.FuturePromise;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
@ -72,9 +72,16 @@ public class HttpDestination implements Destination, AutoCloseable, Dumpable
this.scheme = scheme;
this.host = host;
this.address = new InetSocketAddress(host, port);
this.requests = new ArrayBlockingQueue<>(client.getMaxRequestsQueuedPerDestination());
this.idleConnections = new ArrayBlockingQueue<>(client.getMaxConnectionsPerDestination());
this.activeConnections = new ArrayBlockingQueue<>(client.getMaxConnectionsPerDestination());
int maxRequestsQueued = client.getMaxRequestsQueuedPerDestination();
int capacity = Math.min(32, maxRequestsQueued);
this.requests = new BlockingArrayQueue<>(capacity, capacity, maxRequestsQueued);
int maxConnections = client.getMaxConnectionsPerDestination();
capacity = Math.min(8, maxConnections);
this.idleConnections = new BlockingArrayQueue<>(capacity, capacity, maxConnections);
this.activeConnections = new BlockingArrayQueue<>(capacity, capacity, maxConnections);
this.requestNotifier = new RequestNotifier(client);
this.responseNotifier = new ResponseNotifier(client);

View File

@ -41,8 +41,10 @@ import org.eclipse.jetty.io.SelectorManager;
import org.eclipse.jetty.io.ssl.SslConnection;
import org.eclipse.jetty.io.ssl.SslConnection.DecryptedEndPoint;
import org.eclipse.jetty.spdy.FlowControlStrategy;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.SessionFrameListener;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.FuturePromise;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.ssl.SslContextFactory;
@ -265,7 +267,7 @@ public class SPDYClient
private void closeConnections()
{
for (Session session : sessions)
session.goAway();
session.goAway(new GoAwayInfo(), new Callback.Adapter());
sessions.clear();
}

View File

@ -29,6 +29,7 @@ import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.spdy.Controller;
import org.eclipse.jetty.spdy.ISession;
import org.eclipse.jetty.spdy.IdleListener;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.parser.Parser;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.log.Log;
@ -46,10 +47,10 @@ public class SPDYConnection extends AbstractConnection implements Controller, Id
public SPDYConnection(EndPoint endPoint, ByteBufferPool bufferPool, Parser parser, Executor executor)
{
this(endPoint,bufferPool,parser,executor,8192);
this(endPoint, bufferPool, parser, executor, 8192);
}
public SPDYConnection(EndPoint endPoint, ByteBufferPool bufferPool, Parser parser, Executor executor,int bufferSize)
public SPDYConnection(EndPoint endPoint, ByteBufferPool bufferPool, Parser parser, Executor executor, int bufferSize)
{
// Since SPDY is multiplexed, onFillable() must never block
// while calling application code. In fact, onFillable()
@ -60,7 +61,7 @@ public class SPDYConnection extends AbstractConnection implements Controller, Id
this.bufferPool = bufferPool;
this.parser = parser;
onIdle(true);
this.bufferSize=bufferSize;
this.bufferSize = bufferSize;
}
@Override
@ -165,7 +166,7 @@ public class SPDYConnection extends AbstractConnection implements Controller, Id
protected void goAway(ISession session)
{
if (session != null)
session.goAway();
session.goAway(new GoAwayInfo(), new Callback.Adapter());
}
private void shutdown(ISession session)

View File

@ -18,6 +18,7 @@
package org.eclipse.jetty.spdy;
import org.eclipse.jetty.spdy.api.PushInfo;
import org.eclipse.jetty.spdy.api.SynInfo;
/* ------------------------------------------------------------ */
@ -30,8 +31,8 @@ public class PushSynInfo extends SynInfo
private int associatedStreamId;
public PushSynInfo(int associatedStreamId, SynInfo synInfo){
super(synInfo.getHeaders(), synInfo.isClose(), synInfo.getPriority());
public PushSynInfo(int associatedStreamId, PushInfo pushInfo){
super(pushInfo.getHeaders(), pushInfo.isClose());
this.associatedStreamId = associatedStreamId;
}

View File

@ -33,9 +33,10 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@ -44,7 +45,9 @@ import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.GoAwayReceivedInfo;
import org.eclipse.jetty.spdy.api.PingInfo;
import org.eclipse.jetty.spdy.api.PingResultInfo;
import org.eclipse.jetty.spdy.api.RstInfo;
import org.eclipse.jetty.spdy.api.SPDYException;
import org.eclipse.jetty.spdy.api.Session;
@ -148,15 +151,18 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
}
@Override
public Future<Stream> syn(SynInfo synInfo, StreamFrameListener listener)
public Stream syn(SynInfo synInfo, StreamFrameListener listener) throws ExecutionException, InterruptedException, TimeoutException
{
FuturePromise<Stream> result = new FuturePromise<>();
syn(synInfo,listener,0,TimeUnit.MILLISECONDS,result);
return result;
syn(synInfo, listener, result);
if (synInfo.getTimeout() > 0)
return result.get(synInfo.getTimeout(), synInfo.getUnit());
else
return result.get();
}
@Override
public void syn(SynInfo synInfo, StreamFrameListener listener, long timeout, TimeUnit unit, Promise<Stream> promise)
public void syn(SynInfo synInfo, StreamFrameListener listener, Promise<Stream> promise)
{
// Synchronization is necessary.
// SPEC v3, 2.3.1 requires that the stream creation be monotonically crescent
@ -174,21 +180,24 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
// TODO: for SPDYv3 we need to support the "slot" argument
SynStreamFrame synStream = new SynStreamFrame(version, synInfo.getFlags(), streamId, associatedStreamId, synInfo.getPriority(), (short)0, synInfo.getHeaders());
IStream stream = createStream(synStream, listener, true, promise);
generateAndEnqueueControlFrame(stream, synStream, timeout, unit, stream);
generateAndEnqueueControlFrame(stream, synStream, synInfo.getTimeout(), synInfo.getUnit(), stream);
}
flush();
}
@Override
public Future<Void> rst(RstInfo rstInfo)
public void rst(RstInfo rstInfo) throws InterruptedException, ExecutionException, TimeoutException
{
FutureCallback result = new FutureCallback();
rst(rstInfo,0,TimeUnit.MILLISECONDS,result);
return result;
rst(rstInfo, result);
if (rstInfo.getTimeout() > 0)
result.get(rstInfo.getTimeout(), rstInfo.getUnit());
else
result.get();
}
@Override
public void rst(RstInfo rstInfo, long timeout, TimeUnit unit, Callback callback)
public void rst(RstInfo rstInfo, Callback callback)
{
// SPEC v3, 2.2.2
if (goAwaySent.get())
@ -199,8 +208,8 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
{
int streamId = rstInfo.getStreamId();
IStream stream = streams.get(streamId);
RstStreamFrame frame = new RstStreamFrame(version,streamId,rstInfo.getStreamStatus().getCode(version));
control(stream,frame,timeout,unit,callback);
RstStreamFrame frame = new RstStreamFrame(version, streamId, rstInfo.getStreamStatus().getCode(version));
control(stream, frame, rstInfo.getTimeout(), rstInfo.getUnit(), callback);
if (stream != null)
{
stream.process(frame);
@ -210,64 +219,74 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
}
@Override
public Future<Void> settings(SettingsInfo settingsInfo)
public void settings(SettingsInfo settingsInfo) throws ExecutionException, InterruptedException, TimeoutException
{
FutureCallback result = new FutureCallback();
settings(settingsInfo, 0, TimeUnit.MILLISECONDS, result);
return result;
settings(settingsInfo, result);
if (settingsInfo.getTimeout() > 0)
result.get(settingsInfo.getTimeout(), settingsInfo.getUnit());
else
result.get();
}
@Override
public void settings(SettingsInfo settingsInfo, long timeout, TimeUnit unit, Callback callback)
public void settings(SettingsInfo settingsInfo, Callback callback)
{
SettingsFrame frame = new SettingsFrame(version,settingsInfo.getFlags(),settingsInfo.getSettings());
control(null, frame, timeout, unit, callback);
SettingsFrame frame = new SettingsFrame(version, settingsInfo.getFlags(), settingsInfo.getSettings());
control(null, frame, settingsInfo.getTimeout(), settingsInfo.getUnit(), callback);
}
@Override
public Future<PingInfo> ping()
public PingResultInfo ping(PingInfo pingInfo) throws ExecutionException, InterruptedException, TimeoutException
{
FuturePromise<PingInfo> result = new FuturePromise<>();
ping(0, TimeUnit.MILLISECONDS, result);
return result;
//TODO: find a better name for PingResultInfo
FuturePromise<PingResultInfo> result = new FuturePromise<>();
ping(pingInfo, result);
if (pingInfo.getTimeout() > 0)
return result.get(pingInfo.getTimeout(), pingInfo.getUnit());
else
return result.get();
}
@Override
public void ping(long timeout, TimeUnit unit, Promise<PingInfo> promise)
public void ping(PingInfo pingInfo, Promise<PingResultInfo> promise)
{
int pingId = pingIds.getAndAdd(2);
PingInfoCallback pingInfo = new PingInfoCallback(pingId, promise);
PingInfoCallback pingInfoCallback = new PingInfoCallback(pingId, promise);
PingFrame frame = new PingFrame(version, pingId);
control(null, frame, timeout, unit, pingInfo);
control(null, frame, pingInfo.getTimeout(), pingInfo.getUnit(), pingInfoCallback);
}
@Override
public Future<Void> goAway()
public void goAway(GoAwayInfo goAwayInfo) throws ExecutionException, InterruptedException, TimeoutException
{
return goAway(SessionStatus.OK);
goAway(goAwayInfo, SessionStatus.OK);
}
private Future<Void> goAway(SessionStatus sessionStatus)
private void goAway(GoAwayInfo goAwayInfo, SessionStatus sessionStatus) throws ExecutionException, InterruptedException, TimeoutException
{
FutureCallback result = new FutureCallback();
goAway(sessionStatus, 0, TimeUnit.MILLISECONDS, result);
return result;
goAway(sessionStatus, goAwayInfo.getTimeout(), goAwayInfo.getUnit(), result);
if (goAwayInfo.getTimeout() > 0)
result.get(goAwayInfo.getTimeout(), goAwayInfo.getUnit());
else
result.get();
}
@Override
public void goAway(long timeout, TimeUnit unit, Callback callback)
public void goAway(GoAwayInfo goAwayInfo, Callback callback)
{
goAway(SessionStatus.OK, timeout, unit, callback);
goAway(SessionStatus.OK, goAwayInfo.getTimeout(), goAwayInfo.getUnit(), callback);
}
private void goAway(SessionStatus sessionStatus, long timeout, TimeUnit unit, Callback callback)
{
if (goAwaySent.compareAndSet(false,true))
if (goAwaySent.compareAndSet(false, true))
{
if (!goAwayReceived.get())
{
GoAwayFrame frame = new GoAwayFrame(version,lastStreamId.get(),sessionStatus.getCode());
control(null,frame,timeout,unit,callback);
GoAwayFrame frame = new GoAwayFrame(version, lastStreamId.get(), sessionStatus.getCode());
control(null, frame, timeout, unit, callback);
return;
}
}
@ -416,7 +435,7 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
{
RstInfo rstInfo = new RstInfo(streamId, StreamStatus.INVALID_STREAM);
LOG.debug("Unknown stream {}", rstInfo);
rst(rstInfo);
rst(rstInfo, new Callback.Adapter());
}
else
{
@ -437,7 +456,7 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
private void processData(final IStream stream, DataFrame frame, ByteBuffer data)
{
ByteBufferDataInfo dataInfo = new ByteBufferDataInfo(data, frame.isClose(), frame.isCompress())
ByteBufferDataInfo dataInfo = new ByteBufferDataInfo(data, frame.isClose())
{
@Override
public void consume(int delta)
@ -456,15 +475,15 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
public void onStreamException(StreamException x)
{
notifyOnException(listener, x);
rst(new RstInfo(x.getStreamId(),x.getStreamStatus()));
rst(new RstInfo(x.getStreamId(), x.getStreamStatus()), new Callback.Adapter());
}
@Override
public void onSessionException(SessionException x)
{
Throwable cause = x.getCause();
notifyOnException(listener,cause == null?x:cause);
goAway(x.getSessionStatus());
notifyOnException(listener, cause == null ? x : cause);
goAway(x.getSessionStatus(), 0, TimeUnit.SECONDS, new Callback.Adapter());
}
private void onSyn(SynStreamFrame frame)
@ -479,8 +498,8 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
stream.process(frame);
// Update the last stream id before calling the application (which may send a GO_AWAY)
updateLastStreamId(stream);
SynInfo synInfo = new SynInfo(frame.getHeaders(),frame.isClose(),frame.getPriority());
StreamFrameListener streamListener = notifyOnSyn(listener,stream,synInfo);
SynInfo synInfo = new SynInfo(frame.getHeaders(), frame.isClose(), frame.getPriority());
StreamFrameListener streamListener = notifyOnSyn(listener, stream, synInfo);
stream.setStreamFrameListener(streamListener);
flush();
// The onSyn() listener may have sent a frame that closed the stream
@ -512,7 +531,14 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
throw new IllegalStateException("Duplicate stream id " + streamId);
RstInfo rstInfo = new RstInfo(streamId, StreamStatus.PROTOCOL_ERROR);
LOG.debug("Duplicate stream, {}", rstInfo);
rst(rstInfo);
try
{
rst(rstInfo);
}
catch (InterruptedException | ExecutionException | TimeoutException e)
{
e.printStackTrace(); // TODO: really catch???
}
return null;
}
else
@ -589,13 +615,13 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
IStream stream = streams.get(streamId);
if (stream == null)
{
RstInfo rstInfo = new RstInfo(streamId,StreamStatus.INVALID_STREAM);
LOG.debug("Unknown stream {}",rstInfo);
rst(rstInfo);
RstInfo rstInfo = new RstInfo(streamId, StreamStatus.INVALID_STREAM);
LOG.debug("Unknown stream {}", rstInfo);
rst(rstInfo, new Callback.Adapter());
}
else
{
processReply(stream,frame);
processReply(stream, frame);
}
}
@ -613,7 +639,7 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
if (stream != null)
stream.process(frame);
RstInfo rstInfo = new RstInfo(frame.getStreamId(),StreamStatus.from(frame.getVersion(),frame.getStatusCode()));
RstInfo rstInfo = new RstInfo(frame.getStreamId(), StreamStatus.from(frame.getVersion(), frame.getStatusCode()));
notifyOnRst(listener, rstInfo);
flush();
@ -640,8 +666,8 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
int pingId = frame.getPingId();
if (pingId % 2 == pingIds.get() % 2)
{
PingInfo pingInfo = new PingInfo(frame.getPingId());
notifyOnPing(listener, pingInfo);
PingResultInfo pingResultInfo = new PingResultInfo(frame.getPingId());
notifyOnPing(listener, pingResultInfo);
flush();
}
else
@ -654,8 +680,9 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
{
if (goAwayReceived.compareAndSet(false, true))
{
GoAwayInfo goAwayInfo = new GoAwayInfo(frame.getLastStreamId(),SessionStatus.from(frame.getStatusCode()));
notifyOnGoAway(listener,goAwayInfo);
//TODO: Find a better name for GoAwayReceivedInfo
GoAwayReceivedInfo goAwayReceivedInfo = new GoAwayReceivedInfo(frame.getLastStreamId(), SessionStatus.from(frame.getStatusCode()));
notifyOnGoAway(listener, goAwayReceivedInfo);
flush();
// SPDY does not require to send back a response to a GO_AWAY.
// We notified the application of the last good stream id and
@ -669,13 +696,13 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
IStream stream = streams.get(streamId);
if (stream == null)
{
RstInfo rstInfo = new RstInfo(streamId,StreamStatus.INVALID_STREAM);
LOG.debug("Unknown stream, {}",rstInfo);
rst(rstInfo);
RstInfo rstInfo = new RstInfo(streamId, StreamStatus.INVALID_STREAM);
LOG.debug("Unknown stream, {}", rstInfo);
rst(rstInfo, new Callback.Adapter());
}
else
{
processHeaders(stream,frame);
processHeaders(stream, frame);
}
}
@ -713,7 +740,7 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
{
if (listener != null)
{
LOG.debug("Invoking callback with {} on listener {}",x,listener);
LOG.debug("Invoking callback with {} on listener {}", x, listener);
listener.onException(x);
}
}
@ -734,12 +761,12 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
{
if (listener == null)
return null;
LOG.debug("Invoking callback with {} on listener {}",synInfo,listener);
return listener.onSyn(stream,synInfo);
LOG.debug("Invoking callback with {} on listener {}", synInfo, listener);
return listener.onSyn(stream, synInfo);
}
catch (Exception x)
{
LOG.info("Exception while notifying listener " + listener,x);
LOG.info("Exception while notifying listener " + listener, x);
return null;
}
catch (Error x)
@ -755,8 +782,8 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
{
if (listener != null)
{
LOG.debug("Invoking callback with {} on listener {}",rstInfo,listener);
listener.onRst(this,rstInfo);
LOG.debug("Invoking callback with {} on listener {}", rstInfo, listener);
listener.onRst(this, rstInfo);
}
}
catch (Exception x)
@ -776,7 +803,7 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
{
if (listener != null)
{
LOG.debug("Invoking callback with {} on listener {}",settingsInfo,listener);
LOG.debug("Invoking callback with {} on listener {}", settingsInfo, listener);
listener.onSettings(this, settingsInfo);
}
}
@ -791,14 +818,14 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
}
}
private void notifyOnPing(SessionFrameListener listener, PingInfo pingInfo)
private void notifyOnPing(SessionFrameListener listener, PingResultInfo pingResultInfo)
{
try
{
if (listener != null)
{
LOG.debug("Invoking callback with {} on listener {}",pingInfo,listener);
listener.onPing(this, pingInfo);
LOG.debug("Invoking callback with {} on listener {}", pingResultInfo, listener);
listener.onPing(this, pingResultInfo);
}
}
catch (Exception x)
@ -812,14 +839,14 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
}
}
private void notifyOnGoAway(SessionFrameListener listener, GoAwayInfo goAwayInfo)
private void notifyOnGoAway(SessionFrameListener listener, GoAwayReceivedInfo goAwayReceivedInfo)
{
try
{
if (listener != null)
{
LOG.debug("Invoking callback with {} on listener {}",goAwayInfo,listener);
listener.onGoAway(this, goAwayInfo);
LOG.debug("Invoking callback with {} on listener {}", goAwayReceivedInfo, listener);
listener.onGoAway(this, goAwayReceivedInfo);
}
}
catch (Exception x)
@ -879,10 +906,10 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
@Override
public void data(IStream stream, DataInfo dataInfo, long timeout, TimeUnit unit, Callback callback)
{
LOG.debug("Queuing {} on {}",dataInfo,stream);
DataFrameBytes frameBytes = new DataFrameBytes(stream,callback,dataInfo);
LOG.debug("Queuing {} on {}", dataInfo, stream);
DataFrameBytes frameBytes = new DataFrameBytes(stream, callback, dataInfo);
if (timeout > 0)
frameBytes.task = scheduler.schedule(frameBytes,timeout,unit);
frameBytes.task = scheduler.schedule(frameBytes, timeout, unit);
append(frameBytes);
flush();
}
@ -909,7 +936,7 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
{
if (flushing || queue.isEmpty())
return;
Set<IStream> stalledStreams = null;
for (int i = 0; i < queue.size(); ++i)
{
@ -937,14 +964,14 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
if (stream != null)
stalledStreams.add(stream);
LOG.debug("Flush stalled for {}, {} frame(s) in queue",frameBytes,queue.size());
LOG.debug("Flush stalled for {}, {} frame(s) in queue", frameBytes, queue.size());
}
if (buffer == null)
return;
flushing = true;
LOG.debug("Flushing {}, {} frame(s) in queue",frameBytes,queue.size());
LOG.debug("Flushing {}, {} frame(s) in queue", frameBytes, queue.size());
}
write(buffer, frameBytes);
}
@ -996,7 +1023,7 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
break;
++index;
}
queue.add(index,frameBytes);
queue.add(index, frameBytes);
}
}
@ -1008,8 +1035,8 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
{
if (controller != null)
{
LOG.debug("Writing {} frame bytes of {}",buffer.remaining());
controller.write(buffer,callback);
LOG.debug("Writing {} frame bytes of {}", buffer.remaining(), buffer.limit());
controller.write(buffer, callback);
}
}
@ -1053,7 +1080,8 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
@Override
public String toString()
{
return String.format("%s@%x{v%d,queuSize=%d,windowSize=%d,streams=%d}", getClass().getSimpleName(), hashCode(), version, queue.size(), getWindowSize(), streams.size());
return String.format("%s@%x{v%d,queueSize=%d,windowSize=%d,streams=%d}", getClass().getSimpleName(),
hashCode(), version, queue.size(), getWindowSize(), streams.size());
}
@Override
@ -1065,8 +1093,8 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
@Override
public void dump(Appendable out, String indent) throws IOException
{
ContainerLifeCycle.dumpObject(out,this);
ContainerLifeCycle.dump(out,indent,Collections.singletonList(controller),streams.values());
ContainerLifeCycle.dumpObject(out, this);
ContainerLifeCycle.dump(out, indent, Collections.singletonList(controller), streams.values());
}
private class SessionInvoker extends ForkInvoker<Callback>
@ -1177,7 +1205,7 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
synchronized (queue)
{
if (LOG.isDebugEnabled())
LOG.debug("Completed write of {}, {} frame(s) in queue",this,queue.size());
LOG.debug("Completed write of {}, {} frame(s) in queue", this, queue.size());
flushing = false;
}
complete();
@ -1194,8 +1222,8 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
failure = x;
if (LOG.isDebugEnabled())
{
String logMessage = String.format("Failed write of %s, failing all %d frame(s) in queue",this,queue.size());
LOG.debug(logMessage,x);
String logMessage = String.format("Failed write of %s, failing all %d frame(s) in queue", this, queue.size());
LOG.debug(logMessage, x);
}
frameBytesToFail.addAll(queue);
queue.clear();
@ -1214,7 +1242,7 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
private ControlFrameBytes(IStream stream, Callback callback, ControlFrame frame, ByteBuffer buffer)
{
super(stream,callback);
super(stream, callback);
this.frame = frame;
this.buffer = buffer;
}
@ -1276,7 +1304,7 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
if (size > windowSize)
size = windowSize;
buffer = generator.data(stream.getId(),size,dataInfo);
buffer = generator.data(stream.getId(), size, dataInfo);
return buffer;
}
catch (Throwable x)
@ -1303,7 +1331,7 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
else
{
super.complete();
stream.updateCloseState(dataInfo.isClose(),true);
stream.updateCloseState(dataInfo.isClose(), true);
if (stream.isClosed())
removeStream(stream);
}
@ -1337,14 +1365,14 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable
}
}
private static class PingInfoCallback extends PingInfo implements Callback
private static class PingInfoCallback extends PingResultInfo implements Callback
{
private final Promise<PingInfo> promise;
private final Promise<PingResultInfo> promise;
public PingInfoCallback(int pingId, Promise<PingInfo> promise)
public PingInfoCallback(int pingId, Promise<PingResultInfo> promise)
{
super(pingId);
this.promise=promise;
this.promise = promise;
}
@Override

View File

@ -22,18 +22,18 @@ import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.HeadersInfo;
import org.eclipse.jetty.spdy.api.PushInfo;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.RstInfo;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamFrameListener;
import org.eclipse.jetty.spdy.api.StreamStatus;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.frames.ControlFrame;
import org.eclipse.jetty.spdy.frames.HeadersFrame;
import org.eclipse.jetty.spdy.frames.SynReplyFrame;
@ -133,7 +133,7 @@ public class StandardStream implements IStream
@Override
public void setAttribute(String key, Object value)
{
attributes.put(key,value);
attributes.put(key, value);
}
@Override
@ -156,7 +156,7 @@ public class StandardStream implements IStream
@Override
public void updateCloseState(boolean close, boolean local)
{
LOG.debug("{} close={} local={}",this,close,local);
LOG.debug("{} close={} local={}", this, close, local);
if (close)
{
switch (closeState)
@ -184,7 +184,7 @@ public class StandardStream implements IStream
}
default:
{
LOG.warn("Already CLOSED! {} local={}",this,local);
LOG.warn("Already CLOSED! {} local={}", this, local);
}
}
}
@ -243,8 +243,8 @@ public class StandardStream implements IStream
if (!canReceive())
{
LOG.debug("Protocol error receiving {}, resetting" + dataInfo);
session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR));
LOG.debug("Protocol error receiving {}, resetting", dataInfo);
session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR), new Adapter());
return;
}
@ -335,15 +335,18 @@ public class StandardStream implements IStream
}
@Override
public Future<Stream> syn(SynInfo synInfo)
public Stream push(PushInfo pushInfo) throws InterruptedException, ExecutionException, TimeoutException
{
FuturePromise<Stream> result = new FuturePromise<>();
syn(synInfo,0,TimeUnit.MILLISECONDS,result);
return result;
push(pushInfo, result);
if (pushInfo.getTimeout() > 0)
return result.get(pushInfo.getTimeout(), pushInfo.getUnit());
else
return result.get();
}
@Override
public void syn(SynInfo synInfo, long timeout, TimeUnit unit, Promise<Stream> promise)
public void push(PushInfo pushInfo, Promise<Stream> promise)
{
if (isClosed() || isReset())
{
@ -351,81 +354,90 @@ public class StandardStream implements IStream
"Stream: " + this + " already closed or reset!"));
return;
}
PushSynInfo pushSynInfo = new PushSynInfo(getId(), synInfo);
session.syn(pushSynInfo, null, timeout, unit, promise);
PushSynInfo pushSynInfo = new PushSynInfo(getId(), pushInfo);
session.syn(pushSynInfo, null, promise);
}
@Override
public Future<Void> reply(ReplyInfo replyInfo)
public void reply(ReplyInfo replyInfo) throws InterruptedException, ExecutionException, TimeoutException
{
FutureCallback result = new FutureCallback();
reply(replyInfo, 0, TimeUnit.MILLISECONDS, result);
return result;
reply(replyInfo, result);
if (replyInfo.getTimeout() > 0)
result.get(replyInfo.getTimeout(), replyInfo.getUnit());
else
result.get();
}
@Override
public void reply(ReplyInfo replyInfo, long timeout, TimeUnit unit, Callback callback)
public void reply(ReplyInfo replyInfo, Callback callback)
{
if (isUnidirectional())
throw new IllegalStateException("Protocol violation: cannot send SYN_REPLY frames in unidirectional streams");
openState = OpenState.REPLY_SENT;
updateCloseState(replyInfo.isClose(), true);
SynReplyFrame frame = new SynReplyFrame(session.getVersion(), replyInfo.getFlags(), getId(), replyInfo.getHeaders());
session.control(this, frame, timeout, unit, callback);
session.control(this, frame, replyInfo.getTimeout(), replyInfo.getUnit(), callback);
}
@Override
public Future<Void> data(DataInfo dataInfo)
public void data(DataInfo dataInfo) throws InterruptedException, ExecutionException, TimeoutException
{
FutureCallback result = new FutureCallback();
data(dataInfo, 0, TimeUnit.MILLISECONDS, result);
return result;
data(dataInfo, result);
if (dataInfo.getTimeout() > 0)
result.get(dataInfo.getTimeout(), dataInfo.getUnit());
else
result.get();
}
@Override
public void data(DataInfo dataInfo, long timeout, TimeUnit unit, Callback callback)
public void data(DataInfo dataInfo, Callback callback)
{
if (!canSend())
{
session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR));
session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR), new Adapter());
throw new IllegalStateException("Protocol violation: cannot send a DATA frame before a SYN_REPLY frame");
}
if (isLocallyClosed())
{
session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR));
session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR), new Adapter());
throw new IllegalStateException("Protocol violation: cannot send a DATA frame on a closed stream");
}
// Cannot update the close state here, because the data that we send may
// be flow controlled, so we need the stream to update the window size.
session.data(this, dataInfo, timeout, unit, callback);
session.data(this, dataInfo, dataInfo.getTimeout(), dataInfo.getUnit(), callback);
}
@Override
public Future<Void> headers(HeadersInfo headersInfo)
public void headers(HeadersInfo headersInfo) throws InterruptedException, ExecutionException, TimeoutException
{
FutureCallback result = new FutureCallback();
headers(headersInfo, 0, TimeUnit.MILLISECONDS, result);
return result;
headers(headersInfo, result);
if (headersInfo.getTimeout() > 0)
result.get(headersInfo.getTimeout(), headersInfo.getUnit());
else
result.get();
}
@Override
public void headers(HeadersInfo headersInfo, long timeout, TimeUnit unit, Callback callback)
public void headers(HeadersInfo headersInfo, Callback callback)
{
if (!canSend())
{
session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR));
session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR), new Adapter());
throw new IllegalStateException("Protocol violation: cannot send a HEADERS frame before a SYN_REPLY frame");
}
if (isLocallyClosed())
{
session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR));
session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR), new Adapter());
throw new IllegalStateException("Protocol violation: cannot send a HEADERS frame on a closed stream");
}
updateCloseState(headersInfo.isClose(), true);
HeadersFrame frame = new HeadersFrame(session.getVersion(), headersInfo.getFlags(), getId(), headersInfo.getHeaders());
session.control(this, frame, timeout, unit, callback);
session.control(this, frame, headersInfo.getTimeout(), headersInfo.getUnit(), callback);
}
@Override

View File

@ -19,6 +19,7 @@
package org.eclipse.jetty.spdy.api;
import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;
/**
* <p>Specialized {@link DataInfo} for {@link ByteBuffer} content.</p>
@ -30,12 +31,12 @@ public class ByteBufferDataInfo extends DataInfo
public ByteBufferDataInfo(ByteBuffer buffer, boolean close)
{
this(buffer, close, false);
this(0, TimeUnit.SECONDS, buffer, close);
}
public ByteBufferDataInfo(ByteBuffer buffer, boolean close, boolean compress)
public ByteBufferDataInfo(long timeout, TimeUnit unit, ByteBuffer buffer, boolean close)
{
super(close, compress);
super(timeout, unit, close);
this.buffer = buffer;
this.length = buffer.remaining();
}

View File

@ -19,6 +19,7 @@
package org.eclipse.jetty.spdy.api;
import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;
/**
* <p>Specialized {@link DataInfo} for byte array content.</p>
@ -32,12 +33,17 @@ public class BytesDataInfo extends DataInfo
public BytesDataInfo(byte[] bytes, boolean close)
{
this(bytes, 0, bytes.length, close);
this(0, TimeUnit.SECONDS, bytes, close);
}
public BytesDataInfo(byte[] bytes, int offset, int length, boolean close)
public BytesDataInfo(long timeout, TimeUnit unit, byte[] bytes, boolean close)
{
super(close, false);
this(timeout, unit, bytes, 0, bytes.length, close);
}
public BytesDataInfo(long timeout, TimeUnit unit, byte[] bytes, int offset, int length, boolean close)
{
super(timeout, unit, close);
this.bytes = bytes;
this.offset = offset;
this.length = length;

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.spdy.api;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
@ -41,7 +42,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* <p>Consuming the data bytes can be done only via {@link #consumeInto(ByteBuffer)} or by a combination
* of {@link #readInto(ByteBuffer)} and {@link #consume(int)} (possibly at different times).</p>
*/
public abstract class DataInfo
public abstract class DataInfo extends Info
{
/**
* <p>Flag that indicates that this {@link DataInfo} is the last frame in the stream.</p>
@ -50,17 +51,9 @@ public abstract class DataInfo
* @see #getFlags()
*/
public final static byte FLAG_CLOSE = 1;
/**
* <p>Flag that indicates that this {@link DataInfo}'s data is compressed.</p>
*
* @see #isCompress()
* @see #getFlags()
*/
public final static byte FLAG_COMPRESS = 2;
private final AtomicInteger consumed = new AtomicInteger();
private boolean close;
private boolean compress;
/**
* <p>Creates a new {@link DataInfo} with the given close flag and no compression flag.</p>
@ -73,33 +66,16 @@ public abstract class DataInfo
}
/**
* <p>Creates a new {@link DataInfo} with the given close flag and given compression flag.</p>
* <p>Creates a new {@link DataInfo} with the given close flag and no compression flag.</p>
*
* @param close the close flag
* @param compress the compress flag
* @param timeout
* @param unit
* @param close the value of the close flag
*/
public DataInfo(boolean close, boolean compress)
protected DataInfo(long timeout, TimeUnit unit, boolean close)
{
setClose(close);
setCompress(compress);
}
/**
* @return the value of the compress flag
* @see #setCompress(boolean)
*/
public boolean isCompress()
{
return compress;
}
/**
* @param compress the value of the compress flag
* @see #isCompress()
*/
public void setCompress(boolean compress)
{
this.compress = compress;
super(timeout, unit);
this.close = close;
}
/**
@ -123,13 +99,10 @@ public abstract class DataInfo
/**
* @return the close and compress flags as integer
* @see #FLAG_CLOSE
* @see #FLAG_COMPRESS
*/
public byte getFlags()
{
byte flags = isClose() ? FLAG_CLOSE : 0;
flags |= isCompress() ? FLAG_COMPRESS : 0;
return flags;
return isClose() ? FLAG_CLOSE : 0;
}
/**
@ -275,6 +248,6 @@ public abstract class DataInfo
@Override
public String toString()
{
return String.format("DATA @%x available=%d consumed=%d close=%b compress=%b", hashCode(), available(), consumed(), isClose(), isCompress());
return String.format("DATA @%x available=%d consumed=%d close=%b", hashCode(), available(), consumed(), isClose());
}
}

View File

@ -18,40 +18,21 @@
package org.eclipse.jetty.spdy.api;
import java.util.concurrent.TimeUnit;
/**
* <p>A container for GOAWAY frames metadata: the last good stream id and
* the session status.</p>
* A GoAwayInfo container. Currently adding nothing to it's base class, but serves to keep the api unchanged in
* future versions when we need to pass more info to the methods having a {@link GoAwayInfo} parameter.
*/
public class GoAwayInfo
public class GoAwayInfo extends Info
{
private final int lastStreamId;
private final SessionStatus sessionStatus;
/**
* <p>Creates a new {@link GoAwayInfo} with the given last good stream id and session status</p>
*
* @param lastStreamId the last good stream id
* @param sessionStatus the session status
*/
public GoAwayInfo(int lastStreamId, SessionStatus sessionStatus)
public GoAwayInfo(long timeout, TimeUnit unit)
{
this.lastStreamId = lastStreamId;
this.sessionStatus = sessionStatus;
super(timeout, unit);
}
/**
* @return the last good stream id
*/
public int getLastStreamId()
public GoAwayInfo()
{
return lastStreamId;
}
/**
* @return the session status
*/
public SessionStatus getSessionStatus()
{
return sessionStatus;
super();
}
}

View File

@ -0,0 +1,57 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.spdy.api;
/**
* <p>A container for GOAWAY frames metadata: the last good stream id and
* the session status.</p>
*/
public class GoAwayReceivedInfo
{
private final int lastStreamId;
private final SessionStatus sessionStatus;
/**
* <p>Creates a new {@link GoAwayReceivedInfo} with the given last good stream id and session status</p>
*
* @param lastStreamId the last good stream id
* @param sessionStatus the session status
*/
public GoAwayReceivedInfo(int lastStreamId, SessionStatus sessionStatus)
{
this.lastStreamId = lastStreamId;
this.sessionStatus = sessionStatus;
}
/**
* @return the last good stream id
*/
public int getLastStreamId()
{
return lastStreamId;
}
/**
* @return the session status
*/
public SessionStatus getSessionStatus()
{
return sessionStatus;
}
}

View File

@ -18,12 +18,14 @@
package org.eclipse.jetty.spdy.api;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.util.Fields;
/**
* <p>A container for HEADERS frame metadata and headers.</p>
*/
public class HeadersInfo
public class HeadersInfo extends Info
{
/**
* <p>Flag that indicates that this {@link HeadersInfo} is the last frame in the stream.</p>
@ -45,11 +47,11 @@ public class HeadersInfo
private final Fields headers;
/**
* <p>Creates a new {@link HeadersInfo} instance with the given headers,
* the given close flag and no reset compression flag</p>
* <p>Creates a new {@link HeadersInfo} instance with the given headers, the given close flag and no reset
* compression flag</p>
*
* @param headers the {@link Fields}
* @param close the value of the close flag
* @param close the value of the close flag
*/
public HeadersInfo(Fields headers, boolean close)
{
@ -57,11 +59,11 @@ public class HeadersInfo
}
/**
* <p>Creates a new {@link HeadersInfo} instance with the given headers,
* the given close flag and the given reset compression flag</p>
* <p>Creates a new {@link HeadersInfo} instance with the given headers, the given close flag and the given reset
* compression flag</p>
*
* @param headers the {@link Fields}
* @param close the value of the close flag
* @param headers the {@link Fields}
* @param close the value of the close flag
* @param resetCompression the value of the reset compression flag
*/
public HeadersInfo(Fields headers, boolean close, boolean resetCompression)
@ -71,6 +73,24 @@ public class HeadersInfo
this.resetCompression = resetCompression;
}
/**
* <p>Creates a new {@link HeadersInfo} instance with the given headers, the given close flag and the given reset
* compression flag</p>
*
* @param timeout the operation's timeout
* @param unit the timeout's unit
* @param headers the {@link Fields}
* @param close the value of the close flag
* @param resetCompression the value of the reset compression flag
*/
public HeadersInfo(long timeout, TimeUnit unit, boolean close, boolean resetCompression, Fields headers)
{
super(timeout, unit);
this.close = close;
this.resetCompression = resetCompression;
this.headers = headers;
}
/**
* @return the value of the close flag
*/

View File

@ -0,0 +1,52 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.spdy.api;
import java.util.concurrent.TimeUnit;
/**
* A base class for all *Info classes providing timeout and unit and api to access them
*/
public class Info
{
private final long timeout;
private final TimeUnit unit;
public Info(long timeout, TimeUnit unit)
{
this.timeout = timeout;
this.unit = unit;
}
public Info()
{
timeout = 0;
unit = TimeUnit.SECONDS;
}
public long getTimeout()
{
return timeout;
}
public TimeUnit getUnit()
{
return unit;
}
}

View File

@ -18,27 +18,21 @@
package org.eclipse.jetty.spdy.api;
/**
* <p>A container for PING frames data.</p>
*/
public class PingInfo
{
private final int pingId;
import java.util.concurrent.TimeUnit;
/**
* <p>Creates a {@link PingInfo} with the given ping id</p>
* @param pingId the ping id
*/
public PingInfo(int pingId)
/**
* A PingInfo container. Currently adding nothing to it's base class, but serves to keep the api unchanged in
* future versions when we need to pass more info to the methods having a {@link PingInfo} parameter.
*/
public class PingInfo extends Info
{
public PingInfo(long timeout, TimeUnit unit)
{
this.pingId = pingId;
super(timeout, unit);
}
/**
* @return the ping id
*/
public int getPingId()
public PingInfo()
{
return pingId;
this(0, TimeUnit.SECONDS);
}
}

View File

@ -0,0 +1,44 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.spdy.api;
/**
* <p>A container for PING frames data.</p>
*/
public class PingResultInfo
{
private final int pingId;
/**
* <p>Creates a {@link PingResultInfo} with the given ping id</p>
* @param pingId the ping id
*/
public PingResultInfo(int pingId)
{
this.pingId = pingId;
}
/**
* @return the ping id
*/
public int getPingId()
{
return pingId;
}
}

View File

@ -0,0 +1,101 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.spdy.api;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.util.Fields;
/**
* <p>A container for PUSH_SYN_STREAM frames metadata and data.</p>
*/
public class PushInfo extends Info
{
/**
* <p>Flag that indicates that this {@link PushInfo} is the last frame in the stream.</p>
*
* @see #isClose()
* @see #getFlags()
*/
public static final byte FLAG_CLOSE = 1;
private final boolean close;
private final Fields headers;
/**
* <p>Creates a {@link PushInfo} instance with the given headers and the given close flag,
* not unidirectional, without associated stream, and with default priority.</p>
*
* @param headers the {@link Fields}
* @param close the value of the close flag
*/
public PushInfo(Fields headers, boolean close)
{
this(0, TimeUnit.SECONDS, headers, close);
// either builder or setters for timeout
}
/**
* <p>
* Creates a {@link PushInfo} instance with the given headers, the given close flag and with the given priority.
* </p>
* @param timeout the timeout value
* @param unit the TimeUnit of the timeout
* @param headers
* the {@link Fields}
* @param close
*/
public PushInfo(long timeout, TimeUnit unit, Fields headers, boolean close)
{
super(timeout, unit);
this.close = close;
this.headers = headers;
}
/**
* @return the value of the close flag
*/
public boolean isClose()
{
return close;
}
/**
* @return the {@link Fields}
*/
public Fields getHeaders()
{
return headers;
}
/**
* @return the close flag as integer
* @see #FLAG_CLOSE
*/
public byte getFlags()
{
return isClose() ? FLAG_CLOSE : 0;
}
@Override
public String toString()
{
return String.format("SYN push close=%b headers=%s", close, headers);
}
}

View File

@ -18,12 +18,14 @@
package org.eclipse.jetty.spdy.api;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.util.Fields;
/**
* <p>A container for SYN_REPLY frames metadata and headers.</p>
*/
public class ReplyInfo
public class ReplyInfo extends Info
{
/**
* <p>Flag that indicates that this {@link ReplyInfo} is the last frame in the stream.</p>
@ -50,10 +52,24 @@ public class ReplyInfo
* <p>Creates a {@link ReplyInfo} instance with the given headers and the given close flag.</p>
*
* @param headers the {@link Fields}
* @param close the value of the close flag
* @param close the value of the close flag
*/
public ReplyInfo(Fields headers, boolean close)
{
this(0, TimeUnit.SECONDS, headers, close);
}
/**
* <p>Creates a {@link ReplyInfo} instance with the given headers and the given close flag.</p>
*
* @param timeout the timeout
* @param unit the time unit for the timeout
* @param headers the {@link Fields}
* @param close the value of the close flag
*/
public ReplyInfo(long timeout, TimeUnit unit, Fields headers, boolean close)
{
super(timeout, unit);
this.headers = headers;
this.close = close;
}

View File

@ -18,10 +18,12 @@
package org.eclipse.jetty.spdy.api;
import java.util.concurrent.TimeUnit;
/**
* <p>A container for RST_STREAM frames data: the stream id and the stream status.</p>
*/
public class RstInfo
public class RstInfo extends Info
{
private final int streamId;
private final StreamStatus streamStatus;
@ -29,13 +31,27 @@ public class RstInfo
/**
* <p>Creates a new {@link RstInfo} with the given stream id and stream status</p>
*
* @param streamId the stream id
* @param timeout the operation's timeout
* @param unit the timeout's unit
* @param streamId the stream id
* @param streamStatus the stream status
*/
public RstInfo(long timeout, TimeUnit unit, int streamId, StreamStatus streamStatus)
{
super(timeout, unit);
this.streamId = streamId;
this.streamStatus = streamStatus;
}
/**
* <p>Creates a new {@link RstInfo} with the given stream id and stream status</p>
*
* @param streamId
* @param streamStatus
*/
public RstInfo(int streamId, StreamStatus streamStatus)
{
this.streamId = streamId;
this.streamStatus = streamStatus;
this(0, TimeUnit.SECONDS, streamId, streamStatus);
}
/**

View File

@ -21,8 +21,8 @@ package org.eclipse.jetty.spdy.api;
import java.net.InetSocketAddress;
import java.util.EventListener;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Promise;
@ -33,7 +33,7 @@ import org.eclipse.jetty.util.Promise;
* <pre>
* Session session = ...;
* SynInfo synInfo = new SynInfo(true);
* session.syn(synInfo, new Stream.FrameListener.Adapter()
* session.push(synInfo, new Stream.FrameListener.Adapter()
* {
* public void onReply(Stream stream, ReplyInfo replyInfo)
* {
@ -75,115 +75,118 @@ public interface Session
* <p>Callers may use the returned future to wait for the stream to be created, and
* use the stream, for example, to send data frames.</p>
*
*
* @param synInfo the metadata to send on stream creation
* @param listener the listener to invoke when events happen on the stream just created
* @return a future for the stream that will be created
* @see #syn(SynInfo, StreamFrameListener, long, TimeUnit, Promise)
* @return the stream that will be created
* @see #syn(SynInfo, StreamFrameListener, Promise
*/
public Future<Stream> syn(SynInfo synInfo, StreamFrameListener listener);
public Stream syn(SynInfo synInfo, StreamFrameListener listener) throws ExecutionException, InterruptedException, TimeoutException;
/**
* <p>Sends asynchronously a SYN_FRAME to create a new {@link Stream SPDY stream}.</p>
* <p>Callers may pass a non-null completion callback to be notified of when the
* stream has been created and use the stream, for example, to send data frames.</p>
*
*
* @param synInfo the metadata to send on stream creation
* @param listener the listener to invoke when events happen on the stream just created
* @param timeout the operation's timeout
* @param unit the timeout's unit
* @param promise the completion callback that gets notified of stream creation
* @see #syn(SynInfo, StreamFrameListener)
*/
public void syn(SynInfo synInfo, StreamFrameListener listener, long timeout, TimeUnit unit, Promise<Stream> promise);
public void syn(SynInfo synInfo, StreamFrameListener listener, Promise<Stream> promise);
/**
* <p>Sends asynchronously a RST_STREAM to abort a stream.</p>
* <p>Callers may use the returned future to wait for the reset to be sent.</p>
*
*
* @param rstInfo the metadata to reset the stream
* @return a future to wait for the reset to be sent
* @see #rst(RstInfo, long, TimeUnit, Callback)
* @return the RstInfo belonging to the reset to be sent
* @see #rst(RstInfo, Callback)
*/
public Future<Void> rst(RstInfo rstInfo);
public void rst(RstInfo rstInfo) throws InterruptedException, ExecutionException, TimeoutException;
/**
* <p>Sends asynchronously a RST_STREAM to abort a stream.</p>
* <p>Callers may pass a non-null completion callback to be notified of when the
* reset has been actually sent.</p>
*
*
* @param rstInfo the metadata to reset the stream
* @param timeout the operation's timeout
* @param unit the timeout's unit
* @param callback the completion callback that gets notified of reset's send
* @see #rst(RstInfo)
*/
public void rst(RstInfo rstInfo, long timeout, TimeUnit unit, Callback callback);
public void rst(RstInfo rstInfo, Callback callback);
/**
* <p>Sends asynchronously a SETTINGS to configure the SPDY connection.</p>
* <p>Callers may use the returned future to wait for the settings to be sent.</p>
*
*
* @param settingsInfo the metadata to send
* @return a future to wait for the settings to be sent
* @see #settings(SettingsInfo, long, TimeUnit, Callback)
* @see #settings(SettingsInfo, Callback)
*/
public Future<Void> settings(SettingsInfo settingsInfo);
public void settings(SettingsInfo settingsInfo) throws ExecutionException, InterruptedException, TimeoutException;
/**
* <p>Sends asynchronously a SETTINGS to configure the SPDY connection.</p>
* <p>Callers may pass a non-null completion callback to be notified of when the
* settings has been actually sent.</p>
*
*
* @param settingsInfo the metadata to send
* @param timeout the operation's timeout
* @param unit the timeout's unit
* @param callback the completion callback that gets notified of settings' send
* @see #settings(SettingsInfo)
*/
public void settings(SettingsInfo settingsInfo, long timeout, TimeUnit unit, Callback callback);
public void settings(SettingsInfo settingsInfo, Callback callback);
/**
* <p>Sends asynchronously a PING, normally to measure round-trip time.</p>
* <p>Callers may use the returned future to wait for the ping to be sent.</p>
*
* @return a future for the metadata sent
* @see #ping(long, TimeUnit, Promise)
* @see #ping(PingInfo, Promise
* @param pingInfo
*/
public Future<PingInfo> ping();
public PingResultInfo ping(PingInfo pingInfo) throws ExecutionException, InterruptedException, TimeoutException;
/**
* <p>Sends asynchronously a PING, normally to measure round-trip time.</p>
* <p>Callers may pass a non-null completion callback to be notified of when the
* ping has been actually sent.</p>
*
* @param timeout the operation's timeout
* @param unit the timeout's unit
*
*
* @param pingInfo
* @param promise the completion callback that gets notified of ping's send
* @see #ping()
* @see #ping(PingInfo)
*/
public void ping(long timeout, TimeUnit unit, Promise<PingInfo> promise);
public void ping(PingInfo pingInfo, Promise<PingResultInfo> promise);
/**
* <p>Closes gracefully this session, sending a GO_AWAY frame and then closing the TCP connection.</p>
* <p>Callers may use the returned future to wait for the go away to be sent.</p>
*
* @return a future to wait for the go away to be sent
* @see #goAway(long, TimeUnit, Callback)
* @see #goAway(GoAwayInfo, Callback)
* @param goAwayInfo
*/
public Future<Void> goAway();
public void goAway(GoAwayInfo goAwayInfo) throws ExecutionException, InterruptedException, TimeoutException;
/**
* <p>Closes gracefully this session, sending a GO_AWAY frame and then closing the TCP connection.</p>
* <p>Callers may pass a non-null completion callback to be notified of when the
* go away has been actually sent.</p>
*
* @param timeout the operation's timeout
* @param unit the timeout's unit
*
*
* @param goAwayInfo
* @param callback the completion callback that gets notified of go away's send
* @see #goAway()
* @see #goAway(GoAwayInfo)
*/
public void goAway(long timeout, TimeUnit unit, Callback callback);
public void goAway(GoAwayInfo goAwayInfo, Callback callback);
/**
* @return a snapshot of the streams currently active in this session

View File

@ -98,17 +98,17 @@ public interface SessionFrameListener extends EventListener
* <p>Callback invoked when a ping request has completed its round-trip.</p>
*
* @param session the session
* @param pingInfo the metadata received
* @param pingResultInfo the metadata received
*/
public void onPing(Session session, PingInfo pingInfo);
public void onPing(Session session, PingResultInfo pingResultInfo);
/**
* <p>Callback invoked when the other peer signals that it is closing the connection.</p>
*
* @param session the session
* @param goAwayInfo the metadata sent
* @param goAwayReceivedInfo the metadata sent
*/
public void onGoAway(Session session, GoAwayInfo goAwayInfo);
public void onGoAway(Session session, GoAwayReceivedInfo goAwayReceivedInfo);
/**
* <p>Callback invoked when an exception is thrown during the processing of an event on a
@ -143,12 +143,12 @@ public interface SessionFrameListener extends EventListener
}
@Override
public void onPing(Session session, PingInfo pingInfo)
public void onPing(Session session, PingResultInfo pingResultInfo)
{
}
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
public void onGoAway(Session session, GoAwayReceivedInfo goAwayReceivedInfo)
{
}

View File

@ -18,7 +18,9 @@
package org.eclipse.jetty.spdy.api;
public class SettingsInfo
import java.util.concurrent.TimeUnit;
public class SettingsInfo extends Info
{
public static final byte CLEAR_PERSISTED = 1;
@ -27,13 +29,19 @@ public class SettingsInfo
public SettingsInfo(Settings settings)
{
this(settings, false);
this(0, TimeUnit.SECONDS, settings, false);
}
public SettingsInfo(long timeout, TimeUnit unit, Settings settings, boolean clearPersisted)
{
super(timeout, unit);
this.settings = settings;
this.clearPersisted = clearPersisted;
}
public SettingsInfo(Settings settings, boolean clearPersisted)
{
this.settings = settings;
this.clearPersisted = clearPersisted;
this(0, TimeUnit.SECONDS, settings, clearPersisted);
}
public boolean isClearPersisted()

View File

@ -20,8 +20,8 @@ package org.eclipse.jetty.spdy.api;
import java.nio.channels.WritePendingException;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Promise;
@ -50,7 +50,7 @@ import org.eclipse.jetty.util.Promise;
* stream.data(StringDataInfo("chunk1", false), 5, TimeUnit.SECONDS, new Handler&lt;Void&gt;() { ... });
* stream.data(StringDataInfo("chunk2", true), 1, TimeUnit.SECONDS, new Handler&lt;Void&gt;() { ... });
* </pre>
* <p>where the second call to {@link #data(DataInfo, long, TimeUnit, Callback)} has a timeout smaller
* <p>where the second call to {@link #data(DataInfo, Callback)} has a timeout smaller
* than the previous call.</p>
* <p>The behavior of such style of invocations is unspecified (it may even throw an exception - similar
* to {@link WritePendingException}).</p>
@ -95,35 +95,37 @@ public interface Stream
* <p>Initiate a unidirectional spdy pushstream associated to this stream asynchronously<p>
* <p>Callers may use the returned future to get the pushstream once it got created</p>
*
* @param synInfo the metadata to send on stream creation
*
*
* @param pushInfo the metadata to send on stream creation
* @return a future containing the stream once it got established
* @see #syn(SynInfo, long, TimeUnit, Promise)
* @see #push(PushInfo, Promise
*/
public Future<Stream> syn(SynInfo synInfo);
public Stream push(PushInfo pushInfo) throws InterruptedException, ExecutionException, TimeoutException;
/**
* <p>Initiate a unidirectional spdy pushstream associated to this stream asynchronously<p>
* <p>Callers may pass a non-null completion callback to be notified of when the
* pushstream has been established.</p>
*
* @param synInfo the metadata to send on stream creation
* @param timeout the operation's timeout
* @param unit the timeout's unit
*
* @param pushInfo the metadata to send on stream creation
* @param callback the completion callback that gets notified once the pushstream is established
* @see #syn(SynInfo)
* @see #push(PushInfo)
*/
public void syn(SynInfo synInfo, long timeout, TimeUnit unit, Promise<Stream> callback);
public void push(PushInfo pushInfo, Promise<Stream> callback);
/**
* <p>Sends asynchronously a SYN_REPLY frame in response to a SYN_STREAM frame.</p>
* <p>Callers may use the returned future to wait for the reply to be actually sent.</p>
*
*
* @param replyInfo the metadata to send
* @return a future to wait for the reply to be sent
* @see #reply(ReplyInfo, long, TimeUnit, Callback)
* @see #reply(ReplyInfo, Callback)
* @see SessionFrameListener#onSyn(Stream, SynInfo)
*/
public Future<Void> reply(ReplyInfo replyInfo);
public void reply(ReplyInfo replyInfo) throws InterruptedException, ExecutionException, TimeoutException;
/**
* <p>Sends asynchronously a SYN_REPLY frame in response to a SYN_STREAM frame.</p>
@ -131,24 +133,23 @@ public interface Stream
* reply has been actually sent.</p>
*
* @param replyInfo the metadata to send
* @param timeout the operation's timeout
* @param unit the timeout's unit
* @param callback the completion callback that gets notified of reply sent
* @see #reply(ReplyInfo)
*/
public void reply(ReplyInfo replyInfo, long timeout, TimeUnit unit, Callback callback);
public void reply(ReplyInfo replyInfo, Callback callback);
/**
* <p>Sends asynchronously a DATA frame on this stream.</p>
* <p>DATA frames should always be sent after a SYN_REPLY frame.</p>
* <p>Callers may use the returned future to wait for the data to be actually sent.</p>
*
*
* @param dataInfo the metadata to send
* @return a future to wait for the data to be sent
* @see #data(DataInfo, long, TimeUnit, Callback)
* @see #data(DataInfo, Callback)
* @see #reply(ReplyInfo)
*/
public Future<Void> data(DataInfo dataInfo);
public void data(DataInfo dataInfo) throws InterruptedException, ExecutionException, TimeoutException;
/**
* <p>Sends asynchronously a DATA frame on this stream.</p>
@ -157,24 +158,23 @@ public interface Stream
* data has been actually sent.</p>
*
* @param dataInfo the metadata to send
* @param timeout the operation's timeout
* @param unit the timeout's unit
* @param callback the completion callback that gets notified of data sent
* @see #data(DataInfo)
*/
public void data(DataInfo dataInfo, long timeout, TimeUnit unit, Callback callback);
public void data(DataInfo dataInfo, Callback callback);
/**
* <p>Sends asynchronously a HEADER frame on this stream.</p>
* <p>HEADERS frames should always be sent after a SYN_REPLY frame.</p>
* <p>Callers may use the returned future to wait for the headers to be actually sent.</p>
*
*
* @param headersInfo the metadata to send
* @return a future to wait for the headers to be sent
* @see #headers(HeadersInfo, long, TimeUnit, Callback
* @see #headers(HeadersInfo, Callback
* @see #reply(ReplyInfo)
*/
public Future<Void> headers(HeadersInfo headersInfo);
public void headers(HeadersInfo headersInfo) throws InterruptedException, ExecutionException, TimeoutException;
/**
* <p>Sends asynchronously a HEADER frame on this stream.</p>
@ -183,12 +183,10 @@ public interface Stream
* headers have been actually sent.</p>
*
* @param headersInfo the metadata to send
* @param timeout the operation's timeout
* @param unit the timeout's unit
* @param callback the completion callback that gets notified of headers sent
* @see #headers(HeadersInfo)
*/
public void headers(HeadersInfo headersInfo, long timeout, TimeUnit unit, Callback callback);
public void headers(HeadersInfo headersInfo, Callback callback);
/**
* @return whether this stream is unidirectional or not

View File

@ -19,6 +19,7 @@
package org.eclipse.jetty.spdy.api;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;
/**
* <p>Specialized {@link DataInfo} for {@link String} content.</p>
@ -29,4 +30,9 @@ public class StringDataInfo extends BytesDataInfo
{
super(string.getBytes(Charset.forName("UTF-8")), close);
}
public StringDataInfo(long timeout, TimeUnit unit, String string, boolean close)
{
super(timeout, unit, string.getBytes(Charset.forName("UTF-8")), close);
}
}

View File

@ -18,15 +18,17 @@
package org.eclipse.jetty.spdy.api;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.util.Fields;
/**
* <p>A container for SYN_STREAM frames metadata and data.</p>
*/
public class SynInfo
public class SynInfo extends Info
{
/**
* <p>Flag that indicates that this {@link DataInfo} is the last frame in the stream.</p>
* <p>Flag that indicates that this {@link SynInfo} is the last frame in the stream.</p>
*
* @see #isClose()
* @see #getFlags()
@ -38,18 +40,7 @@ public class SynInfo
private final Fields headers;
/**
* <p>Creates a new {@link SynInfo} instance with empty headers and the given close flag,
* not unidirectional, without associated stream, and with default priority.</p>
*
* @param close the value of the close flag
*/
public SynInfo(boolean close)
{
this(new Fields(), close);
}
/**
* <p>Creates a {@link ReplyInfo} instance with the given headers and the given close flag,
* <p>Creates a {@link SynInfo} instance with the given headers and the given close flag,
* not unidirectional, without associated stream, and with default priority.</p>
*
* @param headers the {@link Fields}
@ -57,23 +48,40 @@ public class SynInfo
*/
public SynInfo(Fields headers, boolean close)
{
this(headers, close, (byte)0);
this(0, TimeUnit.SECONDS, headers, close, (byte)0);
// either builder or setters for timeout
}
/**
* <p>
* Creates a {@link ReplyInfo} instance with the given headers, the given close flag and with the given priority.
* Creates a {@link SynInfo} instance with the given headers, the given close flag and with the given priority.
* </p>
*
* @param headers
* the {@link Fields}
* @param close
* the value of the close flag
* @param priority
* the priority
*/
public SynInfo(Fields headers, boolean close, byte priority)
{
this(0, TimeUnit.SECONDS, headers, close, priority);
}
/**
* <p>
* Creates a {@link SynInfo} instance with the given headers, the given close flag and with the given priority.
* </p>
* @param timeout the timeout value
* @param unit the TimeUnit of the timeout
* @param headers
* the {@link Fields}
* @param close
* the value of the close flag
* @param priority
*/
public SynInfo(long timeout, TimeUnit unit, Fields headers, boolean close, byte priority)
{
super(timeout, unit);
this.close = close;
this.priority = priority;
this.headers = headers;

View File

@ -55,14 +55,9 @@ public class DataFrame
return (flags & DataInfo.FLAG_CLOSE) == DataInfo.FLAG_CLOSE;
}
public boolean isCompress()
{
return (flags & DataInfo.FLAG_COMPRESS) == DataInfo.FLAG_COMPRESS;
}
@Override
public String toString()
{
return String.format("DATA frame stream=%d length=%d close=%b compress=%b", getStreamId(), getLength(), isClose(), isCompress());
return String.format("DATA frame stream=%d length=%d close=%b", getStreamId(), getLength(), isClose());
}
}

View File

@ -36,6 +36,7 @@ import org.eclipse.jetty.spdy.generator.Generator;
import org.eclipse.jetty.toolchain.test.AdvancedRunner;
import org.eclipse.jetty.toolchain.test.annotation.Slow;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.thread.Scheduler;
import org.eclipse.jetty.util.thread.TimerScheduler;
@ -77,7 +78,7 @@ public class AsyncTimeoutTest
};
final CountDownLatch failedLatch = new CountDownLatch(1);
session.syn(new SynInfo(true), null, timeout, unit, new Promise.Adapter<Stream>()
session.syn(new SynInfo(timeout, unit, new Fields(), true, (byte)0), null, new Promise.Adapter<Stream>()
{
@Override
public void failed(Throwable x)
@ -121,9 +122,9 @@ public class AsyncTimeoutTest
}
};
Stream stream = session.syn(new SynInfo(false), null).get(5, TimeUnit.SECONDS);
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), false, (byte)0), null);
final CountDownLatch failedLatch = new CountDownLatch(1);
stream.data(new StringDataInfo("data", true), timeout, unit, new Callback.Adapter()
stream.data(new StringDataInfo(timeout, unit, "data", true), new Callback.Adapter()
{
@Override
public void failed(Throwable x)

View File

@ -34,6 +34,7 @@ import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.HeadersInfo;
import org.eclipse.jetty.spdy.api.PushInfo;
import org.eclipse.jetty.spdy.api.RstInfo;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Session;
@ -48,6 +49,7 @@ import org.eclipse.jetty.spdy.frames.SynStreamFrame;
import org.eclipse.jetty.spdy.generator.Generator;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.FuturePromise;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -76,6 +78,7 @@ import static org.mockito.Mockito.verify;
public class StandardSessionTest
{
private static final Logger LOG = Log.getLogger(StandardSessionTest.class);
private static final short VERSION = SPDY.V2;
@Mock
private Controller controller;
@ -92,7 +95,7 @@ public class StandardSessionTest
threadPool = Executors.newCachedThreadPool();
scheduler = new TimerScheduler();
scheduler.start();
session = new StandardSession(SPDY.V2, bufferPool, threadPool, scheduler, controller, null, null, 1, null,
session = new StandardSession(VERSION, bufferPool, threadPool, scheduler, controller, null, null, 1, null,
generator, new FlowControlStrategy.None());
headers = new Fields();
}
@ -144,7 +147,7 @@ public class StandardSessionTest
IStream stream = createStream();
assertThatStreamIsInSession(stream);
stream.updateCloseState(true, true);
session.onControlFrame(new SynReplyFrame(SPDY.V2, SynInfo.FLAG_CLOSE, stream.getId(), null));
session.onControlFrame(new SynReplyFrame(VERSION, SynInfo.FLAG_CLOSE, stream.getId(), null));
assertThatStreamIsClosed(stream);
assertThatStreamIsNotInSession(stream);
}
@ -202,7 +205,7 @@ public class StandardSessionTest
assertThatPushStreamIsHalfClosed(pushStream);
assertThatPushStreamIsNotClosed(pushStream);
session.onControlFrame(new SynReplyFrame(SPDY.V2, SynInfo.FLAG_CLOSE, stream.getId(), null));
session.onControlFrame(new SynReplyFrame(VERSION, SynInfo.FLAG_CLOSE, stream.getId(), null));
assertThatStreamIsClosed(stream);
assertThatPushStreamIsNotClosed(pushStream);
}
@ -223,8 +226,8 @@ public class StandardSessionTest
private void createPushStreamAndMakeSureItFails(IStream stream) throws InterruptedException
{
final CountDownLatch failedLatch = new CountDownLatch(1);
SynInfo synInfo = new SynInfo(headers, false, stream.getPriority());
stream.syn(synInfo, 5, TimeUnit.SECONDS, new Promise.Adapter<Stream>()
PushInfo pushInfo = new PushInfo(5, TimeUnit.SECONDS, headers, false);
stream.push(pushInfo, new Promise.Adapter<Stream>()
{
@Override
public void failed(Throwable x)
@ -257,7 +260,7 @@ public class StandardSessionTest
setControllerWriteExpectation(false);
IStream stream = createStream();
IStream pushStream = (IStream)stream.syn(new SynInfo(false)).get();
IStream pushStream = (IStream)stream.push(new PushInfo(new Fields(), false));
assertThatPushStreamIsInSession(pushStream);
session.rst(new RstInfo(pushStream.getId(), StreamStatus.INVALID_STREAM));
assertThatPushStreamIsNotInSession(pushStream);
@ -271,8 +274,8 @@ public class StandardSessionTest
setControllerWriteExpectation(false);
IStream stream = createStream();
SynInfo synInfo = new SynInfo(headers, true, stream.getPriority());
IStream pushStream = (IStream)stream.syn(synInfo).get(5, TimeUnit.SECONDS);
PushInfo pushInfo = new PushInfo(5, TimeUnit.SECONDS, headers, true);
IStream pushStream = (IStream)stream.push(pushInfo);
assertThatPushStreamIsHalfClosed(pushStream);
assertThatPushStreamIsClosed(pushStream);
assertThatStreamIsNotAssociatedWithPushStream(stream, pushStream);
@ -286,8 +289,8 @@ public class StandardSessionTest
setControllerWriteExpectation(false);
IStream stream = createStream();
SynInfo synInfo = new SynInfo(headers, false, stream.getPriority());
IStream pushStream = (IStream)stream.syn(synInfo).get(5, TimeUnit.SECONDS);
PushInfo pushInfo = new PushInfo(5, TimeUnit.SECONDS, headers, false);
IStream pushStream = (IStream)stream.push(pushInfo);
assertThatStreamIsAssociatedWithPushStream(stream, pushStream);
assertThatPushStreamIsInSession(pushStream);
pushStream.headers(new HeadersInfo(headers, true));
@ -306,6 +309,7 @@ public class StandardSessionTest
final CountDownLatch closedListenerCalledLatch = new CountDownLatch(1);
session.addListener(new TestStreamListener(createdListenerCalledLatch, closedListenerCalledLatch));
IStream stream = createStream();
session.onControlFrame(new SynReplyFrame(VERSION, (byte)0, stream.getId(), new Fields()));
session.onDataFrame(new DataFrame(stream.getId(), SynInfo.FLAG_CLOSE, 128), ByteBuffer.allocate(128));
stream.data(new StringDataInfo("close", true));
assertThat("onStreamCreated listener has been called", createdListenerCalledLatch.await(5, TimeUnit.SECONDS), is(true));
@ -383,11 +387,11 @@ public class StandardSessionTest
@Test
@Ignore("In V3 we need to rst the stream if we receive data on a remotely half closed stream.")
public void receiveDataOnRemotelyHalfClosedStreamResetsStreamInV3() throws InterruptedException, ExecutionException
public void receiveDataOnRemotelyHalfClosedStreamResetsStreamInV3() throws InterruptedException, ExecutionException, TimeoutException
{
setControllerWriteExpectation(false);
IStream stream = (IStream)session.syn(new SynInfo(false), new StreamFrameListener.Adapter()).get();
IStream stream = (IStream)session.syn(new SynInfo(new Fields(), false), new StreamFrameListener.Adapter());
stream.updateCloseState(true, false);
assertThat("stream is half closed from remote side", stream.isHalfClosed(), is(true));
stream.process(new ByteBufferDataInfo(ByteBuffer.allocate(256), true));
@ -399,16 +403,17 @@ public class StandardSessionTest
setControllerWriteExpectation(false);
final CountDownLatch onDataCalledLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(false), new StreamFrameListener.Adapter()
{
@Override
public void onData(Stream stream, DataInfo dataInfo)
{
onDataCalledLatch.countDown();
super.onData(stream, dataInfo);
}
}).get(5, TimeUnit.SECONDS);
session.onControlFrame(new SynReplyFrame(SPDY.V2, SynInfo.FLAG_CLOSE, stream.getId(), headers));
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), false, (byte)0),
new StreamFrameListener.Adapter()
{
@Override
public void onData(Stream stream, DataInfo dataInfo)
{
onDataCalledLatch.countDown();
super.onData(stream, dataInfo);
}
});
session.onControlFrame(new SynReplyFrame(VERSION, SynInfo.FLAG_CLOSE, stream.getId(), headers));
session.onDataFrame(new DataFrame(stream.getId(), (byte)0, 0), ByteBuffer.allocate(128));
assertThat("onData is never called", onDataCalledLatch.await(1, TimeUnit.SECONDS), not(true));
}
@ -420,7 +425,7 @@ public class StandardSessionTest
setControllerWriteExpectation(true);
final CountDownLatch failedCalledLatch = new CountDownLatch(2);
SynStreamFrame synStreamFrame = new SynStreamFrame(SPDY.V2, SynInfo.FLAG_CLOSE, 1, 0, (byte)0, (short)0, null);
SynStreamFrame synStreamFrame = new SynStreamFrame(VERSION, SynInfo.FLAG_CLOSE, 1, 0, (byte)0, (short)0, null);
IStream stream = new StandardStream(synStreamFrame.getStreamId(), synStreamFrame.getPriority(), session, null, null);
stream.updateWindowSize(8192);
Callback.Adapter callback = new Callback.Adapter()
@ -433,9 +438,9 @@ public class StandardSessionTest
};
// first data frame should fail on controller.write()
stream.data(new StringDataInfo("data", false), 5, TimeUnit.SECONDS, callback);
stream.data(new StringDataInfo(5, TimeUnit.SECONDS, "data", false), callback);
// second data frame should fail without controller.write() as the connection is expected to be broken after first controller.write() call failed.
stream.data(new StringDataInfo("data", false), 5, TimeUnit.SECONDS, callback);
stream.data(new StringDataInfo(5, TimeUnit.SECONDS, "data", false), callback);
verify(controller, times(1)).write(any(ByteBuffer.class), any(Callback.class));
assertThat("Callback.failed has been called twice", failedCalledLatch.await(5, TimeUnit.SECONDS), is(true));
@ -449,7 +454,7 @@ public class StandardSessionTest
// This is necessary to keep the compression context of Headers valid
IStream stream = createStream();
session.rst(new RstInfo(stream.getId(), StreamStatus.INVALID_STREAM));
stream.headers(new HeadersInfo(headers,true));
stream.headers(new HeadersInfo(headers, true));
verify(controller, times(3)).write(any(ByteBuffer.class), any(Callback.class));
@ -471,7 +476,7 @@ public class StandardSessionTest
private void testHeaderFramesAreSentInOrder(final byte priority0, final byte priority1, final byte priority2) throws InterruptedException, ExecutionException
{
final StandardSession testLocalSession = new StandardSession(SPDY.V2, bufferPool, threadPool, scheduler,
final StandardSession testLocalSession = new StandardSession(VERSION, bufferPool, threadPool, scheduler,
new ControllerMock(), null, null, 1, null, generator, new FlowControlStrategy.None());
HashSet<Future> tasks = new HashSet<>();
@ -492,7 +497,7 @@ public class StandardSessionTest
private void synStream(byte priority)
{
SynInfo synInfo = new SynInfo(headers, false, priority);
testLocalSession.syn(synInfo, new StreamFrameListener.Adapter());
testLocalSession.syn(synInfo, new StreamFrameListener.Adapter(), new FuturePromise<Stream>());
}
}));
}
@ -533,14 +538,14 @@ public class StandardSessionTest
private IStream createStream() throws InterruptedException, ExecutionException, TimeoutException
{
SynInfo synInfo = new SynInfo(headers, false, (byte)0);
return (IStream)session.syn(synInfo, new StreamFrameListener.Adapter()).get(5, TimeUnit.SECONDS);
SynInfo synInfo = new SynInfo(5, TimeUnit.SECONDS, headers, false, (byte)0);
return (IStream)session.syn(synInfo, new StreamFrameListener.Adapter());
}
private IStream createPushStream(Stream stream) throws InterruptedException, ExecutionException, TimeoutException
{
SynInfo synInfo = new SynInfo(headers, false, stream.getPriority());
return (IStream)stream.syn(synInfo).get(5, TimeUnit.SECONDS);
PushInfo pushInfo = new PushInfo(5, TimeUnit.SECONDS, headers, false);
return (IStream)stream.push(pushInfo);
}
private void assertThatStreamIsClosed(IStream stream)

View File

@ -26,6 +26,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.PushInfo;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamFrameListener;
@ -33,6 +34,7 @@ import org.eclipse.jetty.spdy.api.StringDataInfo;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.frames.SynStreamFrame;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.Promise;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -45,7 +47,6 @@ import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@ -60,7 +61,7 @@ public class StandardStreamTest
private SynStreamFrame synStreamFrame;
/**
* Test method for {@link org.eclipse.jetty.spdy.StandardStream#syn(org.eclipse.jetty.spdy.api.SynInfo)}.
* Test method for {@link Stream#push(org.eclipse.jetty.spdy.api.PushInfo)}.
*/
@SuppressWarnings("unchecked")
@Test
@ -70,30 +71,29 @@ public class StandardStreamTest
Set<Stream> streams = new HashSet<>();
streams.add(stream);
when(synStreamFrame.isClose()).thenReturn(false);
SynInfo synInfo = new SynInfo(false);
PushInfo pushInfo = new PushInfo(new Fields(), false);
when(session.getStreams()).thenReturn(streams);
stream.syn(synInfo);
verify(session).syn(argThat(new PushSynInfoMatcher(stream.getId(), synInfo)), any(StreamFrameListener.class), anyLong(), any(TimeUnit.class), any(Promise.class));
stream.push(pushInfo, new Promise.Adapter<Stream>());
verify(session).syn(argThat(new PushSynInfoMatcher(stream.getId(), pushInfo)),
any(StreamFrameListener.class), any(Promise.class));
}
private class PushSynInfoMatcher extends ArgumentMatcher<PushSynInfo>
{
int associatedStreamId;
SynInfo synInfo;
private int associatedStreamId;
private PushInfo pushInfo;
public PushSynInfoMatcher(int associatedStreamId, SynInfo synInfo)
public PushSynInfoMatcher(int associatedStreamId, PushInfo pushInfo)
{
this.associatedStreamId = associatedStreamId;
this.synInfo = synInfo;
this.pushInfo = pushInfo;
}
@Override
public boolean matches(Object argument)
{
PushSynInfo pushSynInfo = (PushSynInfo)argument;
if (pushSynInfo.getAssociatedStreamId() != associatedStreamId)
return false;
return pushSynInfo.isClose() == synInfo.isClose();
return pushSynInfo.getAssociatedStreamId() == associatedStreamId && pushSynInfo.isClose() == pushInfo.isClose();
}
}
@ -105,7 +105,7 @@ public class StandardStreamTest
stream.updateCloseState(true, false);
assertThat("stream expected to be closed", stream.isClosed(), is(true));
final CountDownLatch failedLatch = new CountDownLatch(1);
stream.syn(new SynInfo(false), 1, TimeUnit.SECONDS, new Promise.Adapter<Stream>()
stream.push(new PushInfo(1, TimeUnit.SECONDS, new Fields(), false), new Promise.Adapter<Stream>()
{
@Override
public void failed(Throwable x)

View File

@ -19,9 +19,12 @@
package org.eclipse.jetty.spdy.api;
import java.nio.charset.Charset;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.eclipse.jetty.spdy.StandardSession;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.Promise;
import org.junit.Ignore;
@ -35,7 +38,7 @@ public class ClientUsageTest
{
Session session = new StandardSession(SPDY.V2, null, null, null, null, null, null, 1, null, null, null);
session.syn(new SynInfo(true), new StreamFrameListener.Adapter()
session.syn(new SynInfo(new Fields(), true), new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
@ -44,7 +47,14 @@ public class ClientUsageTest
replyInfo.getHeaders().get("host");
// Then issue another similar request
stream.getSession().syn(new SynInfo(true), this);
try
{
stream.getSession().syn(new SynInfo(new Fields(), true), this);
}
catch (ExecutionException | InterruptedException | TimeoutException e)
{
throw new IllegalStateException(e);
}
}
});
}
@ -54,18 +64,26 @@ public class ClientUsageTest
{
Session session = new StandardSession(SPDY.V2, null, null, null, null, null, null, 1, null, null, null);
Stream stream = session.syn(new SynInfo(false), new StreamFrameListener.Adapter()
{
@Override
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), false, (byte)0),
new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
{
// Do something with the response
replyInfo.getHeaders().get("host");
// Then issue another similar request
stream.getSession().syn(new SynInfo(true), this);
try
{
stream.getSession().syn(new SynInfo(new Fields(), true), this);
}
catch (ExecutionException | InterruptedException | TimeoutException e)
{
throw new IllegalStateException(e);
}
}
}).get(5, TimeUnit.SECONDS);
});
// Send-and-forget the data
stream.data(new StringDataInfo("data", true));
}
@ -76,8 +94,8 @@ public class ClientUsageTest
Session session = new StandardSession(SPDY.V2, null, null, null, null, null, null, 1, null, null, null);
final String context = "context";
session.syn(new SynInfo(false), new StreamFrameListener.Adapter()
{
session.syn(new SynInfo(new Fields(), false), new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
{
@ -85,11 +103,18 @@ public class ClientUsageTest
replyInfo.getHeaders().get("host");
// Then issue another similar request
stream.getSession().syn(new SynInfo(true), this);
try
{
stream.getSession().syn(new SynInfo(new Fields(), true), this);
}
catch (ExecutionException | InterruptedException | TimeoutException e)
{
throw new IllegalStateException(e);
}
}
}, 0, TimeUnit.MILLISECONDS, new Promise.Adapter<Stream>()
{
@Override
}, new Promise.Adapter<Stream>()
{
@Override
public void succeeded(Stream stream)
{
// Differently from JDK 7 AIO, there is no need to
@ -100,7 +125,7 @@ public class ClientUsageTest
// The style below is fire-and-forget, since
// we do not pass the handler nor we call get()
// to wait for the data to be sent
stream.data(new StringDataInfo(context, true));
stream.data(new StringDataInfo(context, true), new Callback.Adapter());
}
});
}
@ -110,9 +135,9 @@ public class ClientUsageTest
{
Session session = new StandardSession(SPDY.V2, null, null, null, null, null, null, 1, null, null, null);
session.syn(new SynInfo(false), new StreamFrameListener.Adapter()
{
// The good of passing the listener to syn() is that applications can safely
session.syn(new SynInfo(new Fields(), false), new StreamFrameListener.Adapter()
{
// The good of passing the listener to push() is that applications can safely
// accumulate info from the reply headers to be used in the data callback,
// e.g. content-type, charset, etc.
@ -127,7 +152,14 @@ public class ClientUsageTest
stream.setAttribute("builder", new StringBuilder());
// May issue another similar request while waiting for data
stream.getSession().syn(new SynInfo(true), this);
try
{
stream.getSession().syn(new SynInfo(new Fields(), true), this);
}
catch (ExecutionException | InterruptedException | TimeoutException e)
{
throw new IllegalStateException(e);
}
}
@Override
@ -138,18 +170,18 @@ public class ClientUsageTest
if (dataInfo.isClose())
{
int receivedLength = builder.toString().getBytes(Charset.forName("UTF-8")).length;
assert receivedLength == (Integer)stream.getAttribute("content-length");
assert receivedLength == stream.getAttribute("content-length");
}
}
}, 0, TimeUnit.MILLISECONDS, new Promise.Adapter<Stream>()
{
@Override
}, new Promise.Adapter<Stream>()
{
@Override
public void succeeded(Stream stream)
{
stream.data(new BytesDataInfo("wee".getBytes(Charset.forName("UTF-8")), false));
stream.data(new StringDataInfo("foo", false));
stream.data(new ByteBufferDataInfo(Charset.forName("UTF-8").encode("bar"), true));
stream.data(new BytesDataInfo("wee".getBytes(Charset.forName("UTF-8")), false), new Callback.Adapter());
stream.data(new StringDataInfo("foo", false), new Callback.Adapter());
stream.data(new ByteBufferDataInfo(Charset.forName("UTF-8").encode("bar"), true), new Callback.Adapter());
}
});
}

View File

@ -18,8 +18,6 @@
package org.eclipse.jetty.spdy.api;
import java.util.concurrent.TimeUnit;
import junit.framework.Assert;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
@ -48,11 +46,11 @@ public class ServerUsageTest
Fields replyHeaders = new Fields();
replyHeaders.put(synHeaders.get("host"));
// Sends a reply
stream.reply(new ReplyInfo(replyHeaders, false));
stream.reply(new ReplyInfo(replyHeaders, false), new Callback.Adapter());
// Sends data
StringDataInfo dataInfo = new StringDataInfo("foo", false);
stream.data(dataInfo);
stream.data(dataInfo, new Callback.Adapter());
// Stream is now closed
return null;
}
@ -77,7 +75,7 @@ public class ServerUsageTest
//
// However, the API may allow to initiate the stream
session.syn(new SynInfo(false), null, 0, TimeUnit.MILLISECONDS, new Promise.Adapter<Stream>()
session.syn(new SynInfo(new Fields(), false), null, new Promise.Adapter<Stream>()
{
@Override
public void succeeded(Stream stream)
@ -87,7 +85,7 @@ public class ServerUsageTest
// the client sends a rst frame.
// We have to atomically set some flag on the stream to signal it's closed
// and any operation on it will throw
stream.headers(new HeadersInfo(new Fields(), true));
stream.headers(new HeadersInfo(new Fields(), true), new Callback.Adapter());
}
});
}
@ -104,16 +102,16 @@ public class ServerUsageTest
public StreamFrameListener onSyn(Stream stream, SynInfo streamInfo)
{
// Need to send the reply first
stream.reply(new ReplyInfo(false));
stream.reply(new ReplyInfo(false), new Callback.Adapter());
Session session = stream.getSession();
// Since it's unidirectional, no need to pass the listener
session.syn(new SynInfo(new Fields(), false, (byte)0), null, 0, TimeUnit.MILLISECONDS, new Promise.Adapter<Stream>()
session.syn(new SynInfo(new Fields(), false, (byte)0), null, new Promise.Adapter<Stream>()
{
@Override
public void succeeded(Stream pushStream)
{
pushStream.data(new StringDataInfo("foo", false));
pushStream.data(new StringDataInfo("foo", false), new Callback.Adapter());
}
});
return null;

View File

@ -134,7 +134,7 @@ public class HttpChannelOverSPDY extends HttpChannel<DataInfo>
// will be consumed. When the copy is consumed, we consume also the
// original, so the implementation can send a window update.
ByteBuffer copyByteBuffer = dataInfo.asByteBuffer(false);
ByteBufferDataInfo copyDataInfo = new ByteBufferDataInfo(copyByteBuffer, dataInfo.isClose(), dataInfo.isCompress())
ByteBufferDataInfo copyDataInfo = new ByteBufferDataInfo(copyByteBuffer, dataInfo.isClose())
{
@Override
public void consume(int delta)

View File

@ -37,11 +37,11 @@ import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpTransport;
import org.eclipse.jetty.spdy.StreamException;
import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
import org.eclipse.jetty.spdy.api.PushInfo;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamStatus;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.util.BlockingCallback;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
@ -68,7 +68,7 @@ public class HttpTransportOverSPDY implements HttpTransport
this.connector = connector;
this.configuration = configuration;
this.endPoint = endPoint;
this.pushStrategy = pushStrategy==null?new PushStrategy.None():pushStrategy;
this.pushStrategy = pushStrategy == null ? new PushStrategy.None() : pushStrategy;
this.stream = stream;
this.requestHeaders = requestHeaders;
}
@ -77,7 +77,7 @@ public class HttpTransportOverSPDY implements HttpTransport
public void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent, Callback callback)
{
if (LOG.isDebugEnabled())
LOG.debug("send {} {} {} {} last={}",this,stream,info,BufferUtil.toDetailString(content),lastContent);
LOG.debug("send {} {} {} {} last={}", this, stream, info, BufferUtil.toDetailString(content), lastContent);
if (stream.isClosed() || stream.isReset())
{
@ -98,9 +98,10 @@ public class HttpTransportOverSPDY implements HttpTransport
boolean hasContent = BufferUtil.hasContent(content);
if (info!=null)
if (info != null)
{
if(!committed.compareAndSet(false, true)){
if (!committed.compareAndSet(false, true))
{
StreamException exception = new StreamException(stream.getId(), StreamStatus.PROTOCOL_ERROR,
"Stream already committed!");
callback.failed(exception);
@ -138,7 +139,7 @@ public class HttpTransportOverSPDY implements HttpTransport
}
boolean close = !hasContent && lastContent;
ReplyInfo reply = new ReplyInfo(headers,close);
ReplyInfo reply = new ReplyInfo(headers, close);
reply(stream, reply);
}
@ -146,23 +147,25 @@ public class HttpTransportOverSPDY implements HttpTransport
if (hasContent)
{
// Is the stream still open?
if (stream.isClosed()|| stream.isReset())
if (stream.isClosed() || stream.isReset())
// tell the callback about the EOF
callback.failed(new EofException("stream closed"));
else
callback.failed(new EofException("stream closed"));
else
// send the data and let it call the callback
stream.data(new ByteBufferDataInfo(content, lastContent),endPoint.getIdleTimeout(),TimeUnit.MILLISECONDS,callback);
stream.data(new ByteBufferDataInfo(endPoint.getIdleTimeout(), TimeUnit.MILLISECONDS, content, lastContent
), callback);
}
// else do we need to close
else if (lastContent)
{
// Are we closed ?
if (stream.isClosed()|| stream.isReset())
if (stream.isClosed() || stream.isReset())
// already closed by reply, so just tell callback we are complete
callback.succeeded();
callback.succeeded();
else
// send empty data to close and let the send call the callback
stream.data(new ByteBufferDataInfo(BufferUtil.EMPTY_BUFFER, lastContent),endPoint.getIdleTimeout(),TimeUnit.MILLISECONDS,callback);
stream.data(new ByteBufferDataInfo(endPoint.getIdleTimeout(), TimeUnit.MILLISECONDS,
BufferUtil.EMPTY_BUFFER, lastContent), callback);
}
else
// No data and no close so tell callback we are completed
@ -173,7 +176,7 @@ public class HttpTransportOverSPDY implements HttpTransport
@Override
public void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent) throws EofException
{
send(info,content,lastContent,streamBlocker);
send(info, content, lastContent, streamBlocker);
try
{
streamBlocker.block();
@ -194,7 +197,7 @@ public class HttpTransportOverSPDY implements HttpTransport
private void reply(Stream stream, ReplyInfo replyInfo)
{
if (!stream.isUnidirectional())
stream.reply(replyInfo);
stream.reply(replyInfo, new Callback.Adapter());
Fields responseHeaders = replyInfo.getHeaders();
short version = stream.getSession().getVersion();
@ -212,7 +215,7 @@ public class HttpTransportOverSPDY implements HttpTransport
final Fields pushRequestHeaders = createRequestHeaders(scheme, host, uri, pushResource);
// TODO: handle the timeout better
stream.syn(new SynInfo(pushHeaders, false), 0, TimeUnit.MILLISECONDS, new Promise.Adapter<Stream>()
stream.push(new PushInfo(0, TimeUnit.MILLISECONDS, pushHeaders, false), new Promise.Adapter<Stream>()
{
@Override
public void succeeded(Stream pushStream)

View File

@ -23,8 +23,8 @@ import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.PingInfo;
import org.eclipse.jetty.spdy.api.GoAwayReceivedInfo;
import org.eclipse.jetty.spdy.api.PingResultInfo;
import org.eclipse.jetty.spdy.api.RstInfo;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.Stream;
@ -33,14 +33,15 @@ import org.eclipse.jetty.spdy.api.StreamStatus;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.eclipse.jetty.spdy.server.http.HTTPSPDYHeader;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* <p>{@link ProxyEngineSelector} is the main entry point for syn stream events of a jetty SPDY proxy. It receives the
* syn stream frames from the clients, checks if there's an appropriate {@link ProxyServerInfo} for the given target
* host and forwards the syn to a {@link ProxyEngine} for the protocol defined in {@link ProxyServerInfo}.</p>
* <p>{@link ProxyEngineSelector} is the main entry point for push stream events of a jetty SPDY proxy. It receives the
* push stream frames from the clients, checks if there's an appropriate {@link ProxyServerInfo} for the given target
* host and forwards the push to a {@link ProxyEngine} for the protocol defined in {@link ProxyServerInfo}.</p>
*
* <p>If no {@link ProxyServerInfo} can be found for the given target host or no {@link ProxyEngine} can be found for
* the given protocol, it resets the client stream.</p>
@ -96,14 +97,14 @@ public class ProxyEngineSelector extends ServerSessionFrameListener.Adapter
}
@Override
public void onPing(Session clientSession, PingInfo pingInfo)
public void onPing(Session clientSession, PingResultInfo pingResultInfo)
{
// We do not know to which upstream server
// to send the PING so we just ignore it
}
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
public void onGoAway(Session session, GoAwayReceivedInfo goAwayReceivedInfo)
{
// TODO:
}
@ -153,7 +154,7 @@ public class ProxyEngineSelector extends ServerSessionFrameListener.Adapter
private void rst(Stream stream)
{
RstInfo rstInfo = new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM);
stream.getSession().rst(rstInfo);
stream.getSession().rst(rstInfo, new Callback.Adapter());
}
public static class ProxyServerInfo

View File

@ -20,8 +20,6 @@ package org.eclipse.jetty.spdy.server.proxy;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -44,7 +42,9 @@ import org.eclipse.jetty.spdy.StandardStream;
import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.GoAwayReceivedInfo;
import org.eclipse.jetty.spdy.api.HeadersInfo;
import org.eclipse.jetty.spdy.api.PushInfo;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.RstInfo;
import org.eclipse.jetty.spdy.api.SessionStatus;
@ -135,7 +135,7 @@ public class ProxyHTTPSPDYConnection extends HttpConnection implements HttpParse
{
assert content == null;
if (headers.isEmpty())
proxyEngineSelector.onGoAway(session, new GoAwayInfo(0, SessionStatus.OK));
proxyEngineSelector.onGoAway(session, new GoAwayReceivedInfo(0, SessionStatus.OK));
else
syn(true);
}
@ -184,14 +184,14 @@ public class ProxyHTTPSPDYConnection extends HttpConnection implements HttpParse
}
@Override
public void rst(RstInfo rstInfo, long timeout, TimeUnit unit, Callback handler)
public void rst(RstInfo rstInfo, Callback handler)
{
// Not much we can do in HTTP land: just close the connection
goAway(timeout, unit, handler);
goAway(new GoAwayInfo(rstInfo.getTimeout(), rstInfo.getUnit()), handler);
}
@Override
public void goAway(long timeout, TimeUnit unit, Callback handler)
public void goAway(GoAwayInfo goAwayInfo, Callback handler)
{
getEndPoint().close();
handler.succeeded();
@ -211,21 +211,21 @@ public class ProxyHTTPSPDYConnection extends HttpConnection implements HttpParse
}
@Override
public void syn(SynInfo synInfo, long timeout, TimeUnit unit, Promise<Stream> handler)
public void push(PushInfo pushInfo, Promise<Stream> handler)
{
// HTTP does not support pushed streams
handler.succeeded(new HTTPPushStream(2, getPriority(), getSession(), this));
}
@Override
public void headers(HeadersInfo headersInfo, long timeout, TimeUnit unit, Callback handler)
public void headers(HeadersInfo headersInfo, Callback handler)
{
// TODO
throw new UnsupportedOperationException("Not Yet Implemented");
}
@Override
public void reply(ReplyInfo replyInfo, long timeout, TimeUnit unit, Callback handler)
public void reply(ReplyInfo replyInfo, Callback handler)
{
try
{
@ -284,7 +284,7 @@ public class ProxyHTTPSPDYConnection extends HttpConnection implements HttpParse
}
@Override
public void data(DataInfo dataInfo, long timeout, TimeUnit unit, Callback handler)
public void data(DataInfo dataInfo, Callback handler)
{
try
{
@ -313,14 +313,14 @@ public class ProxyHTTPSPDYConnection extends HttpConnection implements HttpParse
}
@Override
public void headers(HeadersInfo headersInfo, long timeout, TimeUnit unit, Callback handler)
public void headers(HeadersInfo headersInfo, Callback handler)
{
// Ignore pushed headers
handler.succeeded();
}
@Override
public void data(DataInfo dataInfo, long timeout, TimeUnit unit, Callback handler)
public void data(DataInfo dataInfo, Callback handler)
{
// Ignore pushed data
handler.succeeded();

View File

@ -29,7 +29,9 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.GoAwayReceivedInfo;
import org.eclipse.jetty.spdy.api.HeadersInfo;
import org.eclipse.jetty.spdy.api.PushInfo;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.RstInfo;
import org.eclipse.jetty.spdy.api.SPDY;
@ -108,7 +110,7 @@ public class SPDYProxyEngine extends ProxyEngine implements StreamFrameListener
StreamFrameListener listener = new ProxyStreamFrameListener(clientStream);
StreamHandler handler = new StreamHandler(clientStream, serverSynInfo);
clientStream.setAttribute(STREAM_HANDLER_ATTRIBUTE, handler);
serverSession.syn(serverSynInfo, listener, timeout, TimeUnit.MILLISECONDS, handler);
serverSession.syn(serverSynInfo, listener, handler);
return this;
}
@ -170,7 +172,7 @@ public class SPDYProxyEngine extends ProxyEngine implements StreamFrameListener
Session existing = serverSessions.putIfAbsent(host, session);
if (existing != null)
{
session.goAway(getTimeout(), TimeUnit.MILLISECONDS, new Callback.Adapter());
session.goAway(new GoAwayInfo(), new Callback.Adapter());
session = existing;
}
}
@ -203,7 +205,7 @@ public class SPDYProxyEngine extends ProxyEngine implements StreamFrameListener
private void rst(Stream stream)
{
RstInfo rstInfo = new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM);
stream.getSession().rst(rstInfo, getTimeout(), TimeUnit.MILLISECONDS, new Callback.Adapter());
stream.getSession().rst(rstInfo, new Callback.Adapter());
}
private class ProxyStreamFrameListener extends StreamFrameListener.Adapter
@ -259,7 +261,7 @@ public class SPDYProxyEngine extends ProxyEngine implements StreamFrameListener
{
final ReplyInfo replyInfo = this.replyInfo;
this.replyInfo = null;
clientStream.reply(replyInfo, getTimeout(), TimeUnit.MILLISECONDS, new Callback()
clientStream.reply(replyInfo, new Callback()
{
@Override
public void succeeded()
@ -278,7 +280,7 @@ public class SPDYProxyEngine extends ProxyEngine implements StreamFrameListener
private void data(final Stream stream, final DataInfo dataInfo)
{
clientStream.data(dataInfo, getTimeout(), TimeUnit.MILLISECONDS, new Callback()
clientStream.data(dataInfo, new Callback() //TODO: timeout???
{
@Override
public void succeeded()
@ -394,7 +396,7 @@ public class SPDYProxyEngine extends ProxyEngine implements StreamFrameListener
private void flush(Stream serverStream, DataInfoHandler dataInfoHandler)
{
logger.debug("P -> S {} on {}", dataInfoHandler.dataInfo, serverStream);
serverStream.data(dataInfoHandler.dataInfo, getTimeout(), TimeUnit.MILLISECONDS,dataInfoHandler);
serverStream.data(dataInfoHandler.dataInfo, dataInfoHandler); //TODO: timeout???
}
private class DataInfoHandler implements Callback
@ -459,8 +461,8 @@ public class SPDYProxyEngine extends ProxyEngine implements StreamFrameListener
StreamHandler handler = new StreamHandler(clientStream, serverSynInfo);
serverStream.setAttribute(STREAM_HANDLER_ATTRIBUTE, handler);
clientStream.syn(new SynInfo(headers, serverSynInfo.isClose()), getTimeout(), TimeUnit.MILLISECONDS, handler);
clientStream.push(new PushInfo(getTimeout(), TimeUnit.MILLISECONDS, headers, serverSynInfo.isClose()),
handler);
return this;
}
@ -475,13 +477,13 @@ public class SPDYProxyEngine extends ProxyEngine implements StreamFrameListener
{
Session clientSession = clientStream.getSession();
RstInfo clientRstInfo = new RstInfo(clientStream.getId(), serverRstInfo.getStreamStatus());
clientSession.rst(clientRstInfo, getTimeout(), TimeUnit.MILLISECONDS, new Callback.Adapter());
clientSession.rst(clientRstInfo, new Callback.Adapter());
}
}
}
@Override
public void onGoAway(Session serverSession, GoAwayInfo goAwayInfo)
public void onGoAway(Session serverSession, GoAwayReceivedInfo goAwayReceivedInfo)
{
serverSessions.values().remove(serverSession);
}

View File

@ -21,7 +21,6 @@ package org.eclipse.jetty.spdy.server.http;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpStatus;
@ -49,7 +48,6 @@ import org.mockito.runners.MockitoJUnitRunner;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ -97,7 +95,7 @@ public class HttpTransportOverSPDYTest
httpTransportOverSPDY.send(null, content, lastContent, callback);
ArgumentCaptor<ByteBufferDataInfo> dataInfoCaptor = ArgumentCaptor.forClass(ByteBufferDataInfo.class);
verify(stream, times(1)).data(dataInfoCaptor.capture(), anyLong(), any(TimeUnit.class), any(Callback.class));
verify(stream, times(1)).data(dataInfoCaptor.capture(), any(Callback.class));
assertThat("lastContent is true", dataInfoCaptor.getValue().isClose(), is(true));
assertThat("ByteBuffer is empty", dataInfoCaptor.getValue().length(), is(0));
}
@ -108,11 +106,10 @@ public class HttpTransportOverSPDYTest
ByteBuffer content = createRandomByteBuffer();
boolean lastContent = true;
httpTransportOverSPDY.send(null, content, lastContent, callback);
ArgumentCaptor<ByteBufferDataInfo> dataInfoCaptor = ArgumentCaptor.forClass(ByteBufferDataInfo.class);
verify(stream, times(1)).data(dataInfoCaptor.capture(), anyLong(), any(TimeUnit.class), any(Callback.class));
verify(stream, times(1)).data(dataInfoCaptor.capture(), any(Callback.class));
assertThat("lastContent is true", dataInfoCaptor.getValue().isClose(), is(true));
assertThat("ByteBuffer length is 4096", dataInfoCaptor.getValue().length(), is(4096));
}
@ -126,7 +123,7 @@ public class HttpTransportOverSPDYTest
httpTransportOverSPDY.send(null, content, lastContent, callback);
ArgumentCaptor<ByteBufferDataInfo> dataInfoCaptor = ArgumentCaptor.forClass(ByteBufferDataInfo.class);
verify(stream, times(1)).data(dataInfoCaptor.capture(), anyLong(), any(TimeUnit.class), any(Callback.class));
verify(stream, times(1)).data(dataInfoCaptor.capture(), any(Callback.class));
assertThat("lastContent is true", dataInfoCaptor.getValue().isClose(), is(true));
assertThat("ByteBuffer is empty", dataInfoCaptor.getValue().length(), is(0));
}
@ -139,7 +136,7 @@ public class HttpTransportOverSPDYTest
httpTransportOverSPDY.send(null, content, lastContent, callback);
verify(stream, times(0)).data(any(ByteBufferDataInfo.class), anyLong(), any(TimeUnit.class), any(Callback.class));
verify(stream, times(0)).data(any(ByteBufferDataInfo.class), any(Callback.class));
}
@Test
@ -151,7 +148,7 @@ public class HttpTransportOverSPDYTest
httpTransportOverSPDY.send(null, content, lastContent, callback);
ArgumentCaptor<ByteBufferDataInfo> dataInfoCaptor = ArgumentCaptor.forClass(ByteBufferDataInfo.class);
verify(stream, times(1)).data(dataInfoCaptor.capture(), anyLong(), any(TimeUnit.class), any(Callback.class));
verify(stream, times(1)).data(dataInfoCaptor.capture(), any(Callback.class));
assertThat("lastContent is false", dataInfoCaptor.getValue().isClose(), is(false));
assertThat("ByteBuffer is empty", dataInfoCaptor.getValue().length(), is(4096));
}
@ -164,7 +161,7 @@ public class HttpTransportOverSPDYTest
httpTransportOverSPDY.send(null, content, lastContent, callback);
verify(stream, times(0)).data(any(ByteBufferDataInfo.class), anyLong(), any(TimeUnit.class), any(Callback.class));
verify(stream, times(0)).data(any(ByteBufferDataInfo.class), any(Callback.class));
verify(callback, times(1)).succeeded();
}
@ -179,7 +176,7 @@ public class HttpTransportOverSPDYTest
httpTransportOverSPDY.send(responseInfo, content, lastContent, callback);
ArgumentCaptor<ReplyInfo> replyInfoCaptor = ArgumentCaptor.forClass(ReplyInfo.class);
verify(stream, times(1)).reply(replyInfoCaptor.capture());
verify(stream, times(1)).reply(replyInfoCaptor.capture(), any(Callback.class));
assertThat("ReplyInfo close is true", replyInfoCaptor.getValue().isClose(), is(true));
verify(callback, times(1)).succeeded();
@ -196,11 +193,11 @@ public class HttpTransportOverSPDYTest
httpTransportOverSPDY.send(responseInfo, content, lastContent, callback);
ArgumentCaptor<ReplyInfo> replyInfoCaptor = ArgumentCaptor.forClass(ReplyInfo.class);
verify(stream, times(1)).reply(replyInfoCaptor.capture());
verify(stream, times(1)).reply(replyInfoCaptor.capture(), any(Callback.class));
assertThat("ReplyInfo close is false", replyInfoCaptor.getValue().isClose(), is(false));
ArgumentCaptor<ByteBufferDataInfo> dataInfoCaptor = ArgumentCaptor.forClass(ByteBufferDataInfo.class);
verify(stream, times(1)).data(dataInfoCaptor.capture(), anyLong(), any(TimeUnit.class), any(Callback.class));
verify(stream, times(1)).data(dataInfoCaptor.capture(), any(Callback.class));
assertThat("lastContent is true", dataInfoCaptor.getValue().isClose(), is(true));
assertThat("ByteBuffer length is 4096", dataInfoCaptor.getValue().length(), is(4096));
}
@ -214,10 +211,10 @@ public class HttpTransportOverSPDYTest
httpTransportOverSPDY.send(responseInfo, content, lastContent, callback);
ArgumentCaptor<ReplyInfo> replyInfoCaptor = ArgumentCaptor.forClass(ReplyInfo.class);
verify(stream, times(1)).reply(replyInfoCaptor.capture());
verify(stream, times(1)).reply(replyInfoCaptor.capture(), any(Callback.class));
assertThat("ReplyInfo close is true", replyInfoCaptor.getValue().isClose(), is(false));
verify(stream, times(0)).data(any(ByteBufferDataInfo.class), anyLong(), any(TimeUnit.class), any(Callback.class));
verify(stream, times(0)).data(any(ByteBufferDataInfo.class), any(Callback.class));
}
@Test
@ -230,11 +227,11 @@ public class HttpTransportOverSPDYTest
httpTransportOverSPDY.send(responseInfo, content, lastContent, callback);
ArgumentCaptor<ReplyInfo> replyInfoCaptor = ArgumentCaptor.forClass(ReplyInfo.class);
verify(stream, times(1)).reply(replyInfoCaptor.capture());
verify(stream, times(1)).reply(replyInfoCaptor.capture(), any(Callback.class));
assertThat("ReplyInfo close is false", replyInfoCaptor.getValue().isClose(), is(false));
ArgumentCaptor<ByteBufferDataInfo> dataInfoCaptor = ArgumentCaptor.forClass(ByteBufferDataInfo.class);
verify(stream, times(1)).data(dataInfoCaptor.capture(), anyLong(), any(TimeUnit.class), any(Callback.class));
verify(stream, times(1)).data(dataInfoCaptor.capture(), any(Callback.class));
assertThat("lastContent is false", dataInfoCaptor.getValue().isClose(), is(false));
assertThat("ByteBuffer length is 4096", dataInfoCaptor.getValue().length(), is(4096));
}
@ -248,13 +245,12 @@ public class HttpTransportOverSPDYTest
httpTransportOverSPDY.send(responseInfo,content,lastContent, callback);
ArgumentCaptor<ReplyInfo> replyInfoCaptor = ArgumentCaptor.forClass(ReplyInfo.class);
verify(stream, times(1)).reply(replyInfoCaptor.capture());
verify(stream, times(1)).reply(replyInfoCaptor.capture(), any(Callback.class));
assertThat("ReplyInfo close is false", replyInfoCaptor.getValue().isClose(), is(false));
httpTransportOverSPDY.send(HttpGenerator.RESPONSE_500_INFO, null,true);
verify(stream, times(0)).data(any(DataInfo.class));
verify(stream, times(1)).data(any(DataInfo.class), anyLong(), any(TimeUnit.class), any(Callback.class));
verify(stream, times(1)).data(any(DataInfo.class), any(Callback.class));
((StdErrLog)Log.getLogger(HttpTransportOverSPDY.class)).setHideStacks(false);
}

View File

@ -43,6 +43,7 @@ import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.SessionFrameListener;
@ -97,7 +98,7 @@ public class PushStrategyBenchmarkTest extends AbstractHTTPSPDYTest
connector.setDefaultProtocol(factory.getProtocol());
Session session = startClient(version, address, new ClientSessionFrameListener());
benchmarkSPDY(pushStrategy, session);
session.goAway().get(5, TimeUnit.SECONDS);
session.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
// Second push strategy
pushStrategy = new ReferrerPushStrategy();
@ -105,7 +106,7 @@ public class PushStrategyBenchmarkTest extends AbstractHTTPSPDYTest
connector.setDefaultProtocol(factory.getProtocol());
session = startClient(version, address, new ClientSessionFrameListener());
benchmarkSPDY(pushStrategy, session);
session.goAway().get(5, TimeUnit.SECONDS);
session.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
}
private void benchmarkHTTP(HttpClient httpClient) throws Exception

View File

@ -43,7 +43,9 @@ import org.eclipse.jetty.spdy.api.StreamFrameListener;
import org.eclipse.jetty.spdy.api.StreamStatus;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.server.NPNServerConnectionFactory;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.Promise;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@ -117,7 +119,7 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
("" +
".css"),
is(true));
stream.getSession().rst(new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM));
stream.getSession().rst(new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM), new Callback.Adapter());
return new StreamFrameListener.Adapter()
{
@ -130,11 +132,11 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
};
}
});
// Send main request. That should initiate the push syn's which get reset by the client
// Send main request. That should initiate the push push's which get reset by the client
sendRequest(session, mainRequestHeaders);
assertThat("No push data is received", pushDataLatch.await(1, TimeUnit.SECONDS), is(false));
assertThat("Push syn headers valid", pushSynHeadersValid.await(5, TimeUnit.SECONDS), is(true));
assertThat("Push push headers valid", pushSynHeadersValid.await(5, TimeUnit.SECONDS), is(true));
sendRequest(session, associatedCSSRequestHeaders);
}
@ -224,7 +226,7 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
if (dataInfo.isClose())
dataReceivedLatch.countDown();
}
});
}, new Promise.Adapter<Stream>());
Assert.assertTrue(received200OKLatch.await(5, TimeUnit.SECONDS));
Assert.assertTrue(dataReceivedLatch.await(5, TimeUnit.SECONDS));
}
@ -286,7 +288,7 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
else
assertThat("No push data is received", pushDataLatch.await(1, TimeUnit.SECONDS), is(false));
if (validateHeaders)
assertThat("Push syn headers valid", pushSynHeadersValid.await(5, TimeUnit.SECONDS), is(true));
assertThat("Push push headers valid", pushSynHeadersValid.await(5, TimeUnit.SECONDS), is(true));
}
@Test

View File

@ -202,7 +202,8 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Fields headers = createHeaders("POST", path);
headers.put("content-type", "application/x-www-form-urlencoded");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, headers, false, (byte)0),
new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
@ -212,7 +213,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version)).value().contains("200"));
replyLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
});
stream.data(new StringDataInfo(data, true));
Assert.assertTrue(handlerLatch.await(5, TimeUnit.SECONDS));
@ -243,7 +244,8 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Fields headers = createHeaders("POST", path);
headers.put("content-type", "application/x-www-form-urlencoded");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, headers, false, (byte)0),
new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
@ -253,7 +255,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version)).value().contains("200"));
replyLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
});
// Sleep between the data frames so that they will be read in 2 reads
stream.data(new StringDataInfo(data1, false));
Thread.sleep(1000);
@ -287,7 +289,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Fields headers = createHeaders("POST", path);
headers.put("content-type", "application/x-www-form-urlencoded");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, headers, false, (byte)0), new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
@ -297,7 +299,8 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertTrue(replyHeaders.toString(), replyHeaders.get(HTTPSPDYHeader.STATUS.name(version)).value().contains("200"));
replyLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
});
// Send the data frames consecutively, so the server reads both frames in one read
stream.data(new StringDataInfo(data1, false));
stream.data(new StringDataInfo(data2, true));
@ -1034,7 +1037,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Fields headers = createHeaders("POST", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, headers, false, (byte)0), new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
@ -1043,7 +1046,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version)).value().contains("200"));
replyLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
});
stream.data(new BytesDataInfo(data, true));
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
@ -1077,7 +1080,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Fields headers = createHeaders("POST", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
session.syn(new SynInfo(5, TimeUnit.SECONDS, headers, true, (byte)0), new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
@ -1086,7 +1089,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version)).value().contains("200"));
replyLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
});
Assert.assertTrue("Not dispatched again after expire", dispatchedAgainAfterExpire.await(5,
TimeUnit.SECONDS));
@ -1122,7 +1125,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Fields headers = createHeaders("POST", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, headers, false, (byte)0), new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
@ -1131,7 +1134,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version)).value().contains("200"));
replyLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
});
stream.data(new BytesDataInfo(data, true));
Assert.assertTrue("Not dispatched again after expire", dispatchedAgainAfterExpire.await(5,
@ -1190,7 +1193,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Fields headers = createHeaders("POST", "/foo");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, headers, false, (byte)0), new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
@ -1199,7 +1202,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version)).value().contains("200"));
replyLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
});
stream.data(new BytesDataInfo(data, false));
stream.data(new BytesDataInfo(data, true));
@ -1258,7 +1261,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Fields headers = createHeaders("POST", "/foo");
final CountDownLatch responseLatch = new CountDownLatch(2);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, headers, false, (byte)0), new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
@ -1274,7 +1277,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
if (dataInfo.isClose())
responseLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
});
stream.data(new BytesDataInfo(data, true));
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
@ -1299,7 +1302,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Fields headers = createHeaders("POST", "/foo");
final CountDownLatch responseLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, headers, false, (byte)0), new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
@ -1308,9 +1311,9 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version)).value().contains("200"));
responseLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
});
stream.data(new BytesDataInfo(data, false));
stream.data(new BytesDataInfo(data, true)).get(5, TimeUnit.SECONDS);
stream.data(new BytesDataInfo(5, TimeUnit.SECONDS, data, true));
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
Assert.assertTrue(responseLatch.await(5, TimeUnit.SECONDS));

View File

@ -35,7 +35,10 @@ import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.spdy.api.BytesDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.GoAwayReceivedInfo;
import org.eclipse.jetty.spdy.api.PingInfo;
import org.eclipse.jetty.spdy.api.PingResultInfo;
import org.eclipse.jetty.spdy.api.PushInfo;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.RstInfo;
import org.eclipse.jetty.spdy.api.SPDY;
@ -103,7 +106,7 @@ public class ProxyHTTPSPDYTest
{
server = new Server();
SPDYServerConnector serverConnector = new SPDYServerConnector(server, listener);
serverConnector.addConnectionFactory(new SPDYServerConnectionFactory(version,listener));
serverConnector.addConnectionFactory(new SPDYServerConnectionFactory(version, listener));
serverConnector.setPort(0);
server.addConnector(serverConnector);
server.start();
@ -159,12 +162,12 @@ public class ProxyHTTPSPDYTest
Fields responseHeaders = new Fields();
responseHeaders.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
responseHeaders.put(HTTPSPDYHeader.STATUS.name(version), "200 OK");
stream.reply(new ReplyInfo(responseHeaders, true));
stream.reply(new ReplyInfo(responseHeaders, true), new Callback.Adapter());
return null;
}
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
public void onGoAway(Session session, GoAwayReceivedInfo goAwayInfo)
{
closeLatch.countDown();
}
@ -211,7 +214,7 @@ public class ProxyHTTPSPDYTest
responseHeaders.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
responseHeaders.put(HTTPSPDYHeader.STATUS.name(version), "200 OK");
ReplyInfo replyInfo = new ReplyInfo(responseHeaders, true);
stream.reply(replyInfo);
stream.reply(replyInfo, new Callback.Adapter());
return null;
}
}));
@ -272,8 +275,8 @@ public class ProxyHTTPSPDYTest
responseHeaders.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
responseHeaders.put(HTTPSPDYHeader.STATUS.name(version), "200 OK");
ReplyInfo replyInfo = new ReplyInfo(responseHeaders, false);
stream.reply(replyInfo);
stream.data(new BytesDataInfo(data, true));
stream.reply(replyInfo, new Callback.Adapter());
stream.data(new BytesDataInfo(data, true), new Callback.Adapter());
return null;
}
@ -335,7 +338,7 @@ public class ProxyHTTPSPDYTest
Fields headers = new Fields();
headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
headers.put(HTTPSPDYHeader.STATUS.name(version), "303 See Other");
stream.reply(new ReplyInfo(headers, true));
stream.reply(new ReplyInfo(headers, true), new Callback.Adapter());
}
}
};
@ -399,8 +402,8 @@ public class ProxyHTTPSPDYTest
responseHeaders.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
responseHeaders.put(HTTPSPDYHeader.STATUS.name(version), "200 OK");
ReplyInfo replyInfo = new ReplyInfo(responseHeaders, false);
stream.reply(replyInfo);
stream.data(new BytesDataInfo(data, true));
stream.reply(replyInfo, new Callback.Adapter());
stream.data(new BytesDataInfo(data, true), new Callback.Adapter());
}
}
};
@ -462,7 +465,7 @@ public class ProxyHTTPSPDYTest
Fields responseHeaders = new Fields();
responseHeaders.put(header, "baz");
stream.reply(new ReplyInfo(responseHeaders, true));
stream.reply(new ReplyInfo(responseHeaders, true), new Callback.Adapter());
return null;
}
}));
@ -487,7 +490,7 @@ public class ProxyHTTPSPDYTest
Assert.assertTrue(replyLatch.await(5, TimeUnit.SECONDS));
client.goAway().get(5, TimeUnit.SECONDS);
client.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
}
@Test
@ -506,8 +509,8 @@ public class ProxyHTTPSPDYTest
Fields responseHeaders = new Fields();
responseHeaders.put(header, "baz");
stream.reply(new ReplyInfo(responseHeaders, false));
stream.data(new BytesDataInfo(data, true));
stream.reply(new ReplyInfo(responseHeaders, false), new Callback.Adapter());
stream.data(new BytesDataInfo(data, true), new Callback.Adapter());
return null;
}
}));
@ -547,7 +550,7 @@ public class ProxyHTTPSPDYTest
Assert.assertTrue(replyLatch.await(5, TimeUnit.SECONDS));
Assert.assertTrue(dataLatch.await(5, TimeUnit.SECONDS));
client.goAway().get(5, TimeUnit.SECONDS);
client.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
}
@Test
@ -565,16 +568,16 @@ public class ProxyHTTPSPDYTest
Fields pushHeaders = new Fields();
pushHeaders.put(HTTPSPDYHeader.URI.name(version), "/push");
stream.syn(new SynInfo(pushHeaders, false), 5, TimeUnit.SECONDS, new Promise.Adapter<Stream>()
stream.push(new PushInfo(5, TimeUnit.SECONDS, pushHeaders, false), new Promise.Adapter<Stream>()
{
@Override
public void succeeded(Stream pushStream)
{
pushStream.data(new BytesDataInfo(data, true));
pushStream.data(new BytesDataInfo(data, true), new Callback.Adapter());
}
});
stream.reply(new ReplyInfo(responseHeaders, true));
stream.reply(new ReplyInfo(responseHeaders, true), new Callback.Adapter());
return null;
}
}));
@ -614,20 +617,20 @@ public class ProxyHTTPSPDYTest
Fields responseHeaders = new Fields();
responseHeaders.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
responseHeaders.put(HTTPSPDYHeader.STATUS.name(version), "200 OK");
stream.reply(new ReplyInfo(responseHeaders, false));
stream.reply(new ReplyInfo(responseHeaders, false), new Callback.Adapter());
Fields pushHeaders = new Fields();
pushHeaders.put(HTTPSPDYHeader.URI.name(version), "/push");
stream.syn(new SynInfo(pushHeaders, false), 5, TimeUnit.SECONDS, new Promise.Adapter<Stream>()
stream.push(new PushInfo(5, TimeUnit.SECONDS, pushHeaders, false), new Promise.Adapter<Stream>()
{
@Override
public void succeeded(Stream pushStream)
{
pushStream.data(new BytesDataInfo(data, true));
pushStream.data(new BytesDataInfo(data, true), new Callback.Adapter());
}
});
stream.data(new BytesDataInfo(data, true));
stream.data(new BytesDataInfo(data, true), new Callback.Adapter());
return null;
}
@ -681,7 +684,7 @@ public class ProxyHTTPSPDYTest
Assert.assertTrue(pushDataLatch.await(5, TimeUnit.SECONDS));
Assert.assertTrue(dataLatch.await(5, TimeUnit.SECONDS));
client.goAway().get(5, TimeUnit.SECONDS);
client.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
}
@Test
@ -697,17 +700,17 @@ public class ProxyHTTPSPDYTest
Session client = factory.newSPDYClient(version).connect(proxyAddress, new SessionFrameListener.Adapter()
{
@Override
public void onPing(Session session, PingInfo pingInfo)
public void onPing(Session session, PingResultInfo pingInfo)
{
pingLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
client.ping().get(5, TimeUnit.SECONDS);
client.ping(new PingInfo(5, TimeUnit.SECONDS));
Assert.assertTrue(pingLatch.await(5, TimeUnit.SECONDS));
client.goAway().get(5, TimeUnit.SECONDS);
client.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
}
@Test
@ -722,7 +725,7 @@ public class ProxyHTTPSPDYTest
Fields requestHeaders = synInfo.getHeaders();
Assert.assertNotNull(requestHeaders.get("via"));
stream.getSession().rst(new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM));
stream.getSession().rst(new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM), new Callback.Adapter());
return null;
}
@ -758,7 +761,7 @@ public class ProxyHTTPSPDYTest
Fields requestHeaders = synInfo.getHeaders();
Assert.assertNotNull(requestHeaders.get("via"));
stream.getSession().rst(new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM));
stream.getSession().rst(new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM), new Callback.Adapter());
return null;
}
@ -781,6 +784,6 @@ public class ProxyHTTPSPDYTest
Assert.assertTrue(resetLatch.await(5, TimeUnit.SECONDS));
client.goAway().get(5, TimeUnit.SECONDS);
client.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
}
}

View File

@ -32,18 +32,24 @@ import org.eclipse.jetty.spdy.CompressionFactory;
import org.eclipse.jetty.spdy.FlowControlStrategy;
import org.eclipse.jetty.spdy.StandardCompressionFactory;
import org.eclipse.jetty.spdy.StandardSession;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.eclipse.jetty.spdy.client.FlowControlStrategyFactory;
import org.eclipse.jetty.spdy.client.SPDYConnection;
import org.eclipse.jetty.spdy.generator.Generator;
import org.eclipse.jetty.spdy.parser.Parser;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ManagedObject("SPDY Server Connection Factory")
public class SPDYServerConnectionFactory extends AbstractConnectionFactory
{
private static final Logger LOG = Log.getLogger(SPDYServerConnectionFactory.class);
// This method is placed here so as to provide a check for NPN before attempting to load any
// NPN classes.
public static void checkNPNAvailable()
@ -51,15 +57,15 @@ public class SPDYServerConnectionFactory extends AbstractConnectionFactory
try
{
Class<?> npn = ClassLoader.getSystemClassLoader().loadClass("org.eclipse.jetty.npn.NextProtoNego");
if (npn.getClassLoader()!=null)
if (npn.getClassLoader() != null)
throw new IllegalStateException("NextProtoNego must be on JVM boot path");
}
catch (ClassNotFoundException e)
{
throw new IllegalStateException("No NextProtoNego on boot path",e);
throw new IllegalStateException("No NextProtoNego on boot path", e);
}
}
private final short version;
private final ServerSessionFrameListener listener;
private int initialWindowSize;
@ -70,9 +76,9 @@ public class SPDYServerConnectionFactory extends AbstractConnectionFactory
this(version, null);
}
public SPDYServerConnectionFactory(int version, ServerSessionFrameListener listener)
public SPDYServerConnectionFactory(int version, ServerSessionFrameListener listener)
{
super("spdy/"+version);
super("spdy/" + version);
this.version = (short)version;
this.listener = listener;
setInitialWindowSize(65536);
@ -96,8 +102,8 @@ public class SPDYServerConnectionFactory extends AbstractConnectionFactory
Parser parser = new Parser(compressionFactory.newDecompressor());
Generator generator = new Generator(connector.getByteBufferPool(), compressionFactory.newCompressor());
ServerSessionFrameListener listener = provideServerSessionFrameListener(connector,endPoint);
SPDYConnection connection = new ServerSPDYConnection(connector,endPoint, parser, listener, getInputBufferSize());
ServerSessionFrameListener listener = provideServerSessionFrameListener(connector, endPoint);
SPDYConnection connection = new ServerSPDYConnection(connector, endPoint, parser, listener, getInputBufferSize());
FlowControlStrategy flowControlStrategy = newFlowControlStrategy(version);
@ -110,7 +116,7 @@ public class SPDYServerConnectionFactory extends AbstractConnectionFactory
sessionOpened(session);
return configure(connection,connector,endPoint);
return configure(connection, connector, endPoint);
}
protected FlowControlStrategy newFlowControlStrategy(short version)
@ -150,7 +156,7 @@ public class SPDYServerConnectionFactory extends AbstractConnectionFactory
void closeSessions()
{
for (Session session : sessions)
session.goAway();
session.goAway(new GoAwayInfo(), new Callback.Adapter());
sessions.clear();
}
@ -171,9 +177,9 @@ public class SPDYServerConnectionFactory extends AbstractConnectionFactory
private final ServerSessionFrameListener listener;
private final AtomicBoolean connected = new AtomicBoolean();
private ServerSPDYConnection(Connector connector,EndPoint endPoint, Parser parser, ServerSessionFrameListener listener, int bufferSize)
private ServerSPDYConnection(Connector connector, EndPoint endPoint, Parser parser, ServerSessionFrameListener listener, int bufferSize)
{
super(endPoint, connector.getByteBufferPool(), parser, connector.getExecutor(),bufferSize);
super(endPoint, connector.getByteBufferPool(), parser, connector.getExecutor(), bufferSize);
this.listener = listener;
}

View File

@ -31,6 +31,7 @@ import org.eclipse.jetty.spdy.StandardCompressionFactory;
import org.eclipse.jetty.spdy.api.BytesDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.GoAwayReceivedInfo;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Session;
@ -48,6 +49,7 @@ import org.eclipse.jetty.spdy.frames.SynStreamFrame;
import org.eclipse.jetty.spdy.generator.Generator;
import org.eclipse.jetty.spdy.parser.Parser;
import org.eclipse.jetty.spdy.parser.Parser.Listener;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.junit.Assert;
import org.junit.Ignore;
@ -69,7 +71,7 @@ public class ClosedStreamTest extends AbstractTest
Session session = startClient(new InetSocketAddress("localhost", server.socket().getLocalPort()), null);
final CountDownLatch dataLatch = new CountDownLatch(2);
session.syn(new SynInfo(true), new StreamFrameListener.Adapter()
session.syn(new SynInfo(new Fields(), true), new StreamFrameListener.Adapter()
{
@Override
public void onData(Stream stream, DataInfo dataInfo)
@ -102,7 +104,7 @@ public class ClosedStreamTest extends AbstractTest
Assert.assertFalse(dataLatch.await(1, TimeUnit.SECONDS));
session.goAway().get(5, TimeUnit.SECONDS);
session.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
server.close();
}
@ -119,7 +121,7 @@ public class ClosedStreamTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.reply(new ReplyInfo(true));
stream.reply(new ReplyInfo(true), new Callback.Adapter());
try
{
replyReceivedLatch.await(5,TimeUnit.SECONDS);
@ -130,7 +132,7 @@ public class ClosedStreamTest extends AbstractTest
}
try
{
stream.data(new StringDataInfo("data send after half closed",false));
stream.data(new StringDataInfo("data send after half closed",false), new Callback.Adapter());
}
catch (RuntimeException e)
{
@ -142,7 +144,7 @@ public class ClosedStreamTest extends AbstractTest
}
}),null);
Stream stream = clientSession.syn(new SynInfo(false),new StreamFrameListener.Adapter()
Stream stream = clientSession.syn(new SynInfo(new Fields(), false),new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
@ -155,7 +157,7 @@ public class ClosedStreamTest extends AbstractTest
{
clientReceivedDataLatch.countDown();
}
}).get();
});
assertThat("reply has been received by client",replyReceivedLatch.await(5,TimeUnit.SECONDS),is(true));
assertThat("stream is half closed from server",stream.isHalfClosed(),is(true));
assertThat("client has not received any data sent after stream was half closed by server",
@ -189,7 +191,7 @@ public class ClosedStreamTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.reply(new ReplyInfo(false));
stream.reply(new ReplyInfo(false), new Callback.Adapter());
serverReplySentLatch.countDown();
try
{
@ -209,7 +211,7 @@ public class ClosedStreamTest extends AbstractTest
};
}
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
public void onGoAway(Session session, GoAwayReceivedInfo goAwayInfo)
{
goAwayReceivedLatch.countDown();
}
@ -223,7 +225,7 @@ public class ClosedStreamTest extends AbstractTest
socketChannel.write(synData);
assertThat("synData is fully written", synData.hasRemaining(), is(false));
assertThat("server: syn reply is sent",serverReplySentLatch.await(5,TimeUnit.SECONDS),is(true));
assertThat("server: push reply is sent",serverReplySentLatch.await(5,TimeUnit.SECONDS),is(true));
Parser parser = new Parser(new StandardCompressionFactory.StandardDecompressor());
parser.addListener(new Listener.Adapter()

View File

@ -42,6 +42,9 @@ import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamFrameListener;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.FutureCallback;
import org.junit.Assert;
import org.junit.Test;
@ -66,7 +69,7 @@ public class FlowControlTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.reply(new ReplyInfo(true));
stream.reply(new ReplyInfo(true), new Callback.Adapter());
return new StreamFrameListener.Adapter()
{
private final AtomicInteger dataFrames = new AtomicInteger();
@ -80,7 +83,7 @@ public class FlowControlTest extends AbstractTest
dataInfoRef.set(dataInfo);
Settings settings = new Settings();
settings.put(new Settings.Setting(Settings.ID.INITIAL_WINDOW_SIZE, size));
stream.getSession().settings(new SettingsInfo(settings));
stream.getSession().settings(new SettingsInfo(settings), new FutureCallback());
}
else if (dataFrameCount > 1)
{
@ -99,12 +102,12 @@ public class FlowControlTest extends AbstractTest
}
});
Stream stream = session.syn(new SynInfo(false), null).get(5, TimeUnit.SECONDS);
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), false, (byte)0), null);
stream.data(new BytesDataInfo(new byte[size * 2], false));
settingsLatch.await(5, TimeUnit.SECONDS);
// Send the second chunk of data, must not arrive since we're flow control stalled now
stream.data(new BytesDataInfo(new byte[size * 2], true));
stream.data(new BytesDataInfo(new byte[size * 2], true), new Callback.Adapter());
Assert.assertFalse(dataLatch.await(1, TimeUnit.SECONDS));
// Consume the data arrived to server, this will resume flow control
@ -131,8 +134,8 @@ public class FlowControlTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.reply(new ReplyInfo(false));
stream.data(new BytesDataInfo(new byte[length], true));
stream.reply(new ReplyInfo(false), new Callback.Adapter());
stream.data(new BytesDataInfo(new byte[length], true), new Callback.Adapter());
return null;
}
}), null);
@ -144,7 +147,7 @@ public class FlowControlTest extends AbstractTest
Assert.assertTrue(settingsLatch.await(5, TimeUnit.SECONDS));
final Exchanger<DataInfo> exchanger = new Exchanger<>();
session.syn(new SynInfo(true), new StreamFrameListener.Adapter()
session.syn(new SynInfo(new Fields(), true), new StreamFrameListener.Adapter()
{
private AtomicInteger dataFrames = new AtomicInteger();
@ -230,13 +233,13 @@ public class FlowControlTest extends AbstractTest
{
Settings settings = new Settings();
settings.put(new Settings.Setting(Settings.ID.INITIAL_WINDOW_SIZE, windowSize));
session.settings(new SettingsInfo(settings));
session.settings(new SettingsInfo(settings), new FutureCallback());
}
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.reply(new ReplyInfo(false));
stream.reply(new ReplyInfo(false), new Callback.Adapter());
return new StreamFrameListener.Adapter()
{
private AtomicInteger dataFrames = new AtomicInteger();
@ -294,9 +297,9 @@ public class FlowControlTest extends AbstractTest
Assert.assertTrue(settingsLatch.await(5, TimeUnit.SECONDS));
Stream stream = session.syn(new SynInfo(false), null).get(5, TimeUnit.SECONDS);
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), false, (byte)0), null);
final int length = 5 * windowSize;
stream.data(new BytesDataInfo(new byte[length], true));
stream.data(new BytesDataInfo(new byte[length], true), new Callback.Adapter());
DataInfo dataInfo = exchanger.exchange(null, 5, TimeUnit.SECONDS);
checkThatWeAreFlowControlStalled(exchanger);
@ -341,8 +344,8 @@ public class FlowControlTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.reply(new ReplyInfo(false));
stream.data(new BytesDataInfo(new byte[windowSize * 2], true));
stream.reply(new ReplyInfo(false), new Callback.Adapter());
stream.data(new BytesDataInfo(new byte[windowSize * 2], true), new Callback.Adapter());
return null;
}
}), null);
@ -355,7 +358,7 @@ public class FlowControlTest extends AbstractTest
final CountDownLatch latch = new CountDownLatch(3);
final AtomicReference<DataInfo> dataInfoRef1 = new AtomicReference<>();
final AtomicReference<DataInfo> dataInfoRef2 = new AtomicReference<>();
session.syn(new SynInfo(true), new StreamFrameListener.Adapter()
session.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), true, (byte)0), new StreamFrameListener.Adapter()
{
private final AtomicInteger dataFrames = new AtomicInteger();
@ -375,8 +378,8 @@ public class FlowControlTest extends AbstractTest
latch.countDown();
}
}
}).get(5, TimeUnit.SECONDS);
session.syn(new SynInfo(true), new StreamFrameListener.Adapter()
});
session.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), true, (byte)0), new StreamFrameListener.Adapter()
{
private final AtomicInteger dataFrames = new AtomicInteger();
@ -396,8 +399,8 @@ public class FlowControlTest extends AbstractTest
latch.countDown();
}
}
}).get(5, TimeUnit.SECONDS);
session.syn(new SynInfo(true), new StreamFrameListener.Adapter()
});
session.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), true, (byte)0), new StreamFrameListener.Adapter()
{
@Override
public void onData(Stream stream, DataInfo dataInfo)
@ -412,7 +415,7 @@ public class FlowControlTest extends AbstractTest
if (dataInfo.isClose())
latch.countDown();
}
}).get(5, TimeUnit.SECONDS);
});
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
}
@ -440,13 +443,13 @@ public class FlowControlTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.reply(new ReplyInfo(false));
stream.data(bigByteBufferDataInfo);
stream.reply(new ReplyInfo(false), new Callback.Adapter());
stream.data(bigByteBufferDataInfo, new Callback.Adapter());
return null;
}
}),new SessionFrameListener.Adapter());
session.syn(new SynInfo(false),new StreamFrameListener.Adapter()
session.syn(new SynInfo(new Fields(), false),new StreamFrameListener.Adapter()
{
private int dataBytesReceived;

View File

@ -18,16 +18,17 @@
package org.eclipse.jetty.spdy.server;
import java.nio.channels.ClosedChannelException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.GoAwayReceivedInfo;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.SPDYException;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.SessionFrameListener;
import org.eclipse.jetty.spdy.api.SessionStatus;
@ -36,6 +37,10 @@ import org.eclipse.jetty.spdy.api.StreamFrameListener;
import org.eclipse.jetty.spdy.api.StringDataInfo;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.util.FuturePromise;
import org.hamcrest.CoreMatchers;
import org.junit.Assert;
import org.junit.Test;
@ -51,12 +56,12 @@ public class GoAwayTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.reply(new ReplyInfo(true));
stream.reply(new ReplyInfo(true), new Callback.Adapter());
return null;
}
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
public void onGoAway(Session session, GoAwayReceivedInfo goAwayInfo)
{
Assert.assertEquals(0, goAwayInfo.getLastStreamId());
Assert.assertSame(SessionStatus.OK, goAwayInfo.getSessionStatus());
@ -65,9 +70,9 @@ public class GoAwayTest extends AbstractTest
};
Session session = startClient(startServer(serverSessionFrameListener), null);
session.syn(new SynInfo(true), null);
session.syn(new SynInfo(new Fields(), true), null);
session.goAway();
session.goAway(new GoAwayInfo());
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
}
@ -80,17 +85,17 @@ public class GoAwayTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.reply(new ReplyInfo(true));
stream.getSession().goAway();
stream.reply(new ReplyInfo(true), new Callback.Adapter());
stream.getSession().goAway(new GoAwayInfo(), new FutureCallback());
return null;
}
};
final AtomicReference<GoAwayInfo> ref = new AtomicReference<>();
final AtomicReference<GoAwayReceivedInfo> ref = new AtomicReference<>();
final CountDownLatch latch = new CountDownLatch(1);
SessionFrameListener clientSessionFrameListener = new SessionFrameListener.Adapter()
{
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
public void onGoAway(Session session, GoAwayReceivedInfo goAwayInfo)
{
ref.set(goAwayInfo);
latch.countDown();
@ -98,13 +103,13 @@ public class GoAwayTest extends AbstractTest
};
Session session = startClient(startServer(serverSessionFrameListener), clientSessionFrameListener);
Stream stream1 = session.syn(new SynInfo(true), null).get(5, TimeUnit.SECONDS);
Stream stream1 = session.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), true, (byte)0), null);
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
GoAwayInfo goAwayInfo = ref.get();
Assert.assertNotNull(goAwayInfo);
Assert.assertEquals(stream1.getId(), goAwayInfo.getLastStreamId());
Assert.assertSame(SessionStatus.OK, goAwayInfo.getSessionStatus());
GoAwayReceivedInfo goAwayReceivedInfo = ref.get();
Assert.assertNotNull(goAwayReceivedInfo);
Assert.assertEquals(stream1.getId(), goAwayReceivedInfo.getLastStreamId());
Assert.assertSame(SessionStatus.OK, goAwayReceivedInfo.getSessionStatus());
}
@Test
@ -121,8 +126,8 @@ public class GoAwayTest extends AbstractTest
int synCount = syns.incrementAndGet();
if (synCount == 1)
{
stream.reply(new ReplyInfo(true));
stream.getSession().goAway();
stream.reply(new ReplyInfo(true), new Callback.Adapter());
stream.getSession().goAway(new GoAwayInfo(), new FutureCallback());
}
else
{
@ -134,14 +139,14 @@ public class GoAwayTest extends AbstractTest
SessionFrameListener clientSessionFrameListener = new SessionFrameListener.Adapter()
{
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
public void onGoAway(Session session, GoAwayReceivedInfo goAwayInfo)
{
session.syn(new SynInfo(true), null);
session.syn(new SynInfo(new Fields(), true), null, new FuturePromise<Stream>());
}
};
Session session = startClient(startServer(serverSessionFrameListener), clientSessionFrameListener);
session.syn(new SynInfo(true), null);
session.syn(new SynInfo(new Fields(), true), null);
Assert.assertFalse(latch.await(1, TimeUnit.SECONDS));
}
@ -158,7 +163,7 @@ public class GoAwayTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.reply(new ReplyInfo(true));
stream.reply(new ReplyInfo(true), new Callback.Adapter());
int synCount = syns.incrementAndGet();
if (synCount == 1)
{
@ -166,7 +171,7 @@ public class GoAwayTest extends AbstractTest
}
else
{
stream.getSession().goAway();
stream.getSession().goAway(new GoAwayInfo(), new FutureCallback());
closeLatch.countDown();
return new StreamFrameListener.Adapter()
{
@ -179,12 +184,12 @@ public class GoAwayTest extends AbstractTest
}
}
};
final AtomicReference<GoAwayInfo> goAwayRef = new AtomicReference<>();
final AtomicReference<GoAwayReceivedInfo> goAwayRef = new AtomicReference<>();
final CountDownLatch goAwayLatch = new CountDownLatch(1);
SessionFrameListener clientSessionFrameListener = new SessionFrameListener.Adapter()
{
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
public void onGoAway(Session session, GoAwayReceivedInfo goAwayInfo)
{
goAwayRef.set(goAwayInfo);
goAwayLatch.countDown();
@ -194,18 +199,18 @@ public class GoAwayTest extends AbstractTest
// First stream is processed ok
final CountDownLatch reply1Latch = new CountDownLatch(1);
Stream stream1 = session.syn(new SynInfo(true), new StreamFrameListener.Adapter()
session.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), true, (byte)0), new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
{
reply1Latch.countDown();
}
}).get(5, TimeUnit.SECONDS);
});
Assert.assertTrue(reply1Latch.await(5, TimeUnit.SECONDS));
// Second stream is closed in the middle
Stream stream2 = session.syn(new SynInfo(false), null).get(5, TimeUnit.SECONDS);
Stream stream2 = session.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), false, (byte)0), null);
Assert.assertTrue(closeLatch.await(5, TimeUnit.SECONDS));
// There is a race between the data we want to send, and the client
@ -216,14 +221,14 @@ public class GoAwayTest extends AbstractTest
stream2.data(new StringDataInfo("foo", true));
Assert.assertFalse(dataLatch.await(1, TimeUnit.SECONDS));
}
catch (SPDYException x)
catch (ExecutionException x)
{
Assert.assertThat(x.getCause(), CoreMatchers.instanceOf(ClosedChannelException.class));
Assert.assertThat(x.getCause(), CoreMatchers.instanceOf(EofException.class));
}
// The last good stream is the second, because it was received by the server
Assert.assertTrue(goAwayLatch.await(5, TimeUnit.SECONDS));
GoAwayInfo goAway = goAwayRef.get();
GoAwayReceivedInfo goAway = goAwayRef.get();
Assert.assertNotNull(goAway);
Assert.assertEquals(stream2.getId(), goAway.getLastStreamId());
}

View File

@ -29,6 +29,7 @@ import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamFrameListener;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.junit.Assert;
import org.junit.Test;
@ -43,14 +44,14 @@ public class HeadersTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.reply(new ReplyInfo(false));
stream.reply(new ReplyInfo(false), new Callback.Adapter());
return new StreamFrameListener.Adapter()
{
@Override
public void onHeaders(Stream stream, HeadersInfo headersInfo)
{
Assert.assertTrue(stream.isHalfClosed());
stream.headers(new HeadersInfo(new Fields(), true));
stream.headers(new HeadersInfo(new Fields(), true), new Callback.Adapter());
Assert.assertTrue(stream.isClosed());
}
};
@ -60,7 +61,7 @@ public class HeadersTest extends AbstractTest
Session session = startClient(startServer(serverSessionFrameListener), null);
final CountDownLatch latch = new CountDownLatch(1);
session.syn(new SynInfo(false), new StreamFrameListener.Adapter()
session.syn(new SynInfo(new Fields(), false), new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
@ -68,7 +69,7 @@ public class HeadersTest extends AbstractTest
Fields headers = new Fields();
headers.put("foo", "bar");
headers.put("baz", "woo");
stream.headers(new HeadersInfo(headers, true));
stream.headers(new HeadersInfo(headers, true), new Callback.Adapter());
Assert.assertTrue(stream.isHalfClosed());
}

View File

@ -23,7 +23,7 @@ import java.net.InetSocketAddress;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.GoAwayReceivedInfo;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Session;
@ -33,6 +33,8 @@ import org.eclipse.jetty.spdy.api.StreamFrameListener;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.eclipse.jetty.spdy.client.SPDYClient;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.junit.Assert;
import org.junit.Test;
@ -51,7 +53,7 @@ public class IdleTimeoutTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.reply(new ReplyInfo(true));
stream.reply(new ReplyInfo(true), new Callback.Adapter());
return null;
}
});
@ -61,13 +63,13 @@ public class IdleTimeoutTest extends AbstractTest
Session session = startClient(startServer(null), new SessionFrameListener.Adapter()
{
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
public void onGoAway(Session session, GoAwayReceivedInfo goAwayInfo)
{
latch.countDown();
}
});
session.syn(new SynInfo(true), null);
session.syn(new SynInfo(new Fields(), true), null);
Assert.assertTrue(latch.await(2 * idleTimeout, TimeUnit.MILLISECONDS));
}
@ -83,14 +85,14 @@ public class IdleTimeoutTest extends AbstractTest
Session session = startClient(startServer(null), new SessionFrameListener.Adapter()
{
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
public void onGoAway(Session session, GoAwayReceivedInfo goAwayInfo)
{
latch.countDown();
}
});
// The SYN is not replied, and the server should idle timeout
session.syn(new SynInfo(true), null);
session.syn(new SynInfo(new Fields(), true), null);
Assert.assertTrue(latch.await(2 * idleTimeout, TimeUnit.MILLISECONDS));
}
@ -107,7 +109,7 @@ public class IdleTimeoutTest extends AbstractTest
try
{
Thread.sleep(2 * idleTimeout);
stream.reply(new ReplyInfo(true));
stream.reply(new ReplyInfo(true), new Callback.Adapter());
return null;
}
catch (InterruptedException x)
@ -123,14 +125,14 @@ public class IdleTimeoutTest extends AbstractTest
Session session = startClient(startServer(null), new SessionFrameListener.Adapter()
{
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
public void onGoAway(Session session, GoAwayReceivedInfo goAwayInfo)
{
goAwayLatch.countDown();
}
});
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(new SynInfo(true), new StreamFrameListener.Adapter()
session.syn(new SynInfo(new Fields(), true), new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
@ -154,12 +156,12 @@ public class IdleTimeoutTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.reply(new ReplyInfo(true));
stream.reply(new ReplyInfo(true), new Callback.Adapter());
return null;
}
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
public void onGoAway(Session session, GoAwayReceivedInfo goAwayInfo)
{
latch.countDown();
}
@ -173,7 +175,7 @@ public class IdleTimeoutTest extends AbstractTest
client.setIdleTimeout(idleTimeout);
Session session = client.connect(address, null).get(5, TimeUnit.SECONDS);
session.syn(new SynInfo(true), null);
session.syn(new SynInfo(new Fields(), true), null);
Assert.assertTrue(latch.await(2 * idleTimeout, TimeUnit.MILLISECONDS));
}
@ -185,7 +187,7 @@ public class IdleTimeoutTest extends AbstractTest
InetSocketAddress address = startServer(new ServerSessionFrameListener.Adapter()
{
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
public void onGoAway(Session session, GoAwayReceivedInfo goAwayInfo)
{
latch.countDown();
}
@ -199,7 +201,7 @@ public class IdleTimeoutTest extends AbstractTest
client.setIdleTimeout(idleTimeout);
Session session = client.connect(address, null).get(5, TimeUnit.SECONDS);
session.syn(new SynInfo(true), null);
session.syn(new SynInfo(new Fields(), true), null);
Assert.assertTrue(latch.await(2 * idleTimeout, TimeUnit.MILLISECONDS));
}
@ -213,12 +215,12 @@ public class IdleTimeoutTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.reply(new ReplyInfo(true));
stream.reply(new ReplyInfo(true), new Callback.Adapter());
return null;
}
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
public void onGoAway(Session session, GoAwayReceivedInfo goAwayInfo)
{
latch.countDown();
}
@ -233,7 +235,7 @@ public class IdleTimeoutTest extends AbstractTest
Session session = client.connect(address, null).get(5, TimeUnit.SECONDS);
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(new SynInfo(true), new StreamFrameListener.Adapter()
session.syn(new SynInfo(new Fields(), true), new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)

View File

@ -24,10 +24,10 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.spdy.api.PingInfo;
import org.eclipse.jetty.spdy.api.PingResultInfo;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.SessionFrameListener;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Promise;
import org.junit.Assert;
import org.junit.Test;
@ -37,25 +37,25 @@ public class PingTest extends AbstractTest
@Test
public void testPingPong() throws Exception
{
final AtomicReference<PingInfo> ref = new AtomicReference<>();
final AtomicReference<PingResultInfo> ref = new AtomicReference<>();
final CountDownLatch latch = new CountDownLatch(1);
SessionFrameListener clientSessionFrameListener = new SessionFrameListener.Adapter()
{
@Override
public void onPing(Session session, PingInfo pingInfo)
public void onPing(Session session, PingResultInfo pingInfo)
{
ref.set(pingInfo);
latch.countDown();
}
};
Session session = startClient(startServer(null), clientSessionFrameListener);
PingInfo pingInfo = session.ping().get(5, TimeUnit.SECONDS);
Assert.assertEquals(1, pingInfo.getPingId() % 2);
PingResultInfo pingResultInfo = session.ping(new PingInfo(5, TimeUnit.SECONDS));
Assert.assertEquals(1, pingResultInfo.getPingId() % 2);
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
PingInfo pongInfo = ref.get();
PingResultInfo pongInfo = ref.get();
Assert.assertNotNull(pongInfo);
Assert.assertEquals(pingInfo.getPingId(), pongInfo.getPingId());
Assert.assertEquals(pingResultInfo.getPingId(), pongInfo.getPingId());
}
@Test
@ -69,10 +69,10 @@ public class PingTest extends AbstractTest
@Override
public void onConnect(Session session)
{
session.ping(0, TimeUnit.MILLISECONDS, new Promise.Adapter<PingInfo>()
session.ping(new PingInfo(), new Promise.Adapter<PingResultInfo>()
{
@Override
public void succeeded(PingInfo pingInfo)
public void succeeded(PingResultInfo pingInfo)
{
pingId = pingInfo.getPingId();
}
@ -80,7 +80,7 @@ public class PingTest extends AbstractTest
}
@Override
public void onPing(Session session, PingInfo pingInfo)
public void onPing(Session session, PingResultInfo pingInfo)
{
Assert.assertEquals(0, pingInfo.getPingId() % 2);
Assert.assertEquals(pingId, pingInfo.getPingId());

View File

@ -29,6 +29,7 @@ import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.spdy.StandardCompressionFactory;
import org.eclipse.jetty.spdy.api.BytesDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.HeadersInfo;
import org.eclipse.jetty.spdy.api.RstInfo;
import org.eclipse.jetty.spdy.api.SPDY;
@ -43,6 +44,7 @@ import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.eclipse.jetty.spdy.frames.ControlFrameType;
import org.eclipse.jetty.spdy.frames.SynReplyFrame;
import org.eclipse.jetty.spdy.generator.Generator;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.junit.Assert;
import org.junit.Test;
@ -64,7 +66,7 @@ public class ProtocolViolationsTest extends AbstractTest
{
try
{
stream.data(new StringDataInfo("failure", true));
stream.data(new StringDataInfo("failure", true), new Callback.Adapter());
return null;
}
catch (IllegalStateException x)
@ -82,7 +84,7 @@ public class ProtocolViolationsTest extends AbstractTest
resetLatch.countDown();
}
});
session.syn(new SynInfo(true), null);
session.syn(new SynInfo(new Fields(), true), null);
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
Assert.assertTrue(resetLatch.await(5, TimeUnit.SECONDS));
}
@ -94,7 +96,7 @@ public class ProtocolViolationsTest extends AbstractTest
server.bind(new InetSocketAddress("localhost", 0));
Session session = startClient(new InetSocketAddress("localhost", server.socket().getLocalPort()), null);
session.syn(new SynInfo(true), null);
session.syn(new SynInfo(new Fields(), true), null);
SocketChannel channel = server.accept();
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
@ -114,7 +116,7 @@ public class ProtocolViolationsTest extends AbstractTest
Assert.assertEquals(ControlFrameType.RST_STREAM.getCode(), readBuffer.getShort(2));
Assert.assertEquals(streamId, readBuffer.getInt(8));
session.goAway().get(5,TimeUnit.SECONDS);
session.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
server.close();
}
@ -123,7 +125,7 @@ public class ProtocolViolationsTest extends AbstractTest
public void testSendDataAfterCloseIsIllegal() throws Exception
{
Session session = startClient(startServer(null), null);
Stream stream = session.syn(new SynInfo(true), null).get(5, TimeUnit.SECONDS);
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), true, (byte)0), null);
stream.data(new StringDataInfo("test", true));
}
@ -131,7 +133,7 @@ public class ProtocolViolationsTest extends AbstractTest
public void testSendHeadersAfterCloseIsIllegal() throws Exception
{
Session session = startClient(startServer(null), null);
Stream stream = session.syn(new SynInfo(true), null).get(5, TimeUnit.SECONDS);
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), true, (byte)0), null);
stream.headers(new HeadersInfo(new Fields(), true));
}
@ -143,7 +145,7 @@ public class ProtocolViolationsTest extends AbstractTest
Session session = startClient(new InetSocketAddress("localhost", server.socket().getLocalPort()), null);
final CountDownLatch dataLatch = new CountDownLatch(2);
session.syn(new SynInfo(false), new StreamFrameListener.Adapter()
session.syn(new SynInfo(new Fields(), false), new StreamFrameListener.Adapter()
{
@Override
public void onData(Stream stream, DataInfo dataInfo)
@ -176,7 +178,7 @@ public class ProtocolViolationsTest extends AbstractTest
Assert.assertFalse(dataLatch.await(1, TimeUnit.SECONDS));
session.goAway().get(5,TimeUnit.SECONDS);
session.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
server.close();
}

View File

@ -30,6 +30,7 @@ import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
@ -37,7 +38,8 @@ import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.spdy.StandardCompressionFactory;
import org.eclipse.jetty.spdy.api.BytesDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.GoAwayReceivedInfo;
import org.eclipse.jetty.spdy.api.PushInfo;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.RstInfo;
import org.eclipse.jetty.spdy.api.SPDY;
@ -62,6 +64,8 @@ import org.eclipse.jetty.spdy.parser.Parser.Listener;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.junit.Assert;
import org.junit.Test;
@ -73,6 +77,8 @@ import static org.junit.Assert.fail;
public class PushStreamTest extends AbstractTest
{
private static final Logger LOG = Log.getLogger(PushStreamTest.class);
@Test
public void testSynPushStream() throws Exception
{
@ -84,8 +90,8 @@ public class PushStreamTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.reply(new ReplyInfo(false));
stream.syn(new SynInfo(true));
stream.reply(new ReplyInfo(false), new Callback.Adapter());
stream.push(new PushInfo(new Fields(), true), new Promise.Adapter<Stream>());
return null;
}
}), new SessionFrameListener.Adapter()
@ -93,13 +99,13 @@ public class PushStreamTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
assertThat("streamId is even",stream.getId() % 2,is(0));
assertThat("stream is unidirectional",stream.isUnidirectional(),is(true));
assertThat("stream is closed",stream.isClosed(),is(true));
assertThat("stream has associated stream",stream.getAssociatedStream(),notNullValue());
assertThat("streamId is even", stream.getId() % 2, is(0));
assertThat("stream is unidirectional", stream.isUnidirectional(), is(true));
assertThat("stream is closed", stream.isClosed(), is(true));
assertThat("stream has associated stream", stream.getAssociatedStream(), notNullValue());
try
{
stream.reply(new ReplyInfo(false));
stream.reply(new ReplyInfo(false), new Callback.Adapter());
fail("Cannot reply to push streams");
}
catch (IllegalStateException x)
@ -112,10 +118,10 @@ public class PushStreamTest extends AbstractTest
}
});
Stream stream = clientSession.syn(new SynInfo(true),null).get();
assertThat("onSyn has been called",pushStreamLatch.await(5,TimeUnit.SECONDS),is(true));
Stream stream = clientSession.syn(new SynInfo(new Fields(), true), null);
assertThat("onSyn has been called", pushStreamLatch.await(5, TimeUnit.SECONDS), is(true));
Stream pushStream = pushStreamRef.get();
assertThat("main stream and associated stream are the same",stream,sameInstance(pushStream.getAssociatedStream()));
assertThat("main stream and associated stream are the same", stream, sameInstance(pushStream.getAssociatedStream()));
}
@Test
@ -134,10 +140,10 @@ public class PushStreamTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.reply(new ReplyInfo(false));
stream.reply(new ReplyInfo(false), new Callback.Adapter());
try
{
replyBarrier.await(5,TimeUnit.SECONDS);
replyBarrier.await(5, TimeUnit.SECONDS);
return new StreamFrameListener.Adapter()
{
@Override
@ -147,14 +153,14 @@ public class PushStreamTest extends AbstractTest
{
if (dataInfo.isClose())
{
stream.data(new StringDataInfo("close stream",true));
closeBarrier.await(5,TimeUnit.SECONDS);
stream.data(new StringDataInfo("close stream", true));
closeBarrier.await(5, TimeUnit.SECONDS);
}
streamDataSent.countDown();
if (pushStreamDataReceived.getCount() == 2)
{
Stream pushStream = stream.syn(new SynInfo(false)).get();
streamExchanger.exchange(pushStream,5,TimeUnit.SECONDS);
Stream pushStream = stream.push(new PushInfo(new Fields(), false));
streamExchanger.exchange(pushStream, 5, TimeUnit.SECONDS);
}
}
catch (Exception e)
@ -171,7 +177,7 @@ public class PushStreamTest extends AbstractTest
}
}
}),new SessionFrameListener.Adapter()
}), new SessionFrameListener.Adapter()
{
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
@ -183,20 +189,20 @@ public class PushStreamTest extends AbstractTest
public void onData(Stream stream, DataInfo dataInfo)
{
pushStreamDataReceived.countDown();
super.onData(stream,dataInfo);
super.onData(stream, dataInfo);
}
};
}
});
Stream stream = clientSession.syn(new SynInfo(false),new StreamFrameListener.Adapter()
Stream stream = clientSession.syn(new SynInfo(new Fields(), false), new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
{
try
{
replyBarrier.await(5,TimeUnit.SECONDS);
replyBarrier.await(5, TimeUnit.SECONDS);
}
catch (Exception e)
{
@ -209,29 +215,29 @@ public class PushStreamTest extends AbstractTest
{
try
{
closeBarrier.await(5,TimeUnit.SECONDS);
closeBarrier.await(5, TimeUnit.SECONDS);
}
catch (Exception e)
{
exceptionCountDownLatch.countDown();
}
}
}).get();
});
replyBarrier.await(5,TimeUnit.SECONDS);
stream.data(new StringDataInfo("client data",false));
Stream pushStream = streamExchanger.exchange(null,5,TimeUnit.SECONDS);
pushStream.data(new StringDataInfo("first push data frame",false));
replyBarrier.await(5, TimeUnit.SECONDS);
stream.data(new StringDataInfo("client data", false));
Stream pushStream = streamExchanger.exchange(null, 5, TimeUnit.SECONDS);
pushStream.data(new StringDataInfo("first push data frame", false));
// nasty, but less complex than using another cyclicBarrier for example
while (pushStreamDataReceived.getCount() != 1)
Thread.sleep(1);
stream.data(new StringDataInfo("client close",true));
closeBarrier.await(5,TimeUnit.SECONDS);
assertThat("stream is closed",stream.isClosed(),is(true));
pushStream.data(new StringDataInfo("second push data frame while associated stream has been closed already",false));
assertThat("2 pushStream data frames have been received.",pushStreamDataReceived.await(5,TimeUnit.SECONDS),is(true));
assertThat("2 data frames have been sent",streamDataSent.await(5,TimeUnit.SECONDS),is(true));
assertThatNoExceptionOccured(exceptionCountDownLatch);
stream.data(new StringDataInfo("client close", true));
closeBarrier.await(5, TimeUnit.SECONDS);
assertThat("stream is closed", stream.isClosed(), is(true));
pushStream.data(new StringDataInfo("second push data frame while associated stream has been closed already", false));
assertThat("2 pushStream data frames have been received.", pushStreamDataReceived.await(5, TimeUnit.SECONDS), is(true));
assertThat("2 data frames have been sent", streamDataSent.await(5, TimeUnit.SECONDS), is(true));
assertThatNoExceptionOccurred(exceptionCountDownLatch);
}
@Test
@ -244,21 +250,22 @@ public class PushStreamTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.reply(new ReplyInfo(true));
stream.syn(new SynInfo(false),1,TimeUnit.SECONDS,new Promise.Adapter<Stream>()
{
@Override
public void failed(Throwable x)
{
pushStreamFailedLatch.countDown();
}
});
return super.onSyn(stream,synInfo);
stream.reply(new ReplyInfo(true), new Callback.Adapter());
stream.push(new PushInfo(1, TimeUnit.SECONDS, new Fields(), false),
new Promise.Adapter<Stream>()
{
@Override
public void failed(Throwable x)
{
pushStreamFailedLatch.countDown();
}
});
return super.onSyn(stream, synInfo);
}
}),new SessionFrameListener.Adapter());
}), new SessionFrameListener.Adapter());
clientSession.syn(new SynInfo(true),null);
assertThat("pushStream syn has failed",pushStreamFailedLatch.await(5,TimeUnit.SECONDS),is(true));
clientSession.syn(new SynInfo(new Fields(), true), null);
assertThat("pushStream push has failed", pushStreamFailedLatch.await(5, TimeUnit.SECONDS), is(true));
}
@Test
@ -278,11 +285,11 @@ public class PushStreamTest extends AbstractTest
{
try
{
Stream pushStream = stream.syn(new SynInfo(false)).get();
Stream pushStream = stream.push(new PushInfo(new Fields(), false));
stream.reply(new ReplyInfo(true));
// wait until stream is closed
streamClosedLatch.await(5,TimeUnit.SECONDS);
pushStream.data(new BytesDataInfo(transferBytes,true));
streamClosedLatch.await(5, TimeUnit.SECONDS);
pushStream.data(new BytesDataInfo(transferBytes, true), new Callback.Adapter());
return null;
}
catch (Exception e)
@ -291,7 +298,7 @@ public class PushStreamTest extends AbstractTest
throw new IllegalStateException(e);
}
}
}),new SessionFrameListener.Adapter()
}), new SessionFrameListener.Adapter()
{
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
@ -310,7 +317,7 @@ public class PushStreamTest extends AbstractTest
try
{
receivedBytes.flip();
exchanger.exchange(receivedBytes.slice(),5,TimeUnit.SECONDS);
exchanger.exchange(receivedBytes.slice(), 5, TimeUnit.SECONDS);
}
catch (Exception e)
{
@ -322,23 +329,23 @@ public class PushStreamTest extends AbstractTest
}
});
Stream stream = clientSession.syn(new SynInfo(true),new StreamFrameListener.Adapter()
Stream stream = clientSession.syn(new SynInfo(new Fields(), true), new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
{
streamClosedLatch.countDown();
super.onReply(stream,replyInfo);
super.onReply(stream, replyInfo);
}
}).get();
});
ByteBuffer receivedBytes = exchanger.exchange(null,5,TimeUnit.SECONDS);
ByteBuffer receivedBytes = exchanger.exchange(null, 5, TimeUnit.SECONDS);
assertThat("received byte array is the same as transferred byte array",Arrays.equals(transferBytes,receivedBytes.array()),is(true));
assertThat("onReply has been called to close the stream",streamClosedLatch.await(5,TimeUnit.SECONDS),is(true));
assertThat("stream is closed",stream.isClosed(),is(true));
assertThat("all data has been received",allDataReceived.await(20,TimeUnit.SECONDS),is(true));
assertThatNoExceptionOccured(exceptionCountDownLatch);
assertThat("received byte array is the same as transferred byte array", Arrays.equals(transferBytes, receivedBytes.array()), is(true));
assertThat("onReply has been called to close the stream", streamClosedLatch.await(5, TimeUnit.SECONDS), is(true));
assertThat("stream is closed", stream.isClosed(), is(true));
assertThat("all data has been received", allDataReceived.await(20, TimeUnit.SECONDS), is(true));
assertThatNoExceptionOccurred(exceptionCountDownLatch);
}
private byte[] createHugeByteArray(int sizeInBytes)
@ -364,10 +371,11 @@ public class PushStreamTest extends AbstractTest
}
private volatile boolean read = true;
private void testNoMoreFramesAreSentOnPushStreamAfterClientResetsThePushStream(final boolean flowControl) throws Exception, IOException, InterruptedException
private void testNoMoreFramesAreSentOnPushStreamAfterClientResetsThePushStream(final boolean flowControl) throws Exception
{
final short version = SPDY.V3;
final AtomicBoolean unexpectedExceptionOccured = new AtomicBoolean(false);
final AtomicBoolean unexpectedExceptionOccurred = new AtomicBoolean(false);
final CountDownLatch resetReceivedLatch = new CountDownLatch(1);
final CountDownLatch allDataFramesReceivedLatch = new CountDownLatch(1);
final CountDownLatch goAwayReceivedLatch = new CountDownLatch(1);
@ -385,20 +393,28 @@ public class PushStreamTest extends AbstractTest
@Override
public void run()
{
Stream pushStream=null;
Stream pushStream = null;
try
{
stream.reply(new ReplyInfo(false));
pushStream = stream.syn(new SynInfo(false)).get();
resetReceivedLatch.await(5,TimeUnit.SECONDS);
stream.reply(new ReplyInfo(false), new Callback.Adapter());
pushStream = stream.push(new PushInfo(new Fields(), false));
resetReceivedLatch.await(5, TimeUnit.SECONDS);
}
catch (InterruptedException | ExecutionException e)
catch (InterruptedException | ExecutionException | TimeoutException e)
{
e.printStackTrace();
unexpectedExceptionOccured.set(true);
unexpectedExceptionOccurred.set(true);
}
assert pushStream != null;
try
{
pushStream.data(new BytesDataInfo(transferBytes, true));
stream.data(new StringDataInfo("close", true));
}
catch (InterruptedException | ExecutionException | TimeoutException e)
{
LOG.debug(e.getMessage());
}
pushStream.data(new BytesDataInfo(transferBytes,true));
stream.data(new StringDataInfo("close",true));
}
}).start();
return null;
@ -411,7 +427,7 @@ public class PushStreamTest extends AbstractTest
}
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
public void onGoAway(Session session, GoAwayReceivedInfo goAwayInfo)
{
goAwayReceivedLatch.countDown();
}
@ -420,9 +436,9 @@ public class PushStreamTest extends AbstractTest
final SocketChannel channel = SocketChannel.open(serverAddress);
final Generator generator = new Generator(new MappedByteBufferPool(), new StandardCompressionFactory.StandardCompressor());
int streamId = 1;
ByteBuffer writeBuffer = generator.control(new SynStreamFrame(version,(byte)0,streamId,0,(byte)0,(short)0,new Fields()));
ByteBuffer writeBuffer = generator.control(new SynStreamFrame(version, (byte)0, streamId, 0, (byte)0, (short)0, new Fields()));
channel.write(writeBuffer);
assertThat("writeBuffer is fully written",writeBuffer.hasRemaining(), is(false));
assertThat("writeBuffer is fully written", writeBuffer.hasRemaining(), is(false));
final Parser parser = new Parser(new StandardCompressionFactory.StandardDecompressor());
parser.addListener(new Listener.Adapter()
@ -432,9 +448,10 @@ public class PushStreamTest extends AbstractTest
@Override
public void onControlFrame(ControlFrame frame)
{
if(frame instanceof SynStreamFrame){
if (frame instanceof SynStreamFrame)
{
int pushStreamId = ((SynStreamFrame)frame).getStreamId();
ByteBuffer writeBuffer = generator.control(new RstStreamFrame(version,pushStreamId,StreamStatus.CANCEL_STREAM.getCode(version)));
ByteBuffer writeBuffer = generator.control(new RstStreamFrame(version, pushStreamId, StreamStatus.CANCEL_STREAM.getCode(version)));
try
{
channel.write(writeBuffer);
@ -442,7 +459,7 @@ public class PushStreamTest extends AbstractTest
catch (IOException e)
{
e.printStackTrace();
unexpectedExceptionOccured.set(true);
unexpectedExceptionOccurred.set(true);
}
}
}
@ -450,15 +467,16 @@ public class PushStreamTest extends AbstractTest
@Override
public void onDataFrame(DataFrame frame, ByteBuffer data)
{
if(frame.getStreamId() == 2)
if (frame.getStreamId() == 2)
bytesRead = bytesRead + frame.getLength();
if(bytesRead == dataSizeInBytes){
if (bytesRead == dataSizeInBytes)
{
allDataFramesReceivedLatch.countDown();
return;
}
if (flowControl)
{
ByteBuffer writeBuffer = generator.control(new WindowUpdateFrame(version,frame.getStreamId(),frame.getLength()));
ByteBuffer writeBuffer = generator.control(new WindowUpdateFrame(version, frame.getStreamId(), frame.getLength()));
try
{
channel.write(writeBuffer);
@ -466,7 +484,7 @@ public class PushStreamTest extends AbstractTest
catch (IOException e)
{
e.printStackTrace();
unexpectedExceptionOccured.set(true);
unexpectedExceptionOccurred.set(true);
}
}
}
@ -477,7 +495,7 @@ public class PushStreamTest extends AbstractTest
@Override
public void run()
{
ByteBuffer readBuffer = ByteBuffer.allocate(dataSizeInBytes*2);
ByteBuffer readBuffer = ByteBuffer.allocate(dataSizeInBytes * 2);
while (read)
{
try
@ -487,7 +505,7 @@ public class PushStreamTest extends AbstractTest
catch (IOException e)
{
e.printStackTrace();
unexpectedExceptionOccured.set(true);
unexpectedExceptionOccurred.set(true);
}
readBuffer.flip();
parser.parse(readBuffer);
@ -499,15 +517,15 @@ public class PushStreamTest extends AbstractTest
reader.start();
read = false;
assertThat("no unexpected exceptions occured", unexpectedExceptionOccured.get(), is(false));
assertThat("not all dataframes have been received as the pushstream has been reset by the client.",allDataFramesReceivedLatch.await(streamId,TimeUnit.SECONDS),is(false));
assertThat("no unexpected exceptions occurred", unexpectedExceptionOccurred.get(), is(false));
assertThat("not all dataframes have been received as the pushstream has been reset by the client.", allDataFramesReceivedLatch.await(streamId, TimeUnit.SECONDS), is(false));
ByteBuffer buffer = generator.control(new GoAwayFrame(version, streamId, SessionStatus.OK.getCode()));
channel.write(buffer);
Assert.assertThat(buffer.hasRemaining(), is(false));
assertThat("GoAway frame is received by server", goAwayReceivedLatch.await(5,TimeUnit.SECONDS), is(true));
assertThat("GoAway frame is received by server", goAwayReceivedLatch.await(5, TimeUnit.SECONDS), is(true));
channel.shutdownOutput();
channel.close();
}
@ -522,42 +540,42 @@ public class PushStreamTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.syn(new SynInfo(false));
stream.push(new PushInfo(new Fields(), false), new Promise.Adapter<Stream>());
return null;
}
}),new SessionFrameListener.Adapter()
}), new SessionFrameListener.Adapter()
{
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
assertStreamIdIsEven(stream);
pushStreamIdIsEvenLatch.countDown();
return super.onSyn(stream,synInfo);
return super.onSyn(stream, synInfo);
}
});
Stream stream = clientSession.syn(new SynInfo(false),null).get();
Stream stream2 = clientSession.syn(new SynInfo(false),null).get();
Stream stream3 = clientSession.syn(new SynInfo(false),null).get();
Stream stream = clientSession.syn(new SynInfo(new Fields(), false), null);
Stream stream2 = clientSession.syn(new SynInfo(new Fields(), false), null);
Stream stream3 = clientSession.syn(new SynInfo(new Fields(), false), null);
assertStreamIdIsOdd(stream);
assertStreamIdIsOdd(stream2);
assertStreamIdIsOdd(stream3);
assertThat("all pushStreams had even ids",pushStreamIdIsEvenLatch.await(5,TimeUnit.SECONDS),is(true));
assertThat("all pushStreams had even ids", pushStreamIdIsEvenLatch.await(5, TimeUnit.SECONDS), is(true));
}
private void assertStreamIdIsEven(Stream stream)
{
assertThat("streamId is odd",stream.getId() % 2,is(0));
assertThat("streamId is odd", stream.getId() % 2, is(0));
}
private void assertStreamIdIsOdd(Stream stream)
{
assertThat("streamId is odd",stream.getId() % 2,is(1));
assertThat("streamId is odd", stream.getId() % 2, is(1));
}
private void assertThatNoExceptionOccured(final CountDownLatch exceptionCountDownLatch) throws InterruptedException
private void assertThatNoExceptionOccurred(final CountDownLatch exceptionCountDownLatch) throws InterruptedException
{
assertThat("No exception occured",exceptionCountDownLatch.await(1,TimeUnit.SECONDS),is(false));
assertThat("No exception occurred", exceptionCountDownLatch.await(1, TimeUnit.SECONDS), is(false));
}
}

View File

@ -33,6 +33,8 @@ import org.eclipse.jetty.spdy.api.StringDataInfo;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.FutureCallback;
import org.junit.Test;
import static org.hamcrest.Matchers.is;
@ -46,12 +48,12 @@ public class ResetStreamTest extends AbstractTest
@Test
public void testResetStreamIsRemoved() throws Exception
{
Session session = startClient(startServer(new ServerSessionFrameListener.Adapter()/*TODO, true*/),null);
Session session = startClient(startServer(new ServerSessionFrameListener.Adapter()/*TODO, true*/), null);
Stream stream = session.syn(new SynInfo(false),null).get(5,TimeUnit.SECONDS);
session.rst(new RstInfo(stream.getId(),StreamStatus.CANCEL_STREAM)).get(5,TimeUnit.SECONDS);
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), false, (byte)0), null);
session.rst(new RstInfo(5, TimeUnit.SECONDS, stream.getId(), StreamStatus.CANCEL_STREAM));
assertEquals("session expected to contain 0 streams",0,session.getStreams().size());
assertEquals("session expected to contain 0 streams", 0, session.getStreams().size());
}
@Test
@ -67,11 +69,11 @@ public class ResetStreamTest extends AbstractTest
{
Session serverSession = stream.getSession();
serverSessionRef.set(serverSession);
serverSession.rst(new RstInfo(stream.getId(),StreamStatus.REFUSED_STREAM));
serverSession.rst(new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM), new FutureCallback());
synLatch.countDown();
return null;
}
}),new SessionFrameListener.Adapter()
}), new SessionFrameListener.Adapter()
{
@Override
public void onRst(Session session, RstInfo rstInfo)
@ -80,17 +82,17 @@ public class ResetStreamTest extends AbstractTest
}
});
Stream stream = clientSession.syn(new SynInfo(false),null).get(5,TimeUnit.SECONDS);
Stream stream = clientSession.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), false, (byte)0), null);
assertTrue("syncLatch didn't count down",synLatch.await(5,TimeUnit.SECONDS));
assertTrue("syncLatch didn't count down", synLatch.await(5, TimeUnit.SECONDS));
Session serverSession = serverSessionRef.get();
assertEquals("serverSession expected to contain 0 streams",0,serverSession.getStreams().size());
assertEquals("serverSession expected to contain 0 streams", 0, serverSession.getStreams().size());
assertTrue("rstLatch didn't count down",rstLatch.await(5,TimeUnit.SECONDS));
assertTrue("rstLatch didn't count down", rstLatch.await(5, TimeUnit.SECONDS));
// Need to sleep a while to give the chance to the implementation to remove the stream
TimeUnit.SECONDS.sleep(1);
assertTrue("stream is expected to be reset",stream.isReset());
assertEquals("clientSession expected to contain 0 streams",0,clientSession.getStreams().size());
assertTrue("stream is expected to be reset", stream.isReset());
assertEquals("clientSession expected to contain 0 streams", 0, clientSession.getStreams().size());
}
@Test
@ -107,8 +109,8 @@ public class ResetStreamTest extends AbstractTest
try
{
// Refuse the stream, we must ignore data frames
assertTrue(synLatch.await(5,TimeUnit.SECONDS));
stream.getSession().rst(new RstInfo(stream.getId(),StreamStatus.REFUSED_STREAM));
assertTrue(synLatch.await(5, TimeUnit.SECONDS));
stream.getSession().rst(new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM), new FutureCallback());
return new StreamFrameListener.Adapter()
{
@Override
@ -124,7 +126,7 @@ public class ResetStreamTest extends AbstractTest
return null;
}
}
}),new SessionFrameListener.Adapter()
}), new SessionFrameListener.Adapter()
{
@Override
public void onRst(Session session, RstInfo rstInfo)
@ -133,8 +135,8 @@ public class ResetStreamTest extends AbstractTest
}
});
Stream stream = session.syn(new SynInfo(false),null).get(5,TimeUnit.SECONDS);
stream.data(new StringDataInfo("data",true),5,TimeUnit.SECONDS,new Callback.Adapter()
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), false, (byte)0), null);
stream.data(new StringDataInfo(5, TimeUnit.SECONDS, "data", true), new Callback.Adapter()
{
@Override
public void succeeded()
@ -143,9 +145,9 @@ public class ResetStreamTest extends AbstractTest
}
});
assertTrue("rstLatch didn't count down",rstLatch.await(5,TimeUnit.SECONDS));
assertTrue("stream is expected to be reset",stream.isReset());
assertFalse("dataLatch shouln't be count down",dataLatch.await(1,TimeUnit.SECONDS));
assertTrue("rstLatch didn't count down", rstLatch.await(5, TimeUnit.SECONDS));
assertTrue("stream is expected to be reset", stream.isReset());
assertFalse("dataLatch shouldn't be count down", dataLatch.await(1, TimeUnit.SECONDS));
}
@Test
@ -167,11 +169,11 @@ public class ResetStreamTest extends AbstractTest
public void onData(Stream stream, DataInfo dataInfo)
{
dataLatch.countDown();
stream.getSession().rst(new RstInfo(stream.getId(),StreamStatus.REFUSED_STREAM));
stream.getSession().rst(new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM), new FutureCallback());
}
};
}
}),new SessionFrameListener.Adapter()
}), new SessionFrameListener.Adapter()
{
@Override
public void onRst(Session session, RstInfo rstInfo)
@ -180,11 +182,11 @@ public class ResetStreamTest extends AbstractTest
}
});
Stream stream = session.syn(new SynInfo(false),null).get(5,TimeUnit.SECONDS);
assertThat("syn is received by server", synLatch.await(5,TimeUnit.SECONDS),is(true));
stream.data(new StringDataInfo("data",false),5,TimeUnit.SECONDS,new Callback.Adapter());
assertThat("stream is reset",rstLatch.await(5,TimeUnit.SECONDS),is(true));
stream.data(new StringDataInfo("2nd dataframe",false),5L,TimeUnit.SECONDS,new Callback.Adapter()
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), false, (byte)0), null);
assertThat("push is received by server", synLatch.await(5, TimeUnit.SECONDS), is(true));
stream.data(new StringDataInfo(5, TimeUnit.SECONDS, "data", false), new Callback.Adapter());
assertThat("stream is reset", rstLatch.await(5, TimeUnit.SECONDS), is(true));
stream.data(new StringDataInfo(5, TimeUnit.SECONDS, "2nd dataframe", false), new Callback.Adapter()
{
@Override
public void failed(Throwable x)
@ -193,8 +195,8 @@ public class ResetStreamTest extends AbstractTest
}
});
assertThat("2nd data call failed",failLatch.await(5,TimeUnit.SECONDS),is(true));
assertThat("stream is reset",stream.isReset(),is(true));
assertThat("2nd data call failed", failLatch.await(5, TimeUnit.SECONDS), is(true));
assertThat("stream is reset", stream.isReset(), is(true));
}
// TODO: If server already received 2nd dataframe after it rst, it should ignore it. Not easy to do.

View File

@ -23,6 +23,7 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.GoAwayReceivedInfo;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.junit.Assert;
@ -37,7 +38,7 @@ public class SPDYClientFactoryTest extends AbstractTest
startClient(startServer(new ServerSessionFrameListener.Adapter()
{
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
public void onGoAway(Session session, GoAwayReceivedInfo goAwayReceivedInfo)
{
latch.countDown();
}
@ -58,7 +59,7 @@ public class SPDYClientFactoryTest extends AbstractTest
{
Session session = startClient(startServer(null), null);
session.goAway().get(5, TimeUnit.SECONDS);
session.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
// Sleep a while to allow the factory to remove the session
// since it is done asynchronously by the selector thread

View File

@ -23,6 +23,7 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.GoAwayReceivedInfo;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.SessionFrameListener;
import org.junit.Assert;
@ -37,7 +38,7 @@ public class SPDYServerConnectorTest extends AbstractTest
startClient(startServer(null), new SessionFrameListener.Adapter()
{
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
public void onGoAway(Session session, GoAwayReceivedInfo goAwayReceivedInfo)
{
latch.countDown();
}
@ -58,7 +59,7 @@ public class SPDYServerConnectorTest extends AbstractTest
{
Session session = startClient(startServer(null), null);
session.goAway().get(5, TimeUnit.SECONDS);
session.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
// Sleep a while to allow the connector to remove the session
// since it is done asynchronously by the selector thread

View File

@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.npn.NextProtoNego;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.eclipse.jetty.spdy.client.SPDYClient;
@ -83,6 +84,6 @@ public class SSLEngineLeakTest extends AbstractTest
private void avoidStackLocalVariables() throws Exception
{
Session session = startClient(startServer(null), null);
session.goAway().get(5, TimeUnit.SECONDS);
session.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
}
}

View File

@ -31,6 +31,7 @@ import org.eclipse.jetty.spdy.api.SessionFrameListener;
import org.eclipse.jetty.spdy.api.Settings;
import org.eclipse.jetty.spdy.api.SettingsInfo;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.eclipse.jetty.util.FutureCallback;
import org.junit.Assert;
import org.junit.Test;
@ -106,7 +107,7 @@ public class SettingsTest extends AbstractTest
@Override
public void onConnect(Session session)
{
session.settings(serverSettingsInfo);
session.settings(serverSettingsInfo, new FutureCallback());
}
};

View File

@ -57,14 +57,14 @@ public class SynDataReplyDataLoadTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
stream.reply(new ReplyInfo(synInfo.getHeaders(), false));
stream.reply(new ReplyInfo(synInfo.getHeaders(), false), new Callback.Adapter());
return new StreamFrameListener.Adapter()
{
@Override
public void onData(Stream stream, DataInfo dataInfo)
{
ByteBuffer buffer = dataInfo.asByteBuffer(true);
stream.data(new ByteBufferDataInfo(buffer, dataInfo.isClose()));
stream.data(new ByteBufferDataInfo(buffer, dataInfo.isClose()), new Callback.Adapter());
}
};
}
@ -173,12 +173,13 @@ public class SynDataReplyDataLoadTest extends AbstractTest
latch.countDown();
}
}
}, 0, TimeUnit.SECONDS, new Promise.Adapter<Stream>()
{
}, new Promise.Adapter<Stream>()
{
@Override
public void succeeded(Stream stream)
{
stream.data(new StringDataInfo("data_" + stream.getId(), true), 0, TimeUnit.SECONDS, new Callback.Adapter());
stream.data(new StringDataInfo("data_" + stream.getId(), true),
new Callback.Adapter());
}
});
}
@ -195,7 +196,8 @@ public class SynDataReplyDataLoadTest extends AbstractTest
final AtomicInteger count = new AtomicInteger(2);
final int index = i;
counter.put(index, index);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, headers, false, (byte)0),
new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
@ -216,8 +218,8 @@ public class SynDataReplyDataLoadTest extends AbstractTest
latch.countDown();
}
}
}).get(5, TimeUnit.SECONDS);
stream.data(new StringDataInfo("data_" + stream.getId(), true)).get(5, TimeUnit.SECONDS);
});
stream.data(new StringDataInfo(5, TimeUnit.SECONDS, "data_" + stream.getId(), true));
}
Assert.assertTrue(latch.await(iterations, TimeUnit.SECONDS));
Assert.assertTrue(counter.toString(), counter.isEmpty());

View File

@ -64,7 +64,7 @@ public class SynReplyTest extends AbstractTest
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
Assert.assertTrue(stream.isHalfClosed());
stream.reply(new ReplyInfo(new Fields(), true));
stream.reply(new ReplyInfo(new Fields(), true), new Callback.Adapter());
synLatch.countDown();
return null;
}
@ -94,7 +94,8 @@ public class SynReplyTest extends AbstractTest
});
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(new Fields(), true), new StreamFrameListener.Adapter()
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), true, (byte)0),
new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
@ -102,7 +103,7 @@ public class SynReplyTest extends AbstractTest
Assert.assertTrue(stream.isClosed());
replyLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
});
Assert.assertTrue(synLatch.await(5, TimeUnit.SECONDS));
@ -147,7 +148,7 @@ public class SynReplyTest extends AbstractTest
Assert.assertTrue(stream.isHalfClosed());
Assert.assertFalse(stream.isClosed());
stream.reply(new ReplyInfo(true));
stream.reply(new ReplyInfo(true), new Callback.Adapter());
Assert.assertTrue(stream.isClosed());
dataLatch.countDown();
}
@ -168,14 +169,15 @@ public class SynReplyTest extends AbstractTest
});
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(false), new StreamFrameListener.Adapter()
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, new Fields(), false, (byte)0),
new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
{
replyLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
});
stream.data(new BytesDataInfo(dataBytes, true));
Assert.assertTrue(synLatch.await(5, TimeUnit.SECONDS));
@ -199,13 +201,13 @@ public class SynReplyTest extends AbstractTest
{
Assert.assertTrue(stream.isHalfClosed());
stream.reply(new ReplyInfo(false));
stream.data(new StringDataInfo(data1, false), 5, TimeUnit.SECONDS, new Callback.Adapter()
stream.reply(new ReplyInfo(false), new Callback.Adapter());
stream.data(new StringDataInfo(5, TimeUnit.SECONDS, data1, false), new Callback.Adapter()
{
@Override
public void succeeded()
{
stream.data(new StringDataInfo(data2, true));
stream.data(new StringDataInfo(data2, true), new Adapter());
}
});
@ -216,7 +218,7 @@ public class SynReplyTest extends AbstractTest
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch1 = new CountDownLatch(1);
final CountDownLatch dataLatch2 = new CountDownLatch(1);
session.syn(new SynInfo(true), new StreamFrameListener.Adapter()
session.syn(new SynInfo(new Fields(), true), new StreamFrameListener.Adapter()
{
private AtomicInteger dataCount = new AtomicInteger();
@ -264,7 +266,7 @@ public class SynReplyTest extends AbstractTest
@Override
public void onConnect(Session session)
{
session.syn(new SynInfo(false), new StreamFrameListener.Adapter()
session.syn(new SynInfo(new Fields(), false), new StreamFrameListener.Adapter()
{
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
@ -279,12 +281,12 @@ public class SynReplyTest extends AbstractTest
Assert.assertEquals(clientData, data);
clientDataLatch.countDown();
}
}, 0, TimeUnit.MILLISECONDS, new Promise.Adapter<Stream>()
}, new Promise.Adapter<Stream>()
{
@Override
public void succeeded(Stream stream)
{
stream.data(new StringDataInfo(serverData, true));
stream.data(new StringDataInfo(serverData, true), new Callback.Adapter());
}
});
}
@ -299,8 +301,8 @@ public class SynReplyTest extends AbstractTest
{
Assert.assertEquals(0, stream.getId() % 2);
stream.reply(new ReplyInfo(false));
stream.data(new StringDataInfo(clientData, true));
stream.reply(new ReplyInfo(false), new Callback.Adapter());
stream.data(new StringDataInfo(clientData, true), new Callback.Adapter());
synLatch.countDown();
return new StreamFrameListener.Adapter()
@ -336,8 +338,8 @@ public class SynReplyTest extends AbstractTest
{
Assert.assertTrue(stream.isHalfClosed());
stream.reply(new ReplyInfo(false));
stream.data(new StringDataInfo(data, true));
stream.reply(new ReplyInfo(false), new Callback.Adapter());
stream.data(new StringDataInfo(data, true), new Callback.Adapter());
return null;
}
@ -364,8 +366,8 @@ public class SynReplyTest extends AbstractTest
dataLatch.countDown();
}
};
session.syn(new SynInfo(true), clientStreamFrameListener);
session.syn(new SynInfo(true), clientStreamFrameListener);
session.syn(new SynInfo(new Fields(), true), clientStreamFrameListener);
session.syn(new SynInfo(new Fields(), true), clientStreamFrameListener);
Assert.assertTrue(replyLatch.await(5, TimeUnit.SECONDS));
Assert.assertTrue(dataLatch.await(5, TimeUnit.SECONDS));

View File

@ -18,71 +18,68 @@
package org.eclipse.jetty.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.HashSet;
import java.util.ListIterator;
import java.util.Random;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jetty.toolchain.test.AdvancedRunner;
import org.eclipse.jetty.toolchain.test.annotation.Slow;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AdvancedRunner.class)
public class BlockingArrayQueueTest
{
@Test
public void testWrap() throws Exception
{
BlockingArrayQueue<String> queue = new BlockingArrayQueue<String>(3);
BlockingArrayQueue<String> queue = new BlockingArrayQueue<>(3);
assertEquals(0,queue.size());
Assert.assertEquals(0, queue.size());
for (int i=0;i<3;i++)
for (int i=0;i<queue.getMaxCapacity();i++)
{
queue.offer("one");
assertEquals(1,queue.size());
Assert.assertEquals(1, queue.size());
queue.offer("two");
assertEquals(2,queue.size());
Assert.assertEquals(2, queue.size());
queue.offer("three");
assertEquals(3,queue.size());
Assert.assertEquals(3, queue.size());
assertEquals("one",queue.get(0));
assertEquals("two",queue.get(1));
assertEquals("three",queue.get(2));
Assert.assertEquals("one", queue.get(0));
Assert.assertEquals("two", queue.get(1));
Assert.assertEquals("three", queue.get(2));
assertEquals("[one, two, three]",queue.toString());
Assert.assertEquals("[one, two, three]", queue.toString());
assertEquals("one",queue.poll());
assertEquals(2,queue.size());
Assert.assertEquals("one", queue.poll());
Assert.assertEquals(2, queue.size());
assertEquals("two",queue.poll());
assertEquals(1,queue.size());
Assert.assertEquals("two", queue.poll());
Assert.assertEquals(1, queue.size());
assertEquals("three",queue.poll());
assertEquals(0,queue.size());
Assert.assertEquals("three", queue.poll());
Assert.assertEquals(0, queue.size());
queue.offer("xxx");
assertEquals(1,queue.size());
assertEquals("xxx",queue.poll());
assertEquals(0,queue.size());
Assert.assertEquals(1, queue.size());
Assert.assertEquals("xxx", queue.poll());
Assert.assertEquals(0, queue.size());
}
}
@Test
public void testRemove() throws Exception
{
BlockingArrayQueue<String> queue = new BlockingArrayQueue<String>(3,3);
BlockingArrayQueue<String> queue = new BlockingArrayQueue<>(3,3);
queue.add("0");
queue.add("x");
@ -96,23 +93,36 @@ public class BlockingArrayQueueTest
}
for (int i=0;i<99;i++)
assertEquals(i+"!",queue.get(i));
Assert.assertEquals(i + "!", queue.get(i));
}
@Test
public void testLimit() throws Exception
{
BlockingArrayQueue<String> queue = new BlockingArrayQueue<>(1,0,1);
String element = "0";
Assert.assertTrue(queue.add(element));
Assert.assertFalse(queue.offer("1"));
Assert.assertEquals(element, queue.poll());
Assert.assertTrue(queue.add(element));
}
@Test
public void testGrow() throws Exception
{
BlockingArrayQueue<String> queue = new BlockingArrayQueue<String>(3,2);
assertEquals(3,queue.getCapacity());
BlockingArrayQueue<String> queue = new BlockingArrayQueue<>(3,2);
Assert.assertEquals(3, queue.getCapacity());
queue.add("a");
queue.add("a");
assertEquals(2,queue.size());
assertEquals(3,queue.getCapacity());
Assert.assertEquals(2, queue.size());
Assert.assertEquals(3, queue.getCapacity());
queue.add("a");
queue.add("a");
assertEquals(4,queue.size());
assertEquals(5,queue.getCapacity());
Assert.assertEquals(4, queue.size());
Assert.assertEquals(5, queue.getCapacity());
int s=5;
int c=5;
@ -120,25 +130,25 @@ public class BlockingArrayQueueTest
for (int t=0;t<100;t++)
{
assertEquals(s,queue.size());
assertEquals(c,queue.getCapacity());
Assert.assertEquals(s, queue.size());
Assert.assertEquals(c, queue.getCapacity());
for (int i=queue.size();i-->0;)
queue.poll();
assertEquals(0,queue.size());
assertEquals(c,queue.getCapacity());
Assert.assertEquals(0, queue.size());
Assert.assertEquals(c, queue.getCapacity());
for (int i=queue.getCapacity();i-->0;)
queue.add("a");
queue.add("a");
assertEquals(s+1,queue.size());
assertEquals(c+2,queue.getCapacity());
Assert.assertEquals(s + 1, queue.size());
Assert.assertEquals(c + 2, queue.getCapacity());
queue.poll();
queue.add("a");
queue.add("a");
assertEquals(s+2,queue.size());
assertEquals(c+2,queue.getCapacity());
Assert.assertEquals(s + 2, queue.size());
Assert.assertEquals(c + 2, queue.getCapacity());
s+=2;
c+=2;
@ -151,7 +161,7 @@ public class BlockingArrayQueueTest
{
final String[] data=new String[4];
final BlockingArrayQueue<String> queue = new BlockingArrayQueue<String>();
final BlockingArrayQueue<String> queue = new BlockingArrayQueue<>();
Thread thread = new Thread()
{
@ -168,8 +178,8 @@ public class BlockingArrayQueueTest
}
catch(Exception e)
{
assertTrue(false);
e.printStackTrace();
Assert.fail();
}
}
};
@ -183,15 +193,12 @@ public class BlockingArrayQueueTest
queue.offer("two");
thread.join();
assertEquals("zero",data[0]);
assertEquals("one",data[1]);
assertEquals("two",data[2]);
assertEquals(null,data[3]);
Assert.assertEquals("zero", data[0]);
Assert.assertEquals("one", data[1]);
Assert.assertEquals("two", data[2]);
Assert.assertEquals(null, data[3]);
}
volatile boolean _running;
@Test
@Slow
public void testConcurrentAccess() throws Exception
@ -199,19 +206,17 @@ public class BlockingArrayQueueTest
final int THREADS=50;
final int LOOPS=1000;
final BlockingArrayQueue<Integer> queue = new BlockingArrayQueue<Integer>(1+THREADS*LOOPS);
final BlockingArrayQueue<Integer> queue = new BlockingArrayQueue<>(1+THREADS*LOOPS);
final ConcurrentLinkedQueue<Integer> produced=new ConcurrentLinkedQueue<Integer>();
final ConcurrentLinkedQueue<Integer> consumed=new ConcurrentLinkedQueue<Integer>();
final ConcurrentLinkedQueue<Integer> produced=new ConcurrentLinkedQueue<>();
final ConcurrentLinkedQueue<Integer> consumed=new ConcurrentLinkedQueue<>();
_running=true;
final AtomicBoolean running = new AtomicBoolean(true);
// start consumers
final CyclicBarrier barrier0 = new CyclicBarrier(THREADS+1);
for (int i=0;i<THREADS;i++)
{
final Integer id = new Integer(i);
new Thread()
{
@Override
@ -222,7 +227,7 @@ public class BlockingArrayQueueTest
setPriority(getPriority()-1);
try
{
while(_running)
while(running.get())
{
int r=1+random.nextInt(10);
if (r%2==0)
@ -267,7 +272,7 @@ public class BlockingArrayQueueTest
final CyclicBarrier barrier1 = new CyclicBarrier(THREADS+1);
for (int i=0;i<THREADS;i++)
{
final Integer id = new Integer(i);
final int id = i;
new Thread()
{
@Override
@ -278,7 +283,7 @@ public class BlockingArrayQueueTest
{
for (int j=0;j<LOOPS;j++)
{
Integer msg = new Integer(random.nextInt());
Integer msg = random.nextInt();
produced.add(msg);
if (!queue.offer(msg))
throw new Exception(id+" FULL! "+queue.size());
@ -313,12 +318,178 @@ public class BlockingArrayQueueTest
Thread.sleep(500);
size=queue.size();
}
_running=false;
running.set(false);
barrier0.await();
HashSet<Integer> prodSet = new HashSet<Integer>(produced);
HashSet<Integer> consSet = new HashSet<Integer>(consumed);
HashSet<Integer> prodSet = new HashSet<>(produced);
HashSet<Integer> consSet = new HashSet<>(consumed);
assertEquals(prodSet,consSet);
Assert.assertEquals(prodSet, consSet);
}
@Test
public void testRemoveObjectFromEmptyQueue()
{
BlockingArrayQueue<String> queue = new BlockingArrayQueue<>(4,0,4);
Assert.assertFalse(queue.remove("SOMETHING"));
}
@Test
public void testRemoveObjectWithWrappedTail() throws Exception
{
BlockingArrayQueue<String> queue = new BlockingArrayQueue<>(6);
// Wrap the tail
for (int i = 0; i < queue.getMaxCapacity(); ++i)
queue.offer("" + i);
// Advance the head
queue.poll();
// Remove from the middle
Assert.assertTrue(queue.remove("2"));
// Advance the tail
Assert.assertTrue(queue.offer("A"));
Assert.assertTrue(queue.offer("B"));
queue.poll();
// Remove from the middle
Assert.assertTrue(queue.remove("3"));
}
@Test
public void testRemoveObject() throws Exception
{
BlockingArrayQueue<String> queue = new BlockingArrayQueue<>(4,0,4);
String element1 = "A";
Assert.assertTrue(queue.offer(element1));
Assert.assertTrue(queue.remove(element1));
for (int i = 0; i < queue.getMaxCapacity() - 1; ++i)
{
queue.offer("" + i);
queue.poll();
}
String element2 = "B";
Assert.assertTrue(queue.offer(element2));
Assert.assertTrue(queue.offer(element1));
Assert.assertTrue(queue.remove(element1));
Assert.assertFalse(queue.remove("NOT_PRESENT"));
Assert.assertTrue(queue.remove(element2));
Assert.assertFalse(queue.remove("NOT_PRESENT"));
queue.clear();
for (int i = 0; i < queue.getMaxCapacity(); ++i)
queue.offer("" + i);
Assert.assertTrue(queue.remove("" + (queue.getMaxCapacity() - 1)));
}
@Test
public void testRemoveWithMaxCapacityOne() throws Exception
{
BlockingArrayQueue<String> queue = new BlockingArrayQueue<>(1);
String element = "A";
Assert.assertTrue(queue.offer(element));
Assert.assertTrue(queue.remove(element));
Assert.assertTrue(queue.offer(element));
Assert.assertEquals(element, queue.remove(0));
}
@Test
public void testIteratorWithModification() throws Exception
{
BlockingArrayQueue<String> queue = new BlockingArrayQueue<>(4,0,4);
int count = queue.getMaxCapacity() - 1;
for (int i = 0; i < count; ++i)
queue.offer("" + i);
int sum = 0;
for (String element : queue)
{
++sum;
// Concurrent modification, must not change the iterator
queue.remove(element);
}
Assert.assertEquals(count, sum);
Assert.assertTrue(queue.isEmpty());
}
@Test
public void testListIterator() throws Exception
{
BlockingArrayQueue<String> queue = new BlockingArrayQueue<>(4,0,4);
String element1 = "A";
String element2 = "B";
queue.offer(element1);
queue.offer(element2);
ListIterator<String> iterator = queue.listIterator();
Assert.assertTrue(iterator.hasNext());
Assert.assertFalse(iterator.hasPrevious());
String element = iterator.next();
Assert.assertEquals(element1, element);
Assert.assertTrue(iterator.hasNext());
Assert.assertTrue(iterator.hasPrevious());
element = iterator.next();
Assert.assertEquals(element2, element);
Assert.assertFalse(iterator.hasNext());
Assert.assertTrue(iterator.hasPrevious());
element = iterator.previous();
Assert.assertEquals(element2, element);
Assert.assertTrue(iterator.hasNext());
Assert.assertTrue(iterator.hasPrevious());
element = iterator.previous();
Assert.assertEquals(element1, element);
Assert.assertTrue(iterator.hasNext());
Assert.assertFalse(iterator.hasPrevious());
}
@Test
public void testListIteratorWithWrappedHead() throws Exception
{
BlockingArrayQueue<String> queue = new BlockingArrayQueue<>(4,0,4);
// This sequence of offers and polls wraps the head around the array
queue.offer("0");
queue.offer("1");
queue.offer("2");
queue.offer("3");
queue.poll();
queue.poll();
String element1 = queue.get(0);
String element2 = queue.get(1);
ListIterator<String> iterator = queue.listIterator();
Assert.assertTrue(iterator.hasNext());
Assert.assertFalse(iterator.hasPrevious());
String element = iterator.next();
Assert.assertEquals(element1, element);
Assert.assertTrue(iterator.hasNext());
Assert.assertTrue(iterator.hasPrevious());
element = iterator.next();
Assert.assertEquals(element2, element);
Assert.assertFalse(iterator.hasNext());
Assert.assertTrue(iterator.hasPrevious());
element = iterator.previous();
Assert.assertEquals(element2, element);
Assert.assertTrue(iterator.hasNext());
Assert.assertTrue(iterator.hasPrevious());
element = iterator.previous();
Assert.assertEquals(element1, element);
Assert.assertTrue(iterator.hasNext());
Assert.assertFalse(iterator.hasPrevious());
}
}

View File

@ -41,6 +41,7 @@ public class LocalWebSocketConnection implements WebSocketConnection, LogicalCon
private WebSocketPolicy policy = WebSocketPolicy.newServerPolicy();
private boolean open = false;
private IncomingFrames incoming;
private IOState ioState = new IOState();
public LocalWebSocketConnection()
{
@ -83,8 +84,7 @@ public class LocalWebSocketConnection implements WebSocketConnection, LogicalCon
@Override
public IOState getIOState()
{
// TODO Auto-generated method stub
return null;
return ioState;
}
@Override

View File

@ -25,13 +25,16 @@ import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.toolchain.test.AdvancedRunner;
import org.eclipse.jetty.util.Utf8Appendable.NotUtf8Exception;
import org.eclipse.jetty.util.Utf8StringBuilder;
import org.eclipse.jetty.util.log.StdErrLog;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.Generator;
import org.eclipse.jetty.websocket.common.OpCode;
import org.eclipse.jetty.websocket.common.Parser;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.server.blockhead.BlockheadClient;
import org.eclipse.jetty.websocket.server.helper.IncomingFramesCapture;
@ -42,12 +45,14 @@ import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Test various <a href="http://tools.ietf.org/html/rfc6455">RFC 6455</a> specified requirements placed on {@link WebSocketServlet}
* <p>
* This test serves a different purpose than than the {@link WebSocketMessageRFC6455Test}, and {@link WebSocketParserRFC6455Test} tests.
*/
@RunWith(AdvancedRunner.class)
public class WebSocketServletRFCTest
{
private static Generator generator = new UnitGenerator();
@ -66,6 +71,12 @@ public class WebSocketServletRFCTest
server.stop();
}
private void enableStacks(Class<?> clazz, boolean enabled)
{
StdErrLog log = StdErrLog.getLogger(clazz);
log.setHideStacks(!enabled);
}
/**
* Test that aggregation of binary frames into a single message occurs
*/
@ -324,6 +335,9 @@ public class WebSocketServletRFCTest
@Test
public void testTextNotUTF8() throws Exception
{
// Disable Long Stacks from Parser (we know this test will throw an exception)
enableStacks(Parser.class,false);
BlockheadClient client = new BlockheadClient(server.getServerUri());
client.setProtocols("other");
try
@ -347,8 +361,9 @@ public class WebSocketServletRFCTest
}
finally
{
// Reenable Long Stacks from Parser
enableStacks(Parser.class,true);
client.close();
}
}
}

View File

@ -23,6 +23,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.StdErrLog;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.common.Generator;
import org.eclipse.jetty.websocket.server.SimpleServletServer;
@ -88,6 +89,12 @@ public abstract class AbstractABCase
@Rule
public TestName testname = new TestName();
protected void enableStacks(Class<?> clazz, boolean enabled)
{
StdErrLog log = StdErrLog.getLogger(clazz);
log.setHideStacks(!enabled);
}
public Generator getLaxGenerator()
{
return laxGenerator;

View File

@ -190,6 +190,7 @@ public class Fuzzer
// we expect that the close handshake to have occurred and the server should have closed the connection
try
{
@SuppressWarnings("unused")
int val = client.read();
Assert.fail("Server has not closed socket");

View File

@ -22,13 +22,17 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.jetty.toolchain.test.AdvancedRunner;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.OpCode;
import org.eclipse.jetty.websocket.common.Parser;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AdvancedRunner.class)
public class TestABCase2 extends AbstractABCase
{
/**
@ -232,6 +236,9 @@ public class TestABCase2 extends AbstractABCase
@Test
public void testCase2_5() throws Exception
{
// Disable Long Stacks from Parser (we know this test will throw an exception)
enableStacks(Parser.class,false);
byte payload[] = new byte[126]; // intentionally too big
Arrays.fill(payload,(byte)'5');
@ -253,6 +260,7 @@ public class TestABCase2 extends AbstractABCase
}
finally
{
enableStacks(Parser.class,true);
fuzzer.close();
}
}

View File

@ -22,13 +22,34 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.jetty.toolchain.test.AdvancedRunner;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.Parser;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Test various RSV violations
*/
@RunWith(AdvancedRunner.class)
public class TestABCase3 extends AbstractABCase
{
@After
public void enableParserStacks()
{
enableStacks(Parser.class,true);
}
@Before
public void quietParserStacks()
{
enableStacks(Parser.class,false);
}
/**
* Send small text frame, with RSV1 == true, with no extensions defined.
*/

View File

@ -21,12 +21,21 @@ package org.eclipse.jetty.websocket.server.ab;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.toolchain.test.AdvancedRunner;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.Parser;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Test various bad / forbidden opcodes (per spec)
*/
@RunWith(AdvancedRunner.class)
public class TestABCase4 extends AbstractABCase
{
// Allow Fuzzer / Generator to create bad frames for testing frame validation
@ -40,6 +49,18 @@ public class TestABCase4 extends AbstractABCase
}
}
@After
public void enableParserStacks()
{
enableStacks(Parser.class,true);
}
@Before
public void quietParserStacks()
{
enableStacks(Parser.class,false);
}
/**
* Send opcode 3 (reserved)
*/

View File

@ -27,6 +27,7 @@ import org.eclipse.jetty.toolchain.test.annotation.Slow;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.OpCode;
import org.eclipse.jetty.websocket.common.Parser;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -43,6 +44,9 @@ public class TestABCase5 extends AbstractABCase
@Test
public void testCase5_1() throws Exception
{
// Disable Long Stacks from Parser (we know this test will throw an exception)
enableStacks(Parser.class,false);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new WebSocketFrame(OpCode.PING).setPayload("hello, ").setFin(false));
send.add(new WebSocketFrame(OpCode.CONTINUATION).setPayload("world"));
@ -62,6 +66,7 @@ public class TestABCase5 extends AbstractABCase
finally
{
fuzzer.close();
enableStacks(Parser.class,true);
}
}
@ -71,6 +76,9 @@ public class TestABCase5 extends AbstractABCase
@Test
public void testCase5_10() throws Exception
{
// Disable Long Stacks from Parser (we know this test will throw an exception)
enableStacks(Parser.class,false);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new WebSocketFrame(OpCode.CONTINUATION).setPayload("sorry").setFin(true));
send.add(new WebSocketFrame(OpCode.TEXT).setPayload("hello, world"));
@ -89,6 +97,7 @@ public class TestABCase5 extends AbstractABCase
}
finally
{
enableStacks(Parser.class,true);
fuzzer.close();
}
}
@ -99,6 +108,9 @@ public class TestABCase5 extends AbstractABCase
@Test
public void testCase5_11() throws Exception
{
// Disable Long Stacks from Parser (we know this test will throw an exception)
enableStacks(Parser.class,false);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new WebSocketFrame(OpCode.CONTINUATION).setPayload("sorry").setFin(true));
send.add(new WebSocketFrame(OpCode.TEXT).setPayload("hello, world"));
@ -118,6 +130,7 @@ public class TestABCase5 extends AbstractABCase
}
finally
{
enableStacks(Parser.class,true);
fuzzer.close();
}
}
@ -128,6 +141,9 @@ public class TestABCase5 extends AbstractABCase
@Test
public void testCase5_12() throws Exception
{
// Disable Long Stacks from Parser (we know this test will throw an exception)
enableStacks(Parser.class,false);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new WebSocketFrame(OpCode.CONTINUATION).setPayload("sorry").setFin(false));
send.add(new WebSocketFrame(OpCode.TEXT).setPayload("hello, world"));
@ -146,6 +162,7 @@ public class TestABCase5 extends AbstractABCase
}
finally
{
enableStacks(Parser.class,true);
fuzzer.close();
}
}
@ -156,6 +173,8 @@ public class TestABCase5 extends AbstractABCase
@Test
public void testCase5_13() throws Exception
{
// Disable Long Stacks from Parser (we know this test will throw an exception)
enableStacks(Parser.class,false);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new WebSocketFrame(OpCode.CONTINUATION).setPayload("sorry").setFin(false));
send.add(new WebSocketFrame(OpCode.TEXT).setPayload("hello, world"));
@ -174,6 +193,7 @@ public class TestABCase5 extends AbstractABCase
}
finally
{
enableStacks(Parser.class,true);
fuzzer.close();
}
}
@ -184,6 +204,9 @@ public class TestABCase5 extends AbstractABCase
@Test
public void testCase5_14() throws Exception
{
// Disable Long Stacks from Parser (we know this test will throw an exception)
enableStacks(Parser.class,false);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new WebSocketFrame(OpCode.CONTINUATION).setPayload("sorry").setFin(false));
send.add(new WebSocketFrame(OpCode.TEXT).setPayload("hello, world"));
@ -203,6 +226,7 @@ public class TestABCase5 extends AbstractABCase
}
finally
{
enableStacks(Parser.class,false);
fuzzer.close();
}
}
@ -213,6 +237,9 @@ public class TestABCase5 extends AbstractABCase
@Test
public void testCase5_15() throws Exception
{
// Disable Long Stacks from Parser (we know this test will throw an exception)
enableStacks(Parser.class,false);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new WebSocketFrame(OpCode.TEXT).setPayload("fragment1").setFin(false));
send.add(new WebSocketFrame(OpCode.CONTINUATION).setPayload("fragment2").setFin(true));
@ -234,6 +261,7 @@ public class TestABCase5 extends AbstractABCase
}
finally
{
enableStacks(Parser.class,true);
fuzzer.close();
}
}
@ -244,6 +272,9 @@ public class TestABCase5 extends AbstractABCase
@Test
public void testCase5_16() throws Exception
{
// Disable Long Stacks from Parser (we know this test will throw an exception)
enableStacks(Parser.class,false);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new WebSocketFrame(OpCode.CONTINUATION).setPayload("fragment1").setFin(false)); // bad frame
send.add(new WebSocketFrame(OpCode.TEXT).setPayload("fragment2").setFin(false));
@ -266,6 +297,7 @@ public class TestABCase5 extends AbstractABCase
}
finally
{
enableStacks(Parser.class,true);
fuzzer.close();
}
}
@ -276,6 +308,9 @@ public class TestABCase5 extends AbstractABCase
@Test
public void testCase5_17() throws Exception
{
// Disable Long Stacks from Parser (we know this test will throw an exception)
enableStacks(Parser.class,false);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new WebSocketFrame(OpCode.CONTINUATION).setPayload("fragment1").setFin(true)); // nothing to continue
send.add(new WebSocketFrame(OpCode.TEXT).setPayload("fragment2").setFin(false));
@ -298,6 +333,7 @@ public class TestABCase5 extends AbstractABCase
}
finally
{
enableStacks(Parser.class,true);
fuzzer.close();
}
}
@ -308,6 +344,9 @@ public class TestABCase5 extends AbstractABCase
@Test
public void testCase5_18() throws Exception
{
// Disable Long Stacks from Parser (we know this test will throw an exception)
enableStacks(Parser.class,false);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new WebSocketFrame(OpCode.TEXT).setPayload("fragment1").setFin(false));
send.add(new WebSocketFrame(OpCode.TEXT).setPayload("fragment2").setFin(true)); // bad frame, must be continuation
@ -326,6 +365,7 @@ public class TestABCase5 extends AbstractABCase
}
finally
{
enableStacks(Parser.class,true);
fuzzer.close();
}
}
@ -388,6 +428,9 @@ public class TestABCase5 extends AbstractABCase
@Test
public void testCase5_2() throws Exception
{
// Disable Long Stacks from Parser (we know this test will throw an exception)
enableStacks(Parser.class,false);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new WebSocketFrame(OpCode.PONG).setPayload("hello, ").setFin(false));
send.add(new WebSocketFrame(OpCode.CONTINUATION).setPayload("world"));
@ -406,6 +449,7 @@ public class TestABCase5 extends AbstractABCase
}
finally
{
enableStacks(Parser.class,true);
fuzzer.close();
}
}
@ -691,6 +735,9 @@ public class TestABCase5 extends AbstractABCase
@Test
public void testCase5_9() throws Exception
{
// Disable Long Stacks from Parser (we know this test will throw an exception)
enableStacks(Parser.class,false);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new WebSocketFrame(OpCode.CONTINUATION).setPayload("sorry").setFin(true));
send.add(new WebSocketFrame(OpCode.TEXT).setPayload("hello, world"));
@ -709,6 +756,7 @@ public class TestABCase5 extends AbstractABCase
}
finally
{
enableStacks(Parser.class,true);
fuzzer.close();
}
}

View File

@ -31,6 +31,7 @@ import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.OpCode;
import org.eclipse.jetty.websocket.common.Parser;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.server.helper.Hex;
import org.junit.Test;
@ -356,6 +357,9 @@ public class TestABCase6 extends AbstractABCase
@Slow
public void testCase6_4_3() throws Exception
{
// Disable Long Stacks from Parser (we know this test will throw an exception)
enableStacks(Parser.class,false);
ByteBuffer payload = ByteBuffer.allocate(64);
BufferUtil.clearToFill(payload);
payload.put(TypeUtil.fromHexString("cebae1bdb9cf83cebcceb5")); // good
@ -400,6 +404,7 @@ public class TestABCase6 extends AbstractABCase
}
finally
{
enableStacks(Parser.class,true);
fuzzer.close();
}
}
@ -411,6 +416,9 @@ public class TestABCase6 extends AbstractABCase
@Slow
public void testCase6_4_4() throws Exception
{
// Disable Long Stacks from Parser (we know this test will throw an exception)
enableStacks(Parser.class,false);
byte invalid[] = Hex.asByteArray("CEBAE1BDB9CF83CEBCCEB5F49080808080656469746564");
List<WebSocketFrame> send = new ArrayList<>();
@ -437,6 +445,7 @@ public class TestABCase6 extends AbstractABCase
}
finally
{
enableStacks(Parser.class,true);
fuzzer.close();
}
}

View File

@ -24,7 +24,6 @@ import java.util.List;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.log.StdErrLog;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.OpCode;
@ -177,10 +176,4 @@ public class TestABCase6_BadUTF extends AbstractABCase
enableStacks(Parser.class,true);
}
}
private void enableStacks(Class<?> clazz, boolean enabled)
{
StdErrLog log = StdErrLog.getLogger(clazz);
log.setHideStacks(!enabled);
}
}

View File

@ -26,7 +26,6 @@ import java.util.List;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.StdErrLog;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.OpCode;
@ -41,12 +40,6 @@ import org.junit.Test;
*/
public class TestABCase7 extends AbstractABCase
{
private static void enableStacks(Class<?> clazz, boolean enabled)
{
StdErrLog log = StdErrLog.getLogger(clazz);
log.setHideStacks(!enabled);
}
@Rule
public TestTracker tt = new TestTracker();

View File

@ -1,8 +1,8 @@
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
# org.eclipse.jetty.LEVEL=WARN
org.eclipse.jetty.LEVEL=WARN
# org.eclipse.jetty.websocket.LEVEL=DEBUG
org.eclipse.jetty.websocket.LEVEL=WARN
# org.eclipse.jetty.websocket.LEVEL=WARN
# org.eclipse.jetty.websocket.common.io.LEVEL=DEBUG
# org.eclipse.jetty.websocket.server.ab.LEVEL=DEBUG
# org.eclipse.jetty.websocket.common.io.LEVEL=DEBUG