1 module hunt.imf.ParserBase; 2 3 import hunt.imf.EvBuffer; 4 import hunt.net.Connection; 5 import hunt.imf.MessageBuffer; 6 import hunt.util.Serialize; 7 import std.bitmanip; 8 import std.stdint; 9 import std.string; 10 import std.stdio; 11 import std.conv; 12 import std.typecons; 13 import std.uri; 14 15 struct HttpContent { 16 size_t status = 0; 17 string path; 18 string method; 19 string[string] headField; 20 string[string] parameters; 21 string body; 22 23 void reset() 24 { 25 status= 0; 26 path = ""; 27 } 28 } 29 30 enum Field { 31 CONTENTLENGTH = "Content-Length" 32 } 33 34 class ParserBase { 35 36 protected enum string CONTEXT = "REVBUFFER"; 37 38 private const ulong DATAHEADLEN = 20; 39 40 protected const string HTTPHEADEOF = "\r\n\r\n"; 41 protected const string LINEFEEDS = "\r\n"; 42 43 enum MAX_HTTP_REQUEST_BUFF = 4096; 44 45 public void parserTcpStream (EvBuffer!ubyte src , ubyte [] incr , Connection connection) 46 { 47 src.mergeBuffer(incr); 48 ulong uBufLen = 0; 49 50 while ( (uBufLen = src.getBufferLength()) >= DATAHEADLEN ) 51 { 52 auto head = new ubyte [DATAHEADLEN]; 53 if (!src.copyOutFromHead(head ,DATAHEADLEN)) { break;} 54 55 ulong bodyLength = bigEndianToNative!int32_t(head[16 .. 20]); 56 57 if (bodyLength > 2147483647 || bodyLength < 0) 58 { 59 src.reset(); 60 break; 61 } 62 63 if (uBufLen >= bodyLength + DATAHEADLEN) 64 { 65 MessageBuffer msg = new MessageBuffer(); 66 msg.messageId = bigEndianToNative!long(head[8 .. 16]); 67 if (!src.drainBufferFromHead(DATAHEADLEN)) { break;} 68 msg.message = new ubyte [bodyLength]; 69 if (bodyLength) 70 { 71 if (!src.removeBufferFromHead(msg.message,bodyLength)) {break;} 72 } 73 if (connection !is null) 74 { 75 ConnectionEventHandler handler = connection.getHandler(); 76 if(handler !is null) { 77 handler.messageReceived(connection, msg); 78 } 79 } 80 } else 81 { 82 break; 83 } 84 } 85 } 86 87 public void parserHttpStream (EvBuffer!ubyte src , ubyte [] incr , Connection connection) 88 { 89 src.mergeBuffer(incr); 90 if (src.getBufferLength() > MAX_HTTP_REQUEST_BUFF) 91 { 92 src.reset(); 93 return; 94 } 95 96 ulong head_pos = 0 ; 97 string buffer = cast(string)src.getBuffer(); 98 while ((head_pos = indexOf(buffer,HTTPHEADEOF)) != -1) 99 { 100 HttpContent content; 101 string head = cast(string)buffer[0 .. head_pos]; 102 parserHttpHead(content,head); 103 auto content_length = content.headField.get(Field.CONTENTLENGTH,null); 104 if (content_length !is null && (head_pos + 4 + to!int(content_length)) > buffer.length) 105 { 106 break; 107 } 108 else 109 { 110 content.body = buffer[head_pos + 4 .. $]; 111 MessageBuffer msg = new MessageBuffer(); 112 msg.messageId = cast(int)hashOf!string(content.path); 113 msg.message = cast(ubyte[])serialize!HttpContent(content); 114 if (connection !is null) 115 { 116 ConnectionEventHandler handler = connection.getHandler(); 117 if(handler !is null) { 118 handler.messageReceived(connection, msg); 119 } 120 } 121 src.reset(); 122 break; 123 } 124 } 125 } 126 127 private void parserHttpHead(ref HttpContent httpcontent , string headBuff) 128 { 129 auto fields = split(headBuff,"\r\n"); 130 foreach(field;fields) 131 { 132 if (field.count("HTTP/")) 133 { 134 auto child = split(field," "); 135 if (child[0].count("HTTP/")) 136 { 137 httpcontent.status = to!int(child[1]); 138 139 } else 140 { 141 httpcontent.method= child[0]; 142 string url = decodeComponent(child[1]); 143 long flag = indexOf(url ,"?"); 144 httpcontent.path = url[0 .. flag == -1 ? $:flag]; 145 if (flag != -1) 146 { 147 string[] items = url[flag + 1 .. $].split("&"); 148 foreach( item ; items) 149 { 150 if(item != string.init) 151 { 152 auto v = item.split("="); 153 httpcontent.parameters[v[0]] = v[1]; 154 } 155 } 156 } 157 } 158 } else 159 { 160 long pos = 0; 161 if ( (pos = indexOf(field ,":")) != -1) 162 { 163 httpcontent.headField[strip(field[0 .. pos])] = strip(field[pos+1 ..$]); 164 } 165 } 166 } 167 } 168 }