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