1/*
2 * Copyright (c) 1999, 2004, 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 <stdlib.h>
26#include <jni.h>
27#include "SharedMemory.h"
28#include "com_sun_tools_jdi_SharedMemoryTransportService.h"
29#include "jdwpTransport.h"
30#include "shmemBase.h"
31#include "sys.h"
32
33/*
34 * JNI interface to the shared memory transport. These JNI methods
35 * call the base shared memory support to do the real work.
36 *
37 * That is, this is the front-ends interface to our shared memory
38 * transport establishment code.
39 */
40
41/*
42 * When initializing the transport from the front end, we use
43 * standard malloc and free for allocation.
44 */
45static void *allocateWrapper(jint size) {
46    return malloc(size);
47}
48static jdwpTransportCallback callbacks = {allocateWrapper, free};
49
50void
51throwException(JNIEnv *env, char *exceptionClassName, char *message)
52{
53    jclass excClass = (*env)->FindClass(env, exceptionClassName);
54    if ((*env)->ExceptionOccurred(env)) {
55        return;
56    }
57    (*env)->ThrowNew(env, excClass, message);
58}
59
60void
61throwShmemException(JNIEnv *env, char *message, jint errorCode)
62{
63    char msg[80];
64    char buf[255];
65
66    if (shmemBase_getlasterror(msg, sizeof(msg)) == SYS_OK) {
67        sprintf(buf, "%s: %s\n", message, msg);
68    } else {
69        sprintf(buf, "%s, error code = %d", message, errorCode);
70    }
71    throwException(env, "java/io/IOException", buf);
72}
73
74/*
75 * Class:     com_sun_tools_jdi_SharedMemoryTransport
76 * Method:    accept0
77 * Signature: (J)J
78 */
79JNIEXPORT jlong JNICALL Java_com_sun_tools_jdi_SharedMemoryTransportService_accept0
80  (JNIEnv *env, jobject thisObject, jlong id, jlong timeout)
81{
82    SharedMemoryConnection *connection = NULL;
83    SharedMemoryTransport *transport = ID_TO_TRANSPORT(id);
84    jint rc;
85
86    rc = shmemBase_accept(transport, (long)timeout, &connection);
87    if (rc != SYS_OK) {
88        if (rc == SYS_TIMEOUT) {
89            throwException(env, "com/sun/jdi/connect/TransportTimeoutException",
90                "Timed out waiting for target VM to connect");
91        } else {
92            throwShmemException(env, "shmemBase_accept failed", rc);
93        }
94        return -1;
95    }
96    return CONNECTION_TO_ID(connection);
97}
98
99/*
100 * Class:     com_sun_tools_jdi_SharedMemoryTransport
101 * Method:    attach0
102 * Signature: (Ljava/lang/String;)J
103 */
104JNIEXPORT jlong JNICALL Java_com_sun_tools_jdi_SharedMemoryTransportService_attach0
105  (JNIEnv *env, jobject thisObject, jstring address, jlong timeout)
106{
107    SharedMemoryConnection *connection = NULL;
108    jint rc;
109    const char *addrChars;
110
111    addrChars = (*env)->GetStringUTFChars(env, address, NULL);
112    if ((*env)->ExceptionOccurred(env)) {
113        return CONNECTION_TO_ID(connection);
114    } else if (addrChars == NULL) {
115        throwException(env, "java/lang/InternalError", "GetStringUTFChars failed");
116        return CONNECTION_TO_ID(connection);
117    }
118
119    rc = shmemBase_attach(addrChars, (long)timeout, &connection);
120    if (rc != SYS_OK) {
121        throwShmemException(env, "shmemBase_attach failed", rc);
122    }
123
124    (*env)->ReleaseStringUTFChars(env, address, addrChars);
125
126    return CONNECTION_TO_ID(connection);
127}
128
129/*
130 * Class:     com_sun_tools_jdi_SharedMemoryTransport
131 * Method:    name
132 * Signature: (J)Ljava/lang/String;
133 */
134JNIEXPORT jstring JNICALL Java_com_sun_tools_jdi_SharedMemoryTransportService_name
135  (JNIEnv *env, jobject thisObject, jlong id)
136{
137    char *namePtr;
138    jstring nameString = NULL;
139
140    SharedMemoryTransport *transport = ID_TO_TRANSPORT(id);
141    jint rc = shmemBase_name(transport, &namePtr);
142    if (rc != SYS_OK) {
143        throwShmemException(env, "shmemBase_name failed", rc);
144    } else {
145        nameString = (*env)->NewStringUTF(env, namePtr);
146        if ((nameString == NULL) && !(*env)->ExceptionOccurred(env)) {
147            throwException(env, "java/lang/InternalError", "Unable to create string");
148        }
149    }
150    return nameString;
151}
152
153/*
154 * Class:     com_sun_tools_jdi_SharedMemoryTransport
155 * Method:    initialize
156 * Signature: ()V
157 */
158JNIEXPORT void JNICALL Java_com_sun_tools_jdi_SharedMemoryTransportService_initialize
159  (JNIEnv *env, jobject thisObject)
160{
161    JavaVM *vm;
162    jint rc;
163
164    rc = (*env)->GetJavaVM(env, &vm);
165    if (rc != 0) {
166        throwException(env, "java/lang/InternalError", "Unable to access Java VM");
167        return;
168    }
169
170    rc = shmemBase_initialize(vm, &callbacks);
171    if (rc != SYS_OK) {
172        throwException(env, "java/lang/InternalError", "Unable to initialize Shared Memory transport");
173        return;
174    }
175}
176
177
178/*
179 * Class:     com_sun_tools_jdi_SharedMemoryTransport
180 * Method:    startListening0
181 * Signature: (Ljava/lang/String;)J
182 */
183JNIEXPORT jlong JNICALL Java_com_sun_tools_jdi_SharedMemoryTransportService_startListening0
184  (JNIEnv *env, jobject thisObject, jstring address)
185{
186    const char *addrChars = NULL;
187    jint rc;
188    jstring retAddress = NULL;
189    SharedMemoryTransport *transport = NULL;
190
191
192    if (address != NULL) {
193        addrChars = (*env)->GetStringUTFChars(env, address, NULL);
194        if ((*env)->ExceptionOccurred(env)) {
195            return TRANSPORT_TO_ID(transport);
196        } else if (addrChars == NULL) {
197            throwException(env, "java/lang/InternalError", "GetStringUTFChars failed");
198            return TRANSPORT_TO_ID(transport);
199        }
200    }
201
202    rc = shmemBase_listen(addrChars, &transport);
203    if (rc != SYS_OK) {
204        throwShmemException(env, "shmemBase_listen failed", rc);
205    }
206
207    if (addrChars != NULL) {
208        (*env)->ReleaseStringUTFChars(env, address, addrChars);
209    }
210
211    return TRANSPORT_TO_ID(transport);
212}
213
214/*
215 * Class:     com_sun_tools_jdi_SharedMemoryTransport
216 * Method:    stopListening0
217 * Signature: (J)V
218 */
219JNIEXPORT void JNICALL Java_com_sun_tools_jdi_SharedMemoryTransportService_stopListening0
220  (JNIEnv *env, jobject thisObject, jlong id)
221{
222    SharedMemoryTransport *transport = ID_TO_TRANSPORT(id);
223    shmemBase_closeTransport(transport);
224}
225