@@ -9,113 +9,113 @@ public class ProxyProtocolParserV1 : IProxyProtocolParser
99 #region Constants
1010 private const string DELIMITER = "\r \n " ;
1111 private const char SEPARATOR = ' ' ;
12+ private const int MAX_HEADER_SIZE = 107 ;
1213 #endregion
1314
1415 #region Members
1516 private NetworkStream _stream ;
1617 private IPEndPoint _remoteEndpoint ;
1718 private byte [ ] _buffer ;
18- private int _bufferPosition ;
19+ private int _bufferSize ;
1920
20- private bool _isParsed ;
21+ private bool _hasParsed ;
2122 private AddressFamily _addressFamily = AddressFamily . Unknown ;
2223 private ProxyProtocolCommand _protocolCommand = ProxyProtocolCommand . Unknown ;
2324 private IPEndPoint ? _sourceEndpoint ;
2425 private IPEndPoint ? _destEndpoint ;
2526 #endregion
2627
27- public ProxyProtocolParserV1 ( NetworkStream stream , IPEndPoint remoteEndpoint , byte [ ] buffer , ref int bufferPosition )
28+ public ProxyProtocolParserV1 ( NetworkStream stream , IPEndPoint remoteEndpoint , byte [ ] buffer , int bufferSize )
2829 {
2930 #region Args checking
30- if ( stream == null ) throw new ArgumentNullException ( "argument ' stream' cannot be null" ) ;
31- if ( stream . CanRead != true ) throw new ArgumentException ( "argument 'stream' is unreadable" ) ;
32- if ( remoteEndpoint == null ) throw new ArgumentNullException ( "argument ' remoteEndpoint' cannot be null" ) ;
33- if ( buffer == null ) throw new ArgumentNullException ( "argument ' buffer' cannot be null" ) ;
34- if ( bufferPosition > buffer . Length ) throw new ArgumentException ( "argument 'bufferPosition ' is larger than 'buffer.Length'" ) ;
31+ if ( stream == null ) throw new ArgumentNullException ( nameof ( stream ) ) ;
32+ if ( stream . CanRead != true ) throw new ArgumentException ( $ "argument 'stream' is unreadable") ;
33+ if ( remoteEndpoint == null ) throw new ArgumentNullException ( nameof ( remoteEndpoint ) ) ;
34+ if ( buffer == null ) throw new ArgumentNullException ( nameof ( buffer ) ) ;
35+ if ( bufferSize > buffer . Length ) throw new ArgumentException ( $ "argument '{ nameof ( bufferSize ) } ' is larger than '{ nameof ( buffer ) } .Length'") ;
3536 #endregion
3637
3738 #region Filling members
3839 _stream = stream ;
3940 _remoteEndpoint = remoteEndpoint ;
4041 _buffer = buffer ;
41- _bufferPosition = bufferPosition ;
42+ _bufferSize = bufferSize ;
4243 #endregion
4344 }
4445
4546 #region Public methods
4647 public async Task Parse ( )
4748 {
48- if ( _isParsed )
49+ if ( _hasParsed )
4950 return ;
50- _isParsed = true ;
51- Logger . Log ( "Parsing header") ;
51+ _hasParsed = true ;
52+ Logger . Log ( $ "[ { _remoteEndpoint } ] parsing header... ") ;
5253
5354 #region Getting full header and do first check
55+
5456 await GetFullHeader ( ) ;
55- if ( _bufferPosition < 2 || _buffer [ _bufferPosition - 2 ] != '\r ' )
56- throw new Exception ( "Header must end with CRLF" ) ;
57-
58- string [ ] tokens = Encoding . ASCII . GetString ( _buffer . Take ( _bufferPosition - 2 ) . ToArray ( ) ) . Split ( SEPARATOR ) ;
57+ if ( ProxyProtocolSocketPlugin . Config . Settings . LogLevel == LogLevel . Debug )
58+ Logger . Log ( $ "[{ _remoteEndpoint } ] header content: { Convert . ToHexString ( _buffer [ .._bufferSize ] ) } ") ;
59+ var tokens = Encoding . ASCII . GetString ( _buffer [ ..( _bufferSize - 2 ) ] ) . Split ( SEPARATOR ) ;
5960 if ( tokens . Length < 2 )
6061 throw new Exception ( "Unable to read AddressFamily and protocol" ) ;
62+
6163 #endregion
6264
6365 #region Parse address family
64- AddressFamily addressFamily ;
65- switch ( tokens [ 1 ] )
66+
67+ Logger . Log ( $ "[{ _remoteEndpoint } ] parsing address family...") ;
68+ var addressFamily = tokens [ 1 ] switch
6669 {
67- case "TCP4" :
68- addressFamily = AddressFamily . InterNetwork ;
69- break ;
70-
71- case "TCP6" :
72- addressFamily = AddressFamily . InterNetworkV6 ;
73- break ;
74-
75- case "UNKNOWN" :
76- addressFamily = AddressFamily . Unspecified ;
77- break ;
70+ "TCP4" => AddressFamily . InterNetwork ,
71+ "TCP6" => AddressFamily . InterNetworkV6 ,
72+ "UNKNOWN" => AddressFamily . Unspecified ,
73+ _ => throw new Exception ( "Invalid address family" )
74+ } ;
7875
79- default :
80- throw new Exception ( "Invalid address family" ) ;
81- }
8276 #endregion
8377
8478 #region Do second check
79+
8580 if ( addressFamily == AddressFamily . Unspecified )
8681 {
8782 _protocolCommand = ProxyProtocolCommand . Local ;
8883 _sourceEndpoint = _remoteEndpoint ;
89- _isParsed = true ;
84+ _hasParsed = true ;
9085 return ;
9186 }
92- else if ( tokens . Length < 6 )
93- throw new Exception ( "Unable to read ipaddresses and ports" ) ;
87+
88+ if ( tokens . Length < 6 )
89+ throw new Exception ( "Impossible to read ip addresses and ports as the number of tokens is less than 6" ) ;
90+
9491 #endregion
9592
9693 #region Parse source and dest end point
97- IPEndPoint sourceEP ;
98- IPEndPoint destEP ;
94+
95+ Logger . Log ( $ "[{ _remoteEndpoint } ] parsing endpoints...") ;
96+ IPEndPoint sourceEp ;
97+ IPEndPoint destEp ;
9998 try
10099 {
101100 // TODO: IP format validation
102- IPAddress sourceAddr = IPAddress . Parse ( tokens [ 2 ] ) ;
103- IPAddress destAddr = IPAddress . Parse ( tokens [ 3 ] ) ;
104- int sourcePort = Convert . ToInt32 ( tokens [ 4 ] ) ;
105- int destPort = Convert . ToInt32 ( tokens [ 5 ] ) ;
106- sourceEP = new IPEndPoint ( sourceAddr , sourcePort ) ;
107- destEP = new IPEndPoint ( destAddr , destPort ) ;
101+ var sourceAddr = IPAddress . Parse ( tokens [ 2 ] ) ;
102+ var destAddr = IPAddress . Parse ( tokens [ 3 ] ) ;
103+ var sourcePort = Convert . ToInt32 ( tokens [ 4 ] ) ;
104+ var destPort = Convert . ToInt32 ( tokens [ 5 ] ) ;
105+ sourceEp = new IPEndPoint ( sourceAddr , sourcePort ) ;
106+ destEp = new IPEndPoint ( destAddr , destPort ) ;
108107 }
109108 catch ( Exception ex )
110109 {
111110 throw new Exception ( "Unable to parse ip addresses and ports" , ex ) ;
112111 }
112+
113113 #endregion
114114
115115 _addressFamily = addressFamily ;
116116 _protocolCommand = ProxyProtocolCommand . Proxy ;
117- _sourceEndpoint = sourceEP ;
118- _destEndpoint = destEP ;
117+ _sourceEndpoint = sourceEp ;
118+ _destEndpoint = destEp ;
119119 }
120120
121121 public async Task < IPEndPoint ? > GetSourceEndpoint ( )
@@ -146,58 +146,47 @@ public async Task<ProxyProtocolCommand> GetCommand()
146146 #region Private methods
147147 private async Task GetFullHeader ( )
148148 {
149- Logger . Log ( $ "Getting full header") ;
150- for ( int i = 1 ; ; i ++ )
149+ Logger . Log ( $ "[ { _remoteEndpoint } ] getting full header") ;
150+ for ( var i = 7 ; i < MAX_HEADER_SIZE ; i ++ ) // Search after "PROXY" signature
151151 {
152- if ( await GetOneByteOfPosition ( i ) == '\n ' )
153- break ;
154- if ( i >= _buffer . Length )
155- throw new Exception ( "Reaching the end of buffer without reaching the delimiter of version 1" ) ;
152+ if ( await GetOneByteAtPosition ( i ) != DELIMITER [ 1 ] )
153+ continue ;
154+ if ( await GetOneByteAtPosition ( i - 1 ) != DELIMITER [ 0 ] )
155+ throw new Exception ( "Header must end with CRLF" ) ;
156+ return ;
156157 }
158+ throw new Exception ( "Failed to find any delimiter within the maximum header size of version 1" ) ;
157159 }
158160
159- private async Task GetBytesToPosition ( int position )
161+ private async Task GetBytesTillBufferSize ( int size )
160162 {
161- if ( position <= _bufferPosition )
163+ if ( size <= _bufferSize )
162164 return ;
163- await GetBytesFromStream ( position - _bufferPosition ) ;
165+ await GetBytesFromStream ( size - _bufferSize ) ;
164166 }
165167
166168 private async Task GetBytesFromStream ( int length )
167169 {
168- if ( ( _bufferPosition + length ) > _buffer . Length )
170+ if ( _bufferSize + length > _buffer . Length )
169171 throw new InternalBufferOverflowException ( ) ;
170172
171173 while ( length > 0 )
172174 {
173175 if ( ! _stream . DataAvailable )
174176 throw new EndOfStreamException ( ) ;
175177
176- int count = await _stream . ReadAsync ( _buffer , _bufferPosition , length ) ;
178+ var count = await _stream . ReadAsync ( _buffer . AsMemory ( _bufferSize , length ) ) ;
177179 length -= count ;
178- _bufferPosition += count ;
180+ _bufferSize += count ;
179181 }
180182 }
181183
182- private async Task < byte > GetOneByteOfPosition ( int position )
184+ private async Task < byte > GetOneByteAtPosition ( int position )
183185 {
184- await GetBytesToPosition ( position ) ;
185- return _buffer [ position - 1 ] ;
186- }
187-
188- private byte GetOneByteFromStream ( )
189- {
190- if ( ( _bufferPosition + 1 ) > _buffer . Length )
191- throw new InternalBufferOverflowException ( ) ;
192-
193- int readState = _stream . ReadByte ( ) ;
194- if ( readState < 0 )
195- throw new EndOfStreamException ( ) ;
196-
197- _buffer [ _bufferPosition ] = ( byte ) readState ;
198- _bufferPosition ++ ;
199- return ( byte ) readState ;
186+ await GetBytesTillBufferSize ( position + 1 ) ;
187+ return _buffer [ position ] ;
200188 }
189+
201190 #endregion
202191 }
203192}
0 commit comments