1 module hunt.http.server.Http2ServerSession; 2 3 import hunt.http.server.ServerSessionListener; 4 5 import hunt.http.codec.http.decode.ServerParser; 6 import hunt.http.codec.http.encode.Http2Generator; 7 import hunt.http.codec.http.frame; 8 import hunt.http.HttpMetaData; 9 import hunt.http.codec.http.stream; 10 11 import hunt.collection.Collections; 12 import hunt.collection.Map; 13 import hunt.util.Common; 14 import hunt.logging; 15 import hunt.net.Connection; 16 import hunt.concurrency.Scheduler; 17 import hunt.util.Common; 18 19 20 class Http2ServerSession : Http2Session , ServerParser.Listener { 21 22 private ServerSessionListener listener; 23 24 this(Scheduler scheduler, Connection endPoint, Http2Generator generator, 25 ServerSessionListener listener, FlowControlStrategy flowControl, int streamIdleTimeout) { 26 super(scheduler, endPoint, generator, listener, flowControl, 2, streamIdleTimeout); 27 this.listener = listener; 28 } 29 30 override 31 void onPreface() { 32 // SPEC: send a SETTINGS frame upon receiving the preface. 33 Map!(int, int) settings = notifyPreface(this); 34 if (settings is null) 35 settings = Collections.emptyMap!(int, int)(); 36 SettingsFrame settingsFrame = new SettingsFrame(settings, false); 37 38 WindowUpdateFrame windowFrame = null; 39 int sessionWindow = getInitialSessionRecvWindow() - FlowControlStrategy.DEFAULT_WINDOW_SIZE; 40 if (sessionWindow > 0) { 41 updateRecvWindow(sessionWindow); 42 windowFrame = new WindowUpdateFrame(0, sessionWindow); 43 } 44 45 if (windowFrame is null) 46 frames(null, Callback.NOOP, settingsFrame, Frame.EMPTY_ARRAY); 47 else 48 frames(null, Callback.NOOP, settingsFrame, windowFrame); 49 } 50 51 override 52 void onHeaders(HeadersFrame frame) { 53 version(HUNT_HTTP_DEBUG) { 54 tracef("Server received %s", frame); 55 } 56 57 HttpMetaData metaData = frame.getMetaData(); 58 if (metaData.isRequest()) { 59 StreamSPI stream = createRemoteStream(frame.getStreamId()); 60 if (stream !is null) { 61 stream.process(frame, Callback.NOOP); 62 Stream.Listener listener = notifyNewStream(stream, frame); 63 stream.setListener(listener); 64 } 65 } else { 66 if (frame.isEndStream()) { // The trailer frame 67 StreamSPI st = cast(StreamSPI)getStream(frame.getStreamId()); 68 if(st !is null) 69 { 70 st.process(frame, Callback.NOOP); 71 notifyHeaders(st, frame); 72 } 73 } else { 74 onConnectionFailure(ErrorCode.INTERNAL_ERROR, "invalid_request"); 75 } 76 } 77 } 78 79 override 80 void onPushPromise(PushPromiseFrame frame) { 81 onConnectionFailure(ErrorCode.PROTOCOL_ERROR, "push_promise"); 82 } 83 84 private Map!(int, int) notifyPreface(StreamSession session) { 85 try { 86 return listener.onPreface(session); 87 } catch (Throwable x) { 88 errorf("Failure while notifying listener %s", x, listener); 89 return null; 90 } 91 } 92 93 override 94 void onFrame(Frame frame) { 95 switch (frame.getType()) { 96 case FrameType.PREFACE: 97 onPreface(); 98 break; 99 case FrameType.SETTINGS: 100 // SPEC: the required reply to this SETTINGS frame is the 101 101 // response. 102 onSettings(cast(SettingsFrame) frame, false); 103 break; 104 case FrameType.HEADERS: 105 onHeaders(cast(HeadersFrame) frame); 106 break; 107 default: 108 super.onFrame(frame); 109 break; 110 } 111 } 112 }