1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.http2.server;
20
21 import java.util.Collections;
22 import java.util.Map;
23
24 import org.eclipse.jetty.http.MetaData;
25 import org.eclipse.jetty.http2.ErrorCode;
26 import org.eclipse.jetty.http2.FlowControlStrategy;
27 import org.eclipse.jetty.http2.HTTP2Session;
28 import org.eclipse.jetty.http2.IStream;
29 import org.eclipse.jetty.http2.api.Session;
30 import org.eclipse.jetty.http2.api.Stream;
31 import org.eclipse.jetty.http2.api.server.ServerSessionListener;
32 import org.eclipse.jetty.http2.frames.Frame;
33 import org.eclipse.jetty.http2.frames.HeadersFrame;
34 import org.eclipse.jetty.http2.frames.PushPromiseFrame;
35 import org.eclipse.jetty.http2.frames.SettingsFrame;
36 import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
37 import org.eclipse.jetty.http2.generator.Generator;
38 import org.eclipse.jetty.http2.parser.ServerParser;
39 import org.eclipse.jetty.io.EndPoint;
40 import org.eclipse.jetty.util.Callback;
41 import org.eclipse.jetty.util.log.Log;
42 import org.eclipse.jetty.util.log.Logger;
43 import org.eclipse.jetty.util.thread.Scheduler;
44
45 public class HTTP2ServerSession extends HTTP2Session implements ServerParser.Listener
46 {
47 private static final Logger LOG = Log.getLogger(HTTP2ServerSession.class);
48
49 private final ServerSessionListener listener;
50
51 public HTTP2ServerSession(Scheduler scheduler, EndPoint endPoint, Generator generator, ServerSessionListener listener, FlowControlStrategy flowControl)
52 {
53 super(scheduler, endPoint, generator, listener, flowControl, 2);
54 this.listener = listener;
55 }
56
57 @Override
58 public void onPreface()
59 {
60
61 Map<Integer, Integer> settings = notifyPreface(this);
62 if (settings == null)
63 settings = Collections.emptyMap();
64 SettingsFrame settingsFrame = new SettingsFrame(settings, false);
65
66 WindowUpdateFrame windowFrame = null;
67 int sessionWindow = getInitialSessionRecvWindow() - FlowControlStrategy.DEFAULT_WINDOW_SIZE;
68 if (sessionWindow > 0)
69 {
70 updateRecvWindow(sessionWindow);
71 windowFrame = new WindowUpdateFrame(0, sessionWindow);
72 }
73
74 if (windowFrame == null)
75 frames(null, Callback.NOOP, settingsFrame, Frame.EMPTY_ARRAY);
76 else
77 frames(null, Callback.NOOP, settingsFrame, windowFrame);
78 }
79
80 @Override
81 public void onHeaders(HeadersFrame frame)
82 {
83 if (LOG.isDebugEnabled())
84 LOG.debug("Received {}", frame);
85
86 MetaData metaData = frame.getMetaData();
87 if (metaData.isRequest())
88 {
89 IStream stream = createRemoteStream(frame.getStreamId());
90 if (stream != null)
91 {
92 onStreamOpened(stream);
93 stream.process(frame, Callback.NOOP);
94 Stream.Listener listener = notifyNewStream(stream, frame);
95 stream.setListener(listener);
96 }
97 }
98 else
99 {
100 onConnectionFailure(ErrorCode.INTERNAL_ERROR.code, "invalid_request");
101 }
102 }
103
104 @Override
105 public void onPushPromise(PushPromiseFrame frame)
106 {
107 onConnectionFailure(ErrorCode.PROTOCOL_ERROR.code, "push_promise");
108 }
109
110 private Map<Integer, Integer> notifyPreface(Session session)
111 {
112 try
113 {
114 return listener.onPreface(session);
115 }
116 catch (Throwable x)
117 {
118 LOG.info("Failure while notifying listener " + listener, x);
119 return null;
120 }
121 }
122
123 @Override
124 public void onFrame(Frame frame)
125 {
126 switch (frame.getType())
127 {
128 case PREFACE:
129 onPreface();
130 break;
131 case SETTINGS:
132
133 onSettings((SettingsFrame)frame, false);
134 break;
135 case HEADERS:
136 onHeaders((HeadersFrame)frame);
137 break;
138 default:
139 super.onFrame(frame);
140 break;
141 }
142 }
143 }