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