View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
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          // SPEC: send a SETTINGS frame upon receiving the preface.
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                 // SPEC: the required reply to this SETTINGS frame is the 101 response.
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 }