1 /*
2  * MsgTrans - Message Transport Framework for DLang. Based on TCP, WebSocket, UDP transmission protocol.
3  *
4  * Copyright (C) 2019 HuntLabs
5  *
6  * Website: https://www.msgtrans.org
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module msgtrans.channel.tcp.TcpDecoder;
13 
14 import msgtrans.PacketParser;
15 import msgtrans.MessageBuffer;
16 
17 import hunt.io.ByteBuffer;
18 import hunt.io.BufferUtils;
19 import hunt.Exceptions;
20 import hunt.logging.ConsoleLogger;
21 import hunt.net;
22 
23 import std.algorithm;
24 import std.conv;
25 
26 
27 class TcpDecoder : DecoderChain {
28     private enum string PARSER = "PacketParser";
29 
30     /** The default maximum buffer length. Default to 128 chars. */
31     private int bufferLength = 128;
32 
33     /** The default maximum Line length. Default to 1024. */
34     private int maxLineLength = 8*1024;
35 
36 
37     this() {
38         super(null);
39     }
40 
41 
42     /**
43      * @return the allowed maximum size of the line to be decoded.
44      * If the size of the line to be decoded exceeds this value, the
45      * decoder will throw a {@link BufferDataException}.  The default
46      * value is <tt>1024</tt> (1KB).
47      */
48     int getMaxLineLength() {
49         return maxLineLength;
50     }
51 
52     /**
53      * Sets the allowed maximum size of the line to be decoded.
54      * If the size of the line to be decoded exceeds this value, the
55      * decoder will throw a {@link BufferDataException}.  The default
56      * value is <tt>1024</tt> (1KB).
57      *
58      * @param maxLineLength The maximum line length
59      */
60     void setMaxLineLength(int maxLineLength) {
61         if (maxLineLength <= 0) {
62             throw new IllegalArgumentException("maxLineLength (" ~
63                 maxLineLength.to!string() ~ ") should be a positive value");
64         }
65 
66         this.maxLineLength = maxLineLength;
67     }
68 
69     /**
70      * Sets the default buffer size. This buffer is used in the Context
71      * to store the decoded line.
72      *
73      * @param bufferLength The default bufer size
74      */
75     void setBufferLength(int bufferLength) {
76         if (bufferLength <= 0) {
77             throw new IllegalArgumentException("bufferLength (" ~
78                 maxLineLength.to!string() ~ ") should be a positive value");
79 
80         }
81 
82         this.bufferLength = bufferLength;
83     }
84 
85     /**
86      * @return the allowed buffer size used to store the decoded line
87      * in the Context instance.
88      */
89     int getBufferLength() {
90         return bufferLength;
91     }
92 
93     override
94     void decode(ByteBuffer buf, Connection connection) {
95         version(HUNT_MESSAGE_DEBUG) tracef("connection %d: %s", connection.getId(), buf.toString());
96         PacketParser parser = getParser(connection);
97 
98         MessageBuffer[] msgBuffers = parser.parse(buf);
99         if(msgBuffers is null) {
100             warning("No frame parsed.");
101             return;
102         }
103 
104         NetConnectionHandler handler = connection.getHandler();
105         if(handler is null) {
106             warning("No handler found.");
107             return;
108         }
109 
110         foreach(MessageBuffer msg; msgBuffers) {
111             handler.messageReceived(connection, msg);
112         }
113 
114     }
115 
116     private PacketParser getParser(Connection connection) {
117         PacketParser ctx;
118         ctx = cast(PacketParser) connection.getAttribute(PARSER);
119 
120         if (ctx is null) {
121             ctx = new PacketParser(bufferLength);
122             connection.setAttribute(PARSER, ctx);
123         }
124 
125         return ctx;
126     }
127 
128 
129     void dispose(Connection connection) {
130         PacketParser ctx = cast(PacketParser) connection.getAttribute(PARSER);
131 
132         if (ctx !is null) {
133             connection.removeAttribute(PARSER);
134         }
135     }
136 
137 }
138