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                  stream.process(frame, Callback.NOOP);
93                  Stream.Listener listener = notifyNewStream(stream, frame);
94                  stream.setListener(listener);
95              }
96          }
97          else
98          {
99              onConnectionFailure(ErrorCode.INTERNAL_ERROR.code, "invalid_request");
100         }
101     }
102 
103     @Override
104     public void onPushPromise(PushPromiseFrame frame)
105     {
106         onConnectionFailure(ErrorCode.PROTOCOL_ERROR.code, "push_promise");
107     }
108 
109     private Map<Integer, Integer> notifyPreface(Session session)
110     {
111         try
112         {
113             return listener.onPreface(session);
114         }
115         catch (Throwable x)
116         {
117             LOG.info("Failure while notifying listener " + listener, x);
118             return null;
119         }
120     }
121 
122     @Override
123     public void onFrame(Frame frame)
124     {
125         switch (frame.getType())
126         {
127             case PREFACE:
128                 onPreface();
129                 break;
130             case SETTINGS:
131                 // SPEC: the required reply to this SETTINGS frame is the 101 response.
132                 onSettings((SettingsFrame)frame, false);
133                 break;
134             case HEADERS:
135                 onHeaders((HeadersFrame)frame);
136                 break;
137             default:
138                 super.onFrame(frame);
139                 break;
140         }
141     }
142 }