21
21
import java .io .PrintWriter ;
22
22
import java .io .Reader ;
23
23
import java .io .Writer ;
24
+ import java .nio .charset .Charset ;
24
25
import java .nio .charset .StandardCharsets ;
25
26
import java .util .concurrent .ConcurrentLinkedQueue ;
26
27
import java .util .concurrent .atomic .AtomicInteger ;
@@ -33,13 +34,14 @@ public class ProtocolServer {
33
34
private static final int BUFFER_SIZE = 4096 ;
34
35
private static final String TWO_CRLF = "\r \n \r \n " ;
35
36
private static final Pattern CONTENT_LENGTH_MATCHER = Pattern .compile ("Content-Length: (\\ d+)" );
37
+ private static final Charset PROTOCOL_ENCODING = StandardCharsets .UTF_8 ; // vscode protocol uses UTF-8 as encoding format.
36
38
37
39
private Reader reader ;
38
40
private Writer writer ;
39
41
40
- private CharBuffer rawData ;
42
+ private ByteBuffer rawData ;
41
43
private boolean terminateSession = false ;
42
- private int bodyLength = -1 ;
44
+ private int contentLength = -1 ;
43
45
private AtomicInteger sequenceNumber = new AtomicInteger (1 );
44
46
45
47
private boolean isDispatchingData ;
@@ -57,10 +59,10 @@ public class ProtocolServer {
57
59
* provider context for a series of provider implementation
58
60
*/
59
61
public ProtocolServer (InputStream input , OutputStream output , IProviderContext context ) {
60
- this .reader = new BufferedReader (new InputStreamReader (input , StandardCharsets . UTF_8 ));
61
- this .writer = new PrintWriter (new BufferedWriter (new OutputStreamWriter (output , StandardCharsets . UTF_8 )));
62
- this .bodyLength = -1 ;
63
- this .rawData = new CharBuffer ();
62
+ this .reader = new BufferedReader (new InputStreamReader (input , PROTOCOL_ENCODING ));
63
+ this .writer = new PrintWriter (new BufferedWriter (new OutputStreamWriter (output , PROTOCOL_ENCODING )));
64
+ this .contentLength = -1 ;
65
+ this .rawData = new ByteBuffer ();
64
66
this .eventQueue = new ConcurrentLinkedQueue <>();
65
67
this .debugAdapter = new DebugAdapter ((debugEvent , willSendLater ) -> {
66
68
// If the protocolServer has been stopped, it'll no longer receive any event.
@@ -86,7 +88,7 @@ public void start() {
86
88
break ;
87
89
}
88
90
89
- this .rawData .append (buffer , read );
91
+ this .rawData .append (new String ( buffer , 0 , read ). getBytes ( PROTOCOL_ENCODING ) );
90
92
this .processData ();
91
93
}
92
94
} catch (IOException e ) {
@@ -134,16 +136,16 @@ private void sendMessage(Messages.ProtocolMessage message) {
134
136
message .seq = this .sequenceNumber .getAndIncrement ();
135
137
136
138
String jsonMessage = JsonUtils .toJson (message );
137
- byte [] jsonBytes = jsonMessage .getBytes (StandardCharsets . UTF_8 );
139
+ byte [] jsonBytes = jsonMessage .getBytes (PROTOCOL_ENCODING );
138
140
139
141
String header = String .format ("Content-Length: %d%s" , jsonBytes .length , TWO_CRLF );
140
- byte [] headerBytes = header .getBytes (StandardCharsets . UTF_8 );
142
+ byte [] headerBytes = header .getBytes (PROTOCOL_ENCODING );
141
143
142
144
byte [] data = new byte [headerBytes .length + jsonBytes .length ];
143
145
System .arraycopy (headerBytes , 0 , data , 0 , headerBytes .length );
144
146
System .arraycopy (jsonBytes , 0 , data , headerBytes .length , jsonBytes .length );
145
147
146
- String utf8Data = new String (data , StandardCharsets . UTF_8 );
148
+ String utf8Data = new String (data , PROTOCOL_ENCODING );
147
149
148
150
try {
149
151
Logger .logInfo ("\n [[RESPONSE]]\n " + new String (data ));
@@ -156,21 +158,25 @@ private void sendMessage(Messages.ProtocolMessage message) {
156
158
157
159
private void processData () {
158
160
while (true ) {
159
- if (this .bodyLength >= 0 ) {
160
- if (this .rawData .length () >= this .bodyLength ) {
161
- char [] buf = this .rawData .removeFirst (this .bodyLength );
162
- this .bodyLength = -1 ;
163
- dispatchRequest (new String (buf ));
161
+ /**
162
+ * In vscode debug protocol, the content length represents the message's byte length with utf8 format.
163
+ */
164
+ if (this .contentLength >= 0 ) {
165
+ if (this .rawData .length () >= this .contentLength ) {
166
+ byte [] buf = this .rawData .removeFirst (this .contentLength );
167
+ this .contentLength = -1 ;
168
+ dispatchRequest (new String (buf , PROTOCOL_ENCODING ));
164
169
continue ;
165
170
}
166
171
} else {
167
- String body = this .rawData .getString ();
168
- int idx = body .indexOf (TWO_CRLF );
172
+ String rawMessage = this .rawData .getString (PROTOCOL_ENCODING );
173
+ int idx = rawMessage .indexOf (TWO_CRLF );
169
174
if (idx != -1 ) {
170
- Matcher matcher = CONTENT_LENGTH_MATCHER .matcher (body );
175
+ Matcher matcher = CONTENT_LENGTH_MATCHER .matcher (rawMessage );
171
176
if (matcher .find ()) {
172
- this .bodyLength = Integer .parseInt (matcher .group (1 ));
173
- this .rawData .removeFirst (idx + TWO_CRLF .length ());
177
+ this .contentLength = Integer .parseInt (matcher .group (1 ));
178
+ int headerByteLength = rawMessage .substring (0 , idx + TWO_CRLF .length ()).getBytes (PROTOCOL_ENCODING ).length ;
179
+ this .rawData .removeFirst (headerByteLength ); // Remove the header from the raw message.
174
180
continue ;
175
181
}
176
182
}
@@ -209,32 +215,36 @@ private void dispatchRequest(String request) {
209
215
}
210
216
}
211
217
212
- class CharBuffer {
213
- private char [] buffer ;
218
+ class ByteBuffer {
219
+ private byte [] buffer ;
214
220
215
- public CharBuffer () {
216
- this .buffer = new char [0 ];
221
+ public ByteBuffer () {
222
+ this .buffer = new byte [0 ];
217
223
}
218
224
219
225
public int length () {
220
226
return this .buffer .length ;
221
227
}
222
228
223
- public String getString () {
224
- return new String (this .buffer );
229
+ public String getString (Charset cs ) {
230
+ return new String (this .buffer , cs );
225
231
}
226
232
227
- public void append (char [] b , int length ) {
228
- char [] newBuffer = new char [this .buffer .length + length ];
233
+ public void append (byte [] b ) {
234
+ append (b , b .length );
235
+ }
236
+
237
+ public void append (byte [] b , int length ) {
238
+ byte [] newBuffer = new byte [this .buffer .length + length ];
229
239
System .arraycopy (buffer , 0 , newBuffer , 0 , this .buffer .length );
230
240
System .arraycopy (b , 0 , newBuffer , this .buffer .length , length );
231
241
this .buffer = newBuffer ;
232
242
}
233
243
234
- public char [] removeFirst (int n ) {
235
- char [] b = new char [n ];
244
+ public byte [] removeFirst (int n ) {
245
+ byte [] b = new byte [n ];
236
246
System .arraycopy (this .buffer , 0 , b , 0 , n );
237
- char [] newBuffer = new char [this .buffer .length - n ];
247
+ byte [] newBuffer = new byte [this .buffer .length - n ];
238
248
System .arraycopy (this .buffer , n , newBuffer , 0 , this .buffer .length - n );
239
249
this .buffer = newBuffer ;
240
250
return b ;
0 commit comments