1 module hunt.http.server.Http1ServerDecoder;
2 
3 import hunt.http.server.Http1ServerConnection;
4 import hunt.http.server.Http1ServerTunnelConnection;
5 import hunt.http.server.Http2ServerDecoder;
6 
7 import hunt.http.codec.http.decode.HttpParser;
8 import hunt.http.codec.websocket.decode.WebSocketDecoder;
9 
10 import hunt.net.AbstractConnection;
11 import hunt.net.DecoderChain;
12 import hunt.net.ConnectionType;
13 import hunt.net.Session;
14 
15 import hunt.container.ByteBuffer;
16 import hunt.container.BufferUtils;
17 import hunt.lang.exception;
18 import hunt.logging;
19 import std.conv;
20 
21 /**
22 */
23 class Http1ServerDecoder : DecoderChain {
24 
25     private WebSocketDecoder webSocketDecoder;
26     private Http2ServerDecoder http2ServerDecoder;
27 
28     this(WebSocketDecoder webSocketDecoder, Http2ServerDecoder http2ServerDecoder) {
29         super(null);
30         this.webSocketDecoder = webSocketDecoder;
31         this.http2ServerDecoder = http2ServerDecoder;
32     }
33 
34     override void decode(ByteBuffer buffer, Session session) {
35         ByteBuffer buf = BufferUtils.toHeapBuffer(buffer);
36 
37         Object attachment = session.getAttachment();
38         version (HUNT_DEBUG)
39             infof("session type: %s", typeid(attachment));
40 
41         AbstractConnection abstractConnection = cast(AbstractConnection) attachment;
42         if (abstractConnection is null) {
43             warningf("Bad connection instance: ", typeid(attachment));
44             return;
45         }
46 
47         switch (abstractConnection.getConnectionType()) {
48         case ConnectionType.HTTP1: {
49                 Http1ServerConnection http1Connection = cast(Http1ServerConnection) attachment;
50                 if (http1Connection.getTunnelConnectionPromise() is null) {
51                     HttpParser parser = http1Connection.getParser();
52                     version (HUNT_DEBUG) trace("runing http1 parser for a buffer...");
53                     while (buf.hasRemaining()) {
54                         parser.parseNext(buf);
55                         if (http1Connection.getUpgradeHttp2Complete()) {
56                             http2ServerDecoder.decode(buf, session);
57                             break;
58                         } else if (http1Connection.getUpgradeWebSocketComplete()) {
59                             webSocketDecoder.decode(buf, session);
60                             break;
61                         }
62                     }
63                     version (HUNT_DEBUG) trace("http1 parsing done for a buffer...");
64                 } else {
65                     Http1ServerTunnelConnection tunnelConnection = http1Connection.createHttpTunnel();
66                     if (tunnelConnection.content != null) {
67                         tunnelConnection.content(buf);
68                     }
69                 }
70             }
71             break;
72         case ConnectionType.HTTP2: {
73                 http2ServerDecoder.decode(buf, session);
74             }
75             break;
76         case ConnectionType.WEB_SOCKET: {
77                 webSocketDecoder.decode(buf, session);
78             }
79             break;
80         case ConnectionType.HTTP_TUNNEL: {
81                 Http1ServerTunnelConnection tunnelConnection = 
82                     cast(Http1ServerTunnelConnection) session.getAttachment();
83                 if (tunnelConnection.content != null) {
84                     tunnelConnection.content(buf);
85                 }
86             }
87             break;
88         default:
89             throw new IllegalStateException("client does not support the protocol " ~ to!string(
90                     abstractConnection.getConnectionType()));
91         }
92     }
93 }