Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/transport/socket/socketTransport.c
38813 views
1
/*
2
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
#include <stdio.h>
26
#include <string.h>
27
#include <errno.h>
28
#include <stdlib.h>
29
#include <ctype.h>
30
31
#include "jdwpTransport.h"
32
#include "sysSocket.h"
33
34
/*
35
* The Socket Transport Library.
36
*
37
* This module is an implementation of the Java Debug Wire Protocol Transport
38
* Service Provider Interface - see src/share/javavm/export/jdwpTransport.h.
39
*/
40
41
static int serverSocketFD;
42
static int socketFD = -1;
43
static jdwpTransportCallback *callback;
44
static JavaVM *jvm;
45
static int tlsIndex;
46
static jboolean initialized;
47
static struct jdwpTransportNativeInterface_ interface;
48
static jdwpTransportEnv single_env = (jdwpTransportEnv)&interface;
49
50
#define RETURN_ERROR(err, msg) \
51
if (1==1) { \
52
setLastError(err, msg); \
53
return err; \
54
}
55
56
#define RETURN_IO_ERROR(msg) RETURN_ERROR(JDWPTRANSPORT_ERROR_IO_ERROR, msg);
57
58
#define RETURN_RECV_ERROR(n) \
59
if (n == 0) { \
60
RETURN_ERROR(JDWPTRANSPORT_ERROR_IO_ERROR, "premature EOF"); \
61
} else { \
62
RETURN_IO_ERROR("recv error"); \
63
}
64
65
#define HEADER_SIZE 11
66
#define MAX_DATA_SIZE 1000
67
68
static jint recv_fully(int, char *, int);
69
static jint send_fully(int, char *, int);
70
71
/*
72
* Record the last error for this thread.
73
*/
74
static void
75
setLastError(jdwpTransportError err, char *newmsg) {
76
char buf[255];
77
char *msg;
78
79
/* get any I/O first in case any system calls override errno */
80
if (err == JDWPTRANSPORT_ERROR_IO_ERROR) {
81
dbgsysGetLastIOError(buf, sizeof(buf));
82
}
83
84
msg = (char *)dbgsysTlsGet(tlsIndex);
85
if (msg != NULL) {
86
(*callback->free)(msg);
87
}
88
89
if (err == JDWPTRANSPORT_ERROR_IO_ERROR) {
90
char *join_str = ": ";
91
int msg_len = (int)strlen(newmsg) + (int)strlen(join_str) +
92
(int)strlen(buf) + 3;
93
msg = (*callback->alloc)(msg_len);
94
if (msg != NULL) {
95
strcpy(msg, newmsg);
96
strcat(msg, join_str);
97
strcat(msg, buf);
98
}
99
} else {
100
msg = (*callback->alloc)((int)strlen(newmsg)+1);
101
if (msg != NULL) {
102
strcpy(msg, newmsg);
103
}
104
}
105
106
dbgsysTlsPut(tlsIndex, msg);
107
}
108
109
/*
110
* Return the last error for this thread (may be NULL)
111
*/
112
static char*
113
getLastError() {
114
return (char *)dbgsysTlsGet(tlsIndex);
115
}
116
117
static jdwpTransportError
118
setOptions(int fd)
119
{
120
jvalue dontcare;
121
int err;
122
123
dontcare.i = 0; /* keep compiler happy */
124
125
err = dbgsysSetSocketOption(fd, SO_REUSEADDR, JNI_TRUE, dontcare);
126
if (err < 0) {
127
RETURN_IO_ERROR("setsockopt SO_REUSEADDR failed");
128
}
129
130
err = dbgsysSetSocketOption(fd, TCP_NODELAY, JNI_TRUE, dontcare);
131
if (err < 0) {
132
RETURN_IO_ERROR("setsockopt TCPNODELAY failed");
133
}
134
135
return JDWPTRANSPORT_ERROR_NONE;
136
}
137
138
static jdwpTransportError
139
handshake(int fd, jlong timeout) {
140
const char *hello = "JDWP-Handshake";
141
char b[16];
142
int rv, helloLen, received;
143
144
if (timeout > 0) {
145
dbgsysConfigureBlocking(fd, JNI_FALSE);
146
}
147
helloLen = (int)strlen(hello);
148
received = 0;
149
while (received < helloLen) {
150
int n;
151
char *buf;
152
if (timeout > 0) {
153
rv = dbgsysPoll(fd, JNI_TRUE, JNI_FALSE, (long)timeout);
154
if (rv <= 0) {
155
setLastError(0, "timeout during handshake");
156
return JDWPTRANSPORT_ERROR_IO_ERROR;
157
}
158
}
159
buf = b;
160
buf += received;
161
n = recv_fully(fd, buf, helloLen-received);
162
if (n == 0) {
163
setLastError(0, "handshake failed - connection prematurally closed");
164
return JDWPTRANSPORT_ERROR_IO_ERROR;
165
}
166
if (n < 0) {
167
RETURN_IO_ERROR("recv failed during handshake");
168
}
169
received += n;
170
}
171
if (timeout > 0) {
172
dbgsysConfigureBlocking(fd, JNI_TRUE);
173
}
174
if (strncmp(b, hello, received) != 0) {
175
char msg[80+2*16];
176
b[received] = '\0';
177
/*
178
* We should really use snprintf here but it's not available on Windows.
179
* We can't use jio_snprintf without linking the transport against the VM.
180
*/
181
sprintf(msg, "handshake failed - received >%s< - expected >%s<", b, hello);
182
setLastError(0, msg);
183
return JDWPTRANSPORT_ERROR_IO_ERROR;
184
}
185
186
if (send_fully(fd, (char*)hello, helloLen) != helloLen) {
187
RETURN_IO_ERROR("send failed during handshake");
188
}
189
return JDWPTRANSPORT_ERROR_NONE;
190
}
191
192
static jdwpTransportError
193
parseAddress(const char *address, struct sockaddr_in *sa, uint32_t defaultHost) {
194
char *colon;
195
196
memset((void *)sa,0,sizeof(struct sockaddr_in));
197
sa->sin_family = AF_INET;
198
199
/* check for host:port or port */
200
colon = strchr(address, ':');
201
if (colon == NULL) {
202
u_short port = (u_short)atoi(address);
203
sa->sin_port = dbgsysHostToNetworkShort(port);
204
sa->sin_addr.s_addr = dbgsysHostToNetworkLong(defaultHost);
205
} else {
206
char *buf;
207
char *hostname;
208
u_short port;
209
uint32_t addr;
210
211
buf = (*callback->alloc)((int)strlen(address)+1);
212
if (buf == NULL) {
213
RETURN_ERROR(JDWPTRANSPORT_ERROR_OUT_OF_MEMORY, "out of memory");
214
}
215
strcpy(buf, address);
216
buf[colon - address] = '\0';
217
hostname = buf;
218
port = atoi(colon + 1);
219
sa->sin_port = dbgsysHostToNetworkShort(port);
220
221
/*
222
* First see if the host is a literal IP address.
223
* If not then try to resolve it.
224
*/
225
addr = dbgsysInetAddr(hostname);
226
if (addr == 0xffffffff) {
227
struct hostent *hp = dbgsysGetHostByName(hostname);
228
if (hp == NULL) {
229
/* don't use RETURN_IO_ERROR as unknown host is normal */
230
setLastError(0, "gethostbyname: unknown host");
231
(*callback->free)(buf);
232
return JDWPTRANSPORT_ERROR_IO_ERROR;
233
}
234
235
/* lookup was successful */
236
memcpy(&(sa->sin_addr), hp->h_addr_list[0], hp->h_length);
237
} else {
238
sa->sin_addr.s_addr = addr;
239
}
240
241
(*callback->free)(buf);
242
}
243
244
return JDWPTRANSPORT_ERROR_NONE;
245
}
246
247
248
static jdwpTransportError JNICALL
249
socketTransport_getCapabilities(jdwpTransportEnv* env,
250
JDWPTransportCapabilities* capabilitiesPtr)
251
{
252
JDWPTransportCapabilities result;
253
254
memset(&result, 0, sizeof(result));
255
result.can_timeout_attach = JNI_TRUE;
256
result.can_timeout_accept = JNI_TRUE;
257
result.can_timeout_handshake = JNI_TRUE;
258
259
*capabilitiesPtr = result;
260
261
return JDWPTRANSPORT_ERROR_NONE;
262
}
263
264
265
static jdwpTransportError JNICALL
266
socketTransport_startListening(jdwpTransportEnv* env, const char* address,
267
char** actualAddress)
268
{
269
struct sockaddr_in sa;
270
int err;
271
272
memset((void *)&sa,0,sizeof(struct sockaddr_in));
273
sa.sin_family = AF_INET;
274
275
/* no address provided */
276
if ((address == NULL) || (address[0] == '\0')) {
277
address = "0";
278
}
279
280
err = parseAddress(address, &sa, INADDR_ANY);
281
if (err != JDWPTRANSPORT_ERROR_NONE) {
282
return err;
283
}
284
285
serverSocketFD = dbgsysSocket(AF_INET, SOCK_STREAM, 0);
286
if (serverSocketFD < 0) {
287
RETURN_IO_ERROR("socket creation failed");
288
}
289
290
err = setOptions(serverSocketFD);
291
if (err) {
292
return err;
293
}
294
295
err = dbgsysBind(serverSocketFD, (struct sockaddr *)&sa, sizeof(sa));
296
if (err < 0) {
297
RETURN_IO_ERROR("bind failed");
298
}
299
300
err = dbgsysListen(serverSocketFD, 1);
301
if (err < 0) {
302
RETURN_IO_ERROR("listen failed");
303
}
304
305
{
306
char buf[20];
307
socklen_t len = sizeof(sa);
308
jint portNum;
309
err = dbgsysGetSocketName(serverSocketFD,
310
(struct sockaddr *)&sa, &len);
311
portNum = dbgsysNetworkToHostShort(sa.sin_port);
312
sprintf(buf, "%d", portNum);
313
*actualAddress = (*callback->alloc)((int)strlen(buf) + 1);
314
if (*actualAddress == NULL) {
315
RETURN_ERROR(JDWPTRANSPORT_ERROR_OUT_OF_MEMORY, "out of memory");
316
} else {
317
strcpy(*actualAddress, buf);
318
}
319
}
320
321
return JDWPTRANSPORT_ERROR_NONE;
322
}
323
324
static jdwpTransportError JNICALL
325
socketTransport_accept(jdwpTransportEnv* env, jlong acceptTimeout, jlong handshakeTimeout)
326
{
327
socklen_t socketLen;
328
int err;
329
struct sockaddr_in socket;
330
jlong startTime = (jlong)0;
331
332
/*
333
* Use a default handshake timeout if not specified - this avoids an indefinite
334
* hang in cases where something other than a debugger connects to our port.
335
*/
336
if (handshakeTimeout == 0) {
337
handshakeTimeout = 2000;
338
}
339
340
do {
341
/*
342
* If there is an accept timeout then we put the socket in non-blocking
343
* mode and poll for a connection.
344
*/
345
if (acceptTimeout > 0) {
346
int rv;
347
dbgsysConfigureBlocking(serverSocketFD, JNI_FALSE);
348
startTime = dbgsysCurrentTimeMillis();
349
rv = dbgsysPoll(serverSocketFD, JNI_TRUE, JNI_FALSE, (long)acceptTimeout);
350
if (rv <= 0) {
351
/* set the last error here as could be overridden by configureBlocking */
352
if (rv == 0) {
353
setLastError(JDWPTRANSPORT_ERROR_IO_ERROR, "poll failed");
354
}
355
/* restore blocking state */
356
dbgsysConfigureBlocking(serverSocketFD, JNI_TRUE);
357
if (rv == 0) {
358
RETURN_ERROR(JDWPTRANSPORT_ERROR_TIMEOUT, "timed out waiting for connection");
359
} else {
360
return JDWPTRANSPORT_ERROR_IO_ERROR;
361
}
362
}
363
}
364
365
/*
366
* Accept the connection
367
*/
368
memset((void *)&socket,0,sizeof(struct sockaddr_in));
369
socketLen = sizeof(socket);
370
socketFD = dbgsysAccept(serverSocketFD,
371
(struct sockaddr *)&socket,
372
&socketLen);
373
/* set the last error here as could be overridden by configureBlocking */
374
if (socketFD < 0) {
375
setLastError(JDWPTRANSPORT_ERROR_IO_ERROR, "accept failed");
376
}
377
/*
378
* Restore the blocking state - note that the accepted socket may be in
379
* blocking or non-blocking mode (platform dependent). However as there
380
* is a handshake timeout set then it will go into non-blocking mode
381
* anyway for the handshake.
382
*/
383
if (acceptTimeout > 0) {
384
dbgsysConfigureBlocking(serverSocketFD, JNI_TRUE);
385
}
386
if (socketFD < 0) {
387
return JDWPTRANSPORT_ERROR_IO_ERROR;
388
}
389
390
/* handshake with the debugger */
391
err = handshake(socketFD, handshakeTimeout);
392
393
/*
394
* If the handshake fails then close the connection. If there if an accept
395
* timeout then we must adjust the timeout for the next poll.
396
*/
397
if (err) {
398
fprintf(stderr, "Debugger failed to attach: %s\n", getLastError());
399
dbgsysSocketClose(socketFD);
400
socketFD = -1;
401
if (acceptTimeout > 0) {
402
long endTime = dbgsysCurrentTimeMillis();
403
acceptTimeout -= (endTime - startTime);
404
if (acceptTimeout <= 0) {
405
setLastError(JDWPTRANSPORT_ERROR_IO_ERROR,
406
"timeout waiting for debugger to connect");
407
return JDWPTRANSPORT_ERROR_IO_ERROR;
408
}
409
}
410
}
411
} while (socketFD < 0);
412
413
return JDWPTRANSPORT_ERROR_NONE;
414
}
415
416
static jdwpTransportError JNICALL
417
socketTransport_stopListening(jdwpTransportEnv *env)
418
{
419
if (serverSocketFD < 0) {
420
RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_STATE, "connection not open");
421
}
422
if (dbgsysSocketClose(serverSocketFD) < 0) {
423
RETURN_IO_ERROR("close failed");
424
}
425
serverSocketFD = -1;
426
return JDWPTRANSPORT_ERROR_NONE;
427
}
428
429
static jdwpTransportError JNICALL
430
socketTransport_attach(jdwpTransportEnv* env, const char* addressString, jlong attachTimeout,
431
jlong handshakeTimeout)
432
{
433
struct sockaddr_in sa;
434
int err;
435
436
if (addressString == NULL || addressString[0] == '\0') {
437
RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "address is missing");
438
}
439
440
err = parseAddress(addressString, &sa, 0x7f000001);
441
if (err != JDWPTRANSPORT_ERROR_NONE) {
442
return err;
443
}
444
445
socketFD = dbgsysSocket(AF_INET, SOCK_STREAM, 0);
446
if (socketFD < 0) {
447
RETURN_IO_ERROR("unable to create socket");
448
}
449
450
err = setOptions(socketFD);
451
if (err) {
452
return err;
453
}
454
455
/*
456
* To do a timed connect we make the socket non-blocking
457
* and poll with a timeout;
458
*/
459
if (attachTimeout > 0) {
460
dbgsysConfigureBlocking(socketFD, JNI_FALSE);
461
}
462
463
err = dbgsysConnect(socketFD, (struct sockaddr *)&sa, sizeof(sa));
464
if (err == DBG_EINPROGRESS && attachTimeout > 0) {
465
err = dbgsysFinishConnect(socketFD, (long)attachTimeout);
466
467
if (err == DBG_ETIMEOUT) {
468
dbgsysConfigureBlocking(socketFD, JNI_TRUE);
469
RETURN_ERROR(JDWPTRANSPORT_ERROR_TIMEOUT, "connect timed out");
470
}
471
}
472
473
if (err < 0) {
474
RETURN_IO_ERROR("connect failed");
475
}
476
477
if (attachTimeout > 0) {
478
dbgsysConfigureBlocking(socketFD, JNI_TRUE);
479
}
480
481
err = handshake(socketFD, handshakeTimeout);
482
if (err) {
483
dbgsysSocketClose(socketFD);
484
socketFD = -1;
485
return err;
486
}
487
488
return JDWPTRANSPORT_ERROR_NONE;
489
}
490
491
static jboolean JNICALL
492
socketTransport_isOpen(jdwpTransportEnv* env)
493
{
494
if (socketFD >= 0) {
495
return JNI_TRUE;
496
} else {
497
return JNI_FALSE;
498
}
499
}
500
501
static jdwpTransportError JNICALL
502
socketTransport_close(jdwpTransportEnv* env)
503
{
504
int fd = socketFD;
505
socketFD = -1;
506
if (fd < 0) {
507
return JDWPTRANSPORT_ERROR_NONE;
508
}
509
#ifdef _AIX
510
/*
511
AIX needs a workaround for I/O cancellation, see:
512
http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/close.htm
513
...
514
The close subroutine is blocked until all subroutines which use the file
515
descriptor return to usr space. For example, when a thread is calling close
516
and another thread is calling select with the same file descriptor, the
517
close subroutine does not return until the select call returns.
518
...
519
*/
520
shutdown(fd, 2);
521
#endif
522
if (dbgsysSocketClose(fd) < 0) {
523
/*
524
* close failed - it's pointless to restore socketFD here because
525
* any subsequent close will likely fail as well.
526
*/
527
RETURN_IO_ERROR("close failed");
528
}
529
return JDWPTRANSPORT_ERROR_NONE;
530
}
531
532
static jdwpTransportError JNICALL
533
socketTransport_writePacket(jdwpTransportEnv* env, const jdwpPacket *packet)
534
{
535
jint len, data_len, id;
536
/*
537
* room for header and up to MAX_DATA_SIZE data bytes
538
*/
539
char header[HEADER_SIZE + MAX_DATA_SIZE];
540
jbyte *data;
541
542
/* packet can't be null */
543
if (packet == NULL) {
544
RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "packet is NULL");
545
}
546
547
len = packet->type.cmd.len; /* includes header */
548
data_len = len - HEADER_SIZE;
549
550
/* bad packet */
551
if (data_len < 0) {
552
RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "invalid length");
553
}
554
555
/* prepare the header for transmission */
556
len = (jint)dbgsysHostToNetworkLong(len);
557
id = (jint)dbgsysHostToNetworkLong(packet->type.cmd.id);
558
559
memcpy(header + 0, &len, 4);
560
memcpy(header + 4, &id, 4);
561
header[8] = packet->type.cmd.flags;
562
if (packet->type.cmd.flags & JDWPTRANSPORT_FLAGS_REPLY) {
563
jshort errorCode =
564
dbgsysHostToNetworkShort(packet->type.reply.errorCode);
565
memcpy(header + 9, &errorCode, 2);
566
} else {
567
header[9] = packet->type.cmd.cmdSet;
568
header[10] = packet->type.cmd.cmd;
569
}
570
571
data = packet->type.cmd.data;
572
/* Do one send for short packets, two for longer ones */
573
if (data_len <= MAX_DATA_SIZE) {
574
memcpy(header + HEADER_SIZE, data, data_len);
575
if (send_fully(socketFD, (char *)&header, HEADER_SIZE + data_len) !=
576
HEADER_SIZE + data_len) {
577
RETURN_IO_ERROR("send failed");
578
}
579
} else {
580
memcpy(header + HEADER_SIZE, data, MAX_DATA_SIZE);
581
if (send_fully(socketFD, (char *)&header, HEADER_SIZE + MAX_DATA_SIZE) !=
582
HEADER_SIZE + MAX_DATA_SIZE) {
583
RETURN_IO_ERROR("send failed");
584
}
585
/* Send the remaining data bytes right out of the data area. */
586
if (send_fully(socketFD, (char *)data + MAX_DATA_SIZE,
587
data_len - MAX_DATA_SIZE) != data_len - MAX_DATA_SIZE) {
588
RETURN_IO_ERROR("send failed");
589
}
590
}
591
592
return JDWPTRANSPORT_ERROR_NONE;
593
}
594
595
static jint
596
recv_fully(int f, char *buf, int len)
597
{
598
int nbytes = 0;
599
while (nbytes < len) {
600
int res = dbgsysRecv(f, buf + nbytes, len - nbytes, 0);
601
if (res < 0) {
602
return res;
603
} else if (res == 0) {
604
break; /* eof, return nbytes which is less than len */
605
}
606
nbytes += res;
607
}
608
return nbytes;
609
}
610
611
jint
612
send_fully(int f, char *buf, int len)
613
{
614
int nbytes = 0;
615
while (nbytes < len) {
616
int res = dbgsysSend(f, buf + nbytes, len - nbytes, 0);
617
if (res < 0) {
618
return res;
619
} else if (res == 0) {
620
break; /* eof, return nbytes which is less than len */
621
}
622
nbytes += res;
623
}
624
return nbytes;
625
}
626
627
static jdwpTransportError JNICALL
628
socketTransport_readPacket(jdwpTransportEnv* env, jdwpPacket* packet) {
629
jint length, data_len;
630
jint n;
631
632
/* packet can't be null */
633
if (packet == NULL) {
634
RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "packet is null");
635
}
636
637
/* read the length field */
638
n = recv_fully(socketFD, (char *)&length, sizeof(jint));
639
640
/* check for EOF */
641
if (n == 0) {
642
packet->type.cmd.len = 0;
643
return JDWPTRANSPORT_ERROR_NONE;
644
}
645
if (n != sizeof(jint)) {
646
RETURN_RECV_ERROR(n);
647
}
648
649
length = (jint)dbgsysNetworkToHostLong(length);
650
packet->type.cmd.len = length;
651
652
653
n = recv_fully(socketFD,(char *)&(packet->type.cmd.id),sizeof(jint));
654
if (n < (int)sizeof(jint)) {
655
RETURN_RECV_ERROR(n);
656
}
657
658
packet->type.cmd.id = (jint)dbgsysNetworkToHostLong(packet->type.cmd.id);
659
660
n = recv_fully(socketFD,(char *)&(packet->type.cmd.flags),sizeof(jbyte));
661
if (n < (int)sizeof(jbyte)) {
662
RETURN_RECV_ERROR(n);
663
}
664
665
if (packet->type.cmd.flags & JDWPTRANSPORT_FLAGS_REPLY) {
666
n = recv_fully(socketFD,(char *)&(packet->type.reply.errorCode),sizeof(jbyte));
667
if (n < (int)sizeof(jshort)) {
668
RETURN_RECV_ERROR(n);
669
}
670
671
/* FIXME - should the error be converted to host order?? */
672
673
674
} else {
675
n = recv_fully(socketFD,(char *)&(packet->type.cmd.cmdSet),sizeof(jbyte));
676
if (n < (int)sizeof(jbyte)) {
677
RETURN_RECV_ERROR(n);
678
}
679
680
n = recv_fully(socketFD,(char *)&(packet->type.cmd.cmd),sizeof(jbyte));
681
if (n < (int)sizeof(jbyte)) {
682
RETURN_RECV_ERROR(n);
683
}
684
}
685
686
data_len = length - ((sizeof(jint) * 2) + (sizeof(jbyte) * 3));
687
688
if (data_len < 0) {
689
setLastError(0, "Badly formed packet received - invalid length");
690
return JDWPTRANSPORT_ERROR_IO_ERROR;
691
} else if (data_len == 0) {
692
packet->type.cmd.data = NULL;
693
} else {
694
packet->type.cmd.data= (*callback->alloc)(data_len);
695
696
if (packet->type.cmd.data == NULL) {
697
RETURN_ERROR(JDWPTRANSPORT_ERROR_OUT_OF_MEMORY, "out of memory");
698
}
699
700
n = recv_fully(socketFD,(char *)packet->type.cmd.data, data_len);
701
if (n < data_len) {
702
(*callback->free)(packet->type.cmd.data);
703
RETURN_RECV_ERROR(n);
704
}
705
}
706
707
return JDWPTRANSPORT_ERROR_NONE;
708
}
709
710
static jdwpTransportError JNICALL
711
socketTransport_getLastError(jdwpTransportEnv* env, char** msgP) {
712
char *msg = (char *)dbgsysTlsGet(tlsIndex);
713
if (msg == NULL) {
714
return JDWPTRANSPORT_ERROR_MSG_NOT_AVAILABLE;
715
}
716
*msgP = (*callback->alloc)((int)strlen(msg)+1);
717
if (*msgP == NULL) {
718
return JDWPTRANSPORT_ERROR_OUT_OF_MEMORY;
719
}
720
strcpy(*msgP, msg);
721
return JDWPTRANSPORT_ERROR_NONE;
722
}
723
724
JNIEXPORT jint JNICALL
725
jdwpTransport_OnLoad(JavaVM *vm, jdwpTransportCallback* cbTablePtr,
726
jint version, jdwpTransportEnv** result)
727
{
728
if (version != JDWPTRANSPORT_VERSION_1_0) {
729
return JNI_EVERSION;
730
}
731
if (initialized) {
732
/*
733
* This library doesn't support multiple environments (yet)
734
*/
735
return JNI_EEXIST;
736
}
737
initialized = JNI_TRUE;
738
jvm = vm;
739
callback = cbTablePtr;
740
741
/* initialize interface table */
742
interface.GetCapabilities = &socketTransport_getCapabilities;
743
interface.Attach = &socketTransport_attach;
744
interface.StartListening = &socketTransport_startListening;
745
interface.StopListening = &socketTransport_stopListening;
746
interface.Accept = &socketTransport_accept;
747
interface.IsOpen = &socketTransport_isOpen;
748
interface.Close = &socketTransport_close;
749
interface.ReadPacket = &socketTransport_readPacket;
750
interface.WritePacket = &socketTransport_writePacket;
751
interface.GetLastError = &socketTransport_getLastError;
752
*result = &single_env;
753
754
/* initialized TLS */
755
tlsIndex = dbgsysTlsAlloc();
756
return JNI_OK;
757
}
758
759