/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <ctype.h>
#include "jdwpTransport.h"
#include "sysSocket.h"
/*
* The Socket Transport Library.
*
* This module is an implementation of the Java Debug Wire Protocol Transport
* Service Provider Interface - see src/share/javavm/export/jdwpTransport.h.
*/
static int serverSocketFD;
static int tlsIndex;
if (1==1) { \
return err; \
}
#define RETURN_RECV_ERROR(n) \
if (n == 0) { \
} else { \
RETURN_IO_ERROR("recv error"); \
}
static jint recv_fully(int, char *, int);
static jint send_fully(int, char *, int);
/*
* Record the last error for this thread.
*/
static void
char *msg;
/* get any I/O first in case any system calls override errno */
if (err == JDWPTRANSPORT_ERROR_IO_ERROR) {
}
}
if (err == JDWPTRANSPORT_ERROR_IO_ERROR) {
}
} else {
}
}
}
/*
* Return the last error for this thread (may be NULL)
*/
static char*
getLastError() {
return (char *)dbgsysTlsGet(tlsIndex);
}
static jdwpTransportError
{
int err;
dontcare.i = 0; /* keep compiler happy */
if (err < 0) {
RETURN_IO_ERROR("setsockopt SO_REUSEADDR failed");
}
if (err < 0) {
RETURN_IO_ERROR("setsockopt TCPNODELAY failed");
}
return JDWPTRANSPORT_ERROR_NONE;
}
static jdwpTransportError
char b[16];
if (timeout > 0) {
}
received = 0;
int n;
char *buf;
if (timeout > 0) {
if (rv <= 0) {
setLastError(0, "timeout during handshake");
return JDWPTRANSPORT_ERROR_IO_ERROR;
}
}
buf = b;
if (n == 0) {
setLastError(0, "handshake failed - connection prematurally closed");
return JDWPTRANSPORT_ERROR_IO_ERROR;
}
if (n < 0) {
RETURN_IO_ERROR("recv failed during handshake");
}
received += n;
}
if (timeout > 0) {
}
b[received] = '\0';
/*
* We should really use snprintf here but it's not available on Windows.
* We can't use jio_snprintf without linking the transport against the VM.
*/
setLastError(0, msg);
return JDWPTRANSPORT_ERROR_IO_ERROR;
}
RETURN_IO_ERROR("send failed during handshake");
}
return JDWPTRANSPORT_ERROR_NONE;
}
static jdwpTransportError
char *colon;
/* check for host:port or port */
} else {
char *buf;
char *hostname;
}
/*
* First see if the host is a literal IP address.
* If not then try to resolve it.
*/
if (addr == 0xffffffff) {
/* don't use RETURN_IO_ERROR as unknown host is normal */
setLastError(0, "gethostbyname: unknown host");
return JDWPTRANSPORT_ERROR_IO_ERROR;
}
/* lookup was successful */
} else {
}
}
return JDWPTRANSPORT_ERROR_NONE;
}
static jdwpTransportError JNICALL
{
return JDWPTRANSPORT_ERROR_NONE;
}
static jdwpTransportError JNICALL
char** actualAddress)
{
int err;
/* no address provided */
address = "0";
}
if (err != JDWPTRANSPORT_ERROR_NONE) {
return err;
}
if (serverSocketFD < 0) {
RETURN_IO_ERROR("socket creation failed");
}
if (err) {
return err;
}
if (err < 0) {
RETURN_IO_ERROR("bind failed");
}
if (err < 0) {
RETURN_IO_ERROR("listen failed");
}
{
if (*actualAddress == NULL) {
} else {
}
}
return JDWPTRANSPORT_ERROR_NONE;
}
static jdwpTransportError JNICALL
{
/*
* Use a default handshake timeout if not specified - this avoids an indefinite
* hang in cases where something other than a debugger connects to our port.
*/
if (handshakeTimeout == 0) {
handshakeTimeout = 2000;
}
do {
/*
* If there is an accept timeout then we put the socket in non-blocking
* mode and poll for a connection.
*/
if (acceptTimeout > 0) {
int rv;
if (rv <= 0) {
/* set the last error here as could be overridden by configureBlocking */
if (rv == 0) {
}
/* restore blocking state */
if (rv == 0) {
} else {
return JDWPTRANSPORT_ERROR_IO_ERROR;
}
}
}
/*
* Accept the connection
*/
&socketLen);
/* set the last error here as could be overridden by configureBlocking */
if (socketFD < 0) {
}
/*
* Restore the blocking state - note that the accepted socket may be in
* blocking or non-blocking mode (platform dependent). However as there
* is a handshake timeout set then it will go into non-blocking mode
* anyway for the handshake.
*/
if (acceptTimeout > 0) {
}
if (socketFD < 0) {
return JDWPTRANSPORT_ERROR_IO_ERROR;
}
/* handshake with the debugger */
/*
* If the handshake fails then close the connection. If there if an accept
* timeout then we must adjust the timeout for the next poll.
*/
if (err) {
socketFD = -1;
if (acceptTimeout > 0) {
if (acceptTimeout <= 0) {
"timeout waiting for debugger to connect");
return JDWPTRANSPORT_ERROR_IO_ERROR;
}
}
}
} while (socketFD < 0);
return JDWPTRANSPORT_ERROR_NONE;
}
static jdwpTransportError JNICALL
{
if (serverSocketFD < 0) {
}
if (dbgsysSocketClose(serverSocketFD) < 0) {
RETURN_IO_ERROR("close failed");
}
serverSocketFD = -1;
return JDWPTRANSPORT_ERROR_NONE;
}
static jdwpTransportError JNICALL
{
int err;
}
if (err != JDWPTRANSPORT_ERROR_NONE) {
return err;
}
if (socketFD < 0) {
RETURN_IO_ERROR("unable to create socket");
}
if (err) {
return err;
}
/*
* To do a timed connect we make the socket non-blocking
* and poll with a timeout;
*/
if (attachTimeout > 0) {
}
if (err == DBG_ETIMEOUT) {
}
}
if (err < 0) {
RETURN_IO_ERROR("connect failed");
}
if (attachTimeout > 0) {
}
if (err) {
socketFD = -1;
return err;
}
return JDWPTRANSPORT_ERROR_NONE;
}
{
if (socketFD >= 0) {
return JNI_TRUE;
} else {
return JNI_FALSE;
}
}
static jdwpTransportError JNICALL
{
socketFD = -1;
if (fd < 0) {
return JDWPTRANSPORT_ERROR_NONE;
}
if (dbgsysSocketClose(fd) < 0) {
/*
* close failed - it's pointless to restore socketFD here because
* any subsequent close will likely fail aswell.
*/
RETURN_IO_ERROR("close failed");
}
return JDWPTRANSPORT_ERROR_NONE;
}
static jdwpTransportError JNICALL
{
/*
* room for header and up to MAX_DATA_SIZE data bytes
*/
/* packet can't be null */
}
/* bad packet */
if (data_len < 0) {
}
/* prepare the header for transmission */
} else {
}
/* Do one send for short packets, two for longer ones */
if (data_len <= MAX_DATA_SIZE) {
HEADER_SIZE + data_len) {
RETURN_IO_ERROR("send failed");
}
} else {
HEADER_SIZE + MAX_DATA_SIZE) {
RETURN_IO_ERROR("send failed");
}
/* Send the remaining data bytes right out of the data area. */
RETURN_IO_ERROR("send failed");
}
}
return JDWPTRANSPORT_ERROR_NONE;
}
static jint
{
int nbytes = 0;
if (res < 0) {
return res;
} else if (res == 0) {
break; /* eof, return nbytes which is less than len */
}
}
return nbytes;
}
{
int nbytes = 0;
if (res < 0) {
return res;
} else if (res == 0) {
break; /* eof, return nbytes which is less than len */
}
}
return nbytes;
}
static jdwpTransportError JNICALL
jint n;
/* packet can't be null */
}
/* read the length field */
/* check for EOF */
if (n == 0) {
return JDWPTRANSPORT_ERROR_NONE;
}
if (n != sizeof(jint)) {
}
if (n < (int)sizeof(jint)) {
}
if (n < (int)sizeof(jbyte)) {
}
if (n < (int)sizeof(jshort)) {
}
/* FIXME - should the error be converted to host order?? */
} else {
if (n < (int)sizeof(jbyte)) {
}
if (n < (int)sizeof(jbyte)) {
}
}
if (data_len < 0) {
setLastError(0, "Badly formed packet received - invalid length");
return JDWPTRANSPORT_ERROR_IO_ERROR;
} else if (data_len == 0) {
} else {
}
if (n < data_len) {
}
}
return JDWPTRANSPORT_ERROR_NONE;
}
static jdwpTransportError JNICALL
}
}
return JDWPTRANSPORT_ERROR_NONE;
}
{
if (version != JDWPTRANSPORT_VERSION_1_0) {
return JNI_EVERSION;
}
if (initialized) {
/*
* This library doesn't support multiple environments (yet)
*/
return JNI_EEXIST;
}
/* initialize interface table */
*result = &single_env;
/* initialized TLS */
tlsIndex = dbgsysTlsAlloc();
return JNI_OK;
}