sockettransport.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 754 行 · 第 1/2 页

C
754
字号
/* * @(#)socketTransport.c	1.34 06/10/26 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved.   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER   *    * This program is free software; you can redistribute it and/or   * modify it under the terms of the GNU General Public License version   * 2 only, as published by the Free Software Foundation.    *    * This program 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 at /legal/license.txt).    *    * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa   * Clara, CA 95054 or visit www.sun.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"#include "JDWP.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 = -1;static int socketFD = -1;static jdwpTransportCallback *callback;static JavaVM *jvm;static int tlsIndex;static jboolean initialized;static struct jdwpTransportNativeInterface_ jdwpInterface;static jdwpTransportEnv single_env = (jdwpTransportEnv)&jdwpInterface;#define RETURN_ERROR(err, msg) \	if (1==1) { \            setLastError(err, msg); \            return err; \        } #define RETURN_IO_ERROR(msg)	RETURN_ERROR(JDWPTRANSPORT_ERROR_IO_ERROR, msg);#define RETURN_RECV_ERROR(n) \	if (n == 0) { \	    RETURN_ERROR(JDWPTRANSPORT_ERROR_IO_ERROR, "premature EOF"); \	} else { \	    RETURN_IO_ERROR("recv error"); \	} #define HEADER_SIZE	11#define MAX_DATA_SIZE 1000/* * Record the last error for this thread. */static voidsetLastError(jdwpTransportError err, char *newmsg) {    char buf[255];    char *msg;        /* get any I/O first in case any system calls override errno */    if (err == JDWPTRANSPORT_ERROR_IO_ERROR) {	dbgsysGetLastIOError(buf, sizeof(buf));    }    msg = (char *)dbgsysTlsGet(tlsIndex);    if (msg != NULL) {        (*callback->free)(msg);    }    if (err == JDWPTRANSPORT_ERROR_IO_ERROR) {	char *join_str = ": ";	int msg_len = strlen(newmsg) + strlen(join_str) + strlen(buf) + 3;		msg = (*callback->alloc)(msg_len);	if (msg != NULL) {	    strcpy(msg, newmsg);	    strcat(msg, join_str);	    strcat(msg, buf);	}    } else {	msg = (*callback->alloc)(strlen(newmsg)+1);        if (msg != NULL) {            strcpy(msg, newmsg);         }    }    dbgsysTlsPut(tlsIndex, msg);}/* * Return the last error for this thread (may be NULL) */static char*getLastError() {    return (char *)dbgsysTlsGet(tlsIndex);    }static jdwpTransportError setOptions(int fd) {    jvalue dontcare = {0};    int err;     dontcare.i = 0;  /* keep compiler happy */        err = dbgsysSetSocketOption(fd, SO_REUSEADDR, JNI_TRUE, dontcare);                         if (err < 0) {                                                              	RETURN_IO_ERROR("setsockopt SO_REUSEADDR failed");    }        err = dbgsysSetSocketOption(fd, TCP_NODELAY, JNI_TRUE, dontcare);    if (err < 0) {        RETURN_IO_ERROR("setsockopt TCPNODELAY failed");    }    return JDWPTRANSPORT_ERROR_NONE;}static jdwpTransportError handshake(int fd, jlong timeout) {    char *hello = "JDWP-Handshake";    char b[16];    int rv, received, i;    if (timeout > 0) {        dbgsysConfigureBlocking(fd, JNI_FALSE);    }    received = 0;    while (received < (int)strlen(hello)) {        int n; 	char *buf;		if (timeout > 0) {	    rv = dbgsysPoll(fd, JNI_TRUE, JNI_FALSE, (long)timeout);	    if (rv <= 0) {		setLastError(0, "timeout during handshake");                return JDWPTRANSPORT_ERROR_IO_ERROR;	    }	}	buf = b;	buf += received;	n = dbgsysRecv(fd, buf, strlen(hello)-received, 0);	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) {	dbgsysConfigureBlocking(fd, JNI_TRUE);    }    for (i=0; i<(int)strlen(hello); i++) {        if (b[i] != hello[i]) {	    char msg[64];	    strcpy(msg, "handshake failed - received >");	    strncat(msg, b, strlen(hello));	    strcat(msg, "< - excepted >");	    strcat(msg, hello);	    strcat(msg, "<");	    setLastError(0, msg);	    return JDWPTRANSPORT_ERROR_IO_ERROR;	}    }    if (dbgsysSend(fd, hello, strlen(hello), 0) != (int)strlen(hello)) {	RETURN_IO_ERROR("send failed during handshake");    }    return JDWPTRANSPORT_ERROR_NONE;}static jdwpTransportErrorparseAddress(const char *address, struct sockaddr_in *sa, U_SOCKINT32 defaultHost) {    char *colon;    memset((void *)sa,0,sizeof(struct sockaddr_in));    sa->sin_family = AF_INET;    /* check for host:port or port */    colon = strchr(address, ':');    if (colon == NULL) {        u_short port = (u_short)atoi(address);        sa->sin_port = dbgsysHostToNetworkShort(port);        sa->sin_addr.s_addr = dbgsysHostToNetworkLong(defaultHost);    } else {        char *buf;        char *hostname;        u_short port;        U_SOCKINT32 addr;        buf = (*callback->alloc)(strlen(address)+1);        if (buf == NULL) {            RETURN_ERROR(JDWPTRANSPORT_ERROR_OUT_OF_MEMORY, "out of memory");        }        strcpy(buf, address);        buf[colon - address] = '\0';        hostname = buf;        port = atoi(colon + 1);        sa->sin_port = dbgsysHostToNetworkShort(port);        /*         * First see if the host is a literal IP address.         * If not then try to resolve it.         */        addr = dbgsysInetAddr(hostname);        if (addr == 0xffffffff) {            struct hostent *hp = dbgsysGetHostByName(hostname);            if (hp == NULL) {                /* don't use RETURN_IO_ERROR as unknown host is normal */                setLastError(0, "gethostbyname: unknown host");                (*callback->free)(buf);                return JDWPTRANSPORT_ERROR_IO_ERROR;            }            /* lookup was successful */            memcpy(&(sa->sin_addr), hp->h_addr_list[0], hp->h_length);        } else {            sa->sin_addr.s_addr = addr;        }        (*callback->free)(buf);    }    return JDWPTRANSPORT_ERROR_NONE;}static jdwpTransportError JNICALLsocketTransport_getCapabilities(jdwpTransportEnv* env, 	JDWPTransportCapabilities* capabilitiesPtr) {    JDWPTransportCapabilities result;    memset(&result, 0, sizeof(result));    result.can_timeout_attach = JNI_TRUE;    result.can_timeout_accept = JNI_TRUE;    result.can_timeout_handshake = JNI_TRUE;    *capabilitiesPtr = result;    return JDWPTRANSPORT_ERROR_NONE;}static jdwpTransportError JNICALLsocketTransport_startListening(jdwpTransportEnv* env, const char* address, 		               char** actualAddress){    struct sockaddr_in sa;		    int err;    memset((void *)&sa,0,sizeof(struct sockaddr_in));    sa.sin_family = AF_INET;    /* no address provided */    if ((address == NULL) || (address[0] == '\0')) {	address = "0";    }    err = parseAddress(address, &sa, INADDR_ANY);    if (err != JDWPTRANSPORT_ERROR_NONE) {	return err;    }    serverSocketFD = dbgsysSocket(AF_INET, SOCK_STREAM, 0);    if (serverSocketFD < 0) {        RETURN_IO_ERROR("socket creation failed");    }    err = setOptions(serverSocketFD);    if (err) {        return err;    }    err = dbgsysBind(serverSocketFD, (struct sockaddr *)&sa, sizeof(sa));    if (err < 0) {	RETURN_IO_ERROR("bind failed");    }    err = dbgsysListen(serverSocketFD, 1);    if (err < 0) {        RETURN_IO_ERROR("listen failed");    }    {        char buf[20];        int len = sizeof(sa);	jint portNum;        err = dbgsysGetSocketName(serverSocketFD,                                (struct sockaddr *)&sa, &len);        portNum = dbgsysNetworkToHostShort(sa.sin_port);        sprintf(buf, "%d", portNum);        *actualAddress = (*callback->alloc)(strlen(buf) + 1);	if (*actualAddress == NULL) {	    RETURN_ERROR(JDWPTRANSPORT_ERROR_OUT_OF_MEMORY, "out of memory");	} else {	    strcpy(*actualAddress, buf);	}    }    return JDWPTRANSPORT_ERROR_NONE;}static jdwpTransportError JNICALLsocketTransport_accept(jdwpTransportEnv* env, jlong acceptTimeout, jlong handshakeTimeout) {    int socketLen, err;    struct sockaddr_in socket;    jlong startTime = (jlong)0;    /*     * 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;	    dbgsysConfigureBlocking(serverSocketFD, JNI_FALSE);            startTime = dbgsysCurrentTimeMillis();	    rv = dbgsysPoll(serverSocketFD, JNI_TRUE, JNI_FALSE, (long)acceptTimeout);	    if (rv <= 0) {	        /* set the last error here as could be overridden by configureBlocking */	        if (rv == 0) {	            setLastError(JDWPTRANSPORT_ERROR_IO_ERROR, "poll failed");	        }		/* restore blocking state */	        dbgsysConfigureBlocking(serverSocketFD, JNI_TRUE);	        if (rv == 0) {	            RETURN_ERROR(JDWPTRANSPORT_ERROR_TIMEOUT, "timed out waiting for connection");	        } else {				    return JDWPTRANSPORT_ERROR_IO_ERROR;		}	    }	}   	/*	 * Accept the connection	 */	memset((void *)&socket,0,sizeof(struct sockaddr_in));        socketLen = sizeof(socket);        socketFD = dbgsysAccept(serverSocketFD,                                (struct sockaddr *)&socket,                                &socketLen);        /* set the last error here as could be overridden by configureBlocking */        if (socketFD < 0) {	    setLastError(JDWPTRANSPORT_ERROR_IO_ERROR, "accept failed");        }	/* 	 * Restore the blocking state - note that the accepted socket may be in 	 * blocking or non-blocking mode (platform dependent). However as there

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?