1/*
2 * Copyright (c) 1999, 2008, 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
30#include "sysShmem.h"
31#include "shmemBase.h"
32#include "jdwpTransport.h"  /* for Packet, TransportCallback */
33
34#define MIN(x,y) ((x)<(y)?(x):(y))
35
36/*
37 * This is the base shared memory transport implementation that is used
38 * by both front-end transports (through com.sun.tools.jdi) and
39 * back-end transports (through JDWP_OnLoad and the function tables
40 * it requires). It supports multiple connections for the benefit of the
41 * front-end client; the back end interface assumes only a single connection.
42 */
43
44#define MAX_IPC_PREFIX 50   /* user-specified or generated name for */
45                            /* shared memory seg and prefix for other IPC */
46#define MAX_IPC_SUFFIX 25   /* suffix to shmem name for other IPC names */
47#define MAX_IPC_NAME   (MAX_IPC_PREFIX + MAX_IPC_SUFFIX)
48
49#define MAX_GENERATION_RETRIES 20
50#define SHARED_BUFFER_SIZE 5000
51
52#define CHECK_ERROR(expr) do { \
53                              jint error = (expr); \
54                              if (error != SYS_OK) { \
55                                  setLastError(error); \
56                                  return error; \
57                              } \
58                          } while (0)
59
60/*
61 * The following assertions should hold anytime the stream's mutex is not held
62 */
63#define STREAM_INVARIANT(stream) \
64        do { \
65            SHMEM_ASSERT((stream->shared->readOffset < SHARED_BUFFER_SIZE) \
66                         && (stream->shared->readOffset >= 0)); \
67            SHMEM_ASSERT((stream->shared->writeOffset < SHARED_BUFFER_SIZE) \
68                         && (stream->shared->writeOffset >= 0)); \
69        } while (0)
70
71/*
72 * Transports are duplex, so carve the shared memory into "streams",
73 * one used to send from client to server, the other vice versa.
74 */
75typedef struct SharedMemoryListener {
76    char mutexName[MAX_IPC_NAME];
77    char acceptEventName[MAX_IPC_NAME];
78    char attachEventName[MAX_IPC_NAME];
79    jboolean isListening;
80    jboolean isAccepted;
81    jlong acceptingPID;
82    jlong attachingPID;
83} SharedListener;
84
85typedef struct SharedMemoryTransport {
86    char name[MAX_IPC_PREFIX];
87    sys_ipmutex_t mutex;
88    sys_event_t acceptEvent;
89    sys_event_t attachEvent;
90    sys_shmem_t sharedMemory;
91    SharedListener *shared;
92} SharedMemoryTransport;
93
94/*
95 * Access must be syncronized.  Holds one shared
96 * memory buffer and its state.
97 */
98typedef struct SharedStream {
99    char mutexName[MAX_IPC_NAME];
100    char hasDataEventName[MAX_IPC_NAME];
101    char hasSpaceEventName[MAX_IPC_NAME];
102    int readOffset;
103    int writeOffset;
104    jboolean isFull;
105    jbyte buffer[SHARED_BUFFER_SIZE];
106} SharedStream;
107
108/*
109 * The two shared streams: client to server and
110 * server to client.
111 */
112typedef struct SharedMemory {
113    SharedStream toClient;
114    SharedStream toServer;
115} SharedMemory;
116
117/*
118 * Local (to process) access to the shared memory
119 * stream.  access to hasData and hasSpace synchronized
120 * by OS.
121 */
122typedef struct Stream {
123    sys_ipmutex_t mutex;
124    sys_event_t hasData;
125    sys_event_t hasSpace;
126    SharedStream *shared;
127    jint state;
128} Stream;
129
130/*
131 * Values for Stream.state field above.
132 */
133#define STATE_CLOSED 0xDEAD
134#define STATE_OPEN   (STATE_CLOSED -1)
135/*
136 * State checking macro. We compare against the STATE_OPEN value so
137 * that STATE_CLOSED and any other value will be considered closed.
138 * This catches a freed Stream as long as the memory page is still
139 * valid. If the memory page is gone, then there is little that we
140 * can do.
141 */
142#define IS_STATE_CLOSED(state) (state != STATE_OPEN)
143
144
145typedef struct SharedMemoryConnection {
146    char name[MAX_IPC_NAME];
147    SharedMemory *shared;
148    sys_shmem_t sharedMemory;
149    Stream incoming;
150    Stream outgoing;
151    sys_process_t otherProcess;
152    sys_event_t shutdown;           /* signalled to indicate shutdown */
153} SharedMemoryConnection;
154
155static jdwpTransportCallback *callback;
156static JavaVM *jvm;
157static int tlsIndex;
158
159typedef jint (*CreateFunc)(char *name, void *arg);
160
161/*
162 * Set the per-thread error message (if not already set)
163 */
164static void
165setLastErrorMsg(char *newmsg) {
166    char *msg;
167
168    msg = (char *)sysTlsGet(tlsIndex);
169    if (msg == NULL) {
170        msg = (*callback->alloc)((int)strlen(newmsg)+1);
171        if (msg != NULL) {
172           strcpy(msg, newmsg);
173        }
174        sysTlsPut(tlsIndex, (void *)msg);
175    }
176}
177
178/*
179 * Clear last per-thread error message
180 */
181static void
182clearLastError() {
183    char* msg = (char *)sysTlsGet(tlsIndex);
184    if (msg != NULL) {
185        (*callback->free)(msg);
186        sysTlsPut(tlsIndex, NULL);
187    }
188}
189
190/*
191 * Set the per-thread error message to the textual representation
192 * of the last system error (if not already set)
193 */
194static void
195setLastError(jint error) {
196    char buf[128];
197
198    switch (error) {
199        case SYS_OK      : return;      /* no-op */
200        case SYS_DIED    : strcpy(buf, "Other process terminated"); break;
201        case SYS_TIMEOUT : strcpy(buf, "Timed out"); break;
202        default          : sysGetLastError(buf, sizeof(buf));
203    }
204    setLastErrorMsg(buf);
205}
206
207jint
208shmemBase_initialize(JavaVM *vm, jdwpTransportCallback *cbPtr)
209{
210    jvm = vm;
211    callback = cbPtr;
212    tlsIndex = sysTlsAlloc();
213    return SYS_OK;
214}
215
216static jint
217createWithGeneratedName(char *prefix, char *nameBuffer, CreateFunc func, void *arg)
218{
219    jint error;
220    jint i = 0;
221
222    do {
223        strcpy(nameBuffer, prefix);
224        if (i > 0) {
225            char buf[10];
226            sprintf(buf, ".%d", i+1);
227            strcat(nameBuffer, buf);
228        }
229        error = func(nameBuffer, arg);
230        i++;
231    } while ((error == SYS_INUSE) && (i < MAX_GENERATION_RETRIES));
232
233    if (error != SYS_OK) {
234        setLastError(error);
235    }
236
237    return error;
238}
239
240typedef struct SharedMemoryArg {
241    jint size;
242    sys_shmem_t memory;
243    void *start;
244} SharedMemoryArg;
245
246static jint
247createSharedMem(char *name, void *ptr)
248{
249    SharedMemoryArg *arg = ptr;
250    return sysSharedMemCreate(name, arg->size, &arg->memory, &arg->start);
251}
252
253static jint
254createMutex(char *name, void *arg)
255{
256    sys_ipmutex_t *retArg = arg;
257    return sysIPMutexCreate(name, retArg);
258}
259
260/*
261 * Creates named or unnamed event that is automatically reset
262 * (in other words, no need to reset event after it has signalled
263 * a thread).
264 */
265static jint
266createEvent(char *name, void *arg)
267{
268    sys_event_t *retArg = arg;
269    return sysEventCreate(name, retArg, JNI_FALSE);
270}
271
272#define ADD_OFFSET(o1, o2) ((o1 + o2) % SHARED_BUFFER_SIZE)
273#define FULL(stream) (stream->shared->isFull)
274#define EMPTY(stream) ((stream->shared->writeOffset == stream->shared->readOffset) \
275                       && !stream->shared->isFull)
276
277static jint
278leaveMutex(Stream *stream)
279{
280    return sysIPMutexExit(stream->mutex);
281}
282
283/* enter the stream's mutex and (optionally) check for a closed stream */
284static jint
285enterMutex(Stream *stream, sys_event_t event)
286{
287    jint ret = sysIPMutexEnter(stream->mutex, event);
288    if (ret != SYS_OK) {
289        if (IS_STATE_CLOSED(stream->state)) {
290            setLastErrorMsg("stream closed");
291        }
292        return ret;
293    }
294    if (IS_STATE_CLOSED(stream->state)) {
295        setLastErrorMsg("stream closed");
296        (void)leaveMutex(stream);
297        return SYS_ERR;
298    }
299    return SYS_OK;
300}
301
302/*
303 * Enter/exit with stream mutex held.
304 * On error, does not hold the stream mutex.
305 */
306static jint
307waitForSpace(SharedMemoryConnection *connection, Stream *stream)
308{
309    jint error = SYS_OK;
310
311    /* Assumes mutex is held on call */
312    while ((error == SYS_OK) && FULL(stream)) {
313        CHECK_ERROR(leaveMutex(stream));
314        error = sysEventWait(connection->otherProcess, stream->hasSpace, 0);
315        if (error == SYS_OK) {
316            CHECK_ERROR(enterMutex(stream, connection->shutdown));
317        } else {
318            setLastError(error);
319        }
320    }
321    return error;
322}
323
324static jint
325signalSpace(Stream *stream)
326{
327    return sysEventSignal(stream->hasSpace);
328}
329
330/*
331 * Enter/exit with stream mutex held.
332 * On error, does not hold the stream mutex.
333 */
334static jint
335waitForData(SharedMemoryConnection *connection, Stream *stream)
336{
337    jint error = SYS_OK;
338
339    /* Assumes mutex is held on call */
340    while ((error == SYS_OK) && EMPTY(stream)) {
341        CHECK_ERROR(leaveMutex(stream));
342        error = sysEventWait(connection->otherProcess, stream->hasData, 0);
343        if (error == SYS_OK) {
344            CHECK_ERROR(enterMutex(stream, connection->shutdown));
345        } else {
346            setLastError(error);
347        }
348    }
349    return error;
350}
351
352static jint
353signalData(Stream *stream)
354{
355    return sysEventSignal(stream->hasData);
356}
357
358
359static jint
360closeStream(Stream *stream, jboolean linger)
361{
362    /*
363     * Lock stream during close - ignore shutdown event as we are
364     * closing down and shutdown should be signalled.
365     */
366    CHECK_ERROR(enterMutex(stream, NULL));
367
368    /* mark the stream as closed */
369    stream->state = STATE_CLOSED;
370    /* wake up waitForData() if it is in sysEventWait() */
371    sysEventSignal(stream->hasData);
372    sysEventClose(stream->hasData);
373    /* wake up waitForSpace() if it is in sysEventWait() */
374    sysEventSignal(stream->hasSpace);
375    sysEventClose(stream->hasSpace);
376
377    /*
378     * If linger requested then give the stream a few seconds to
379     * drain before closing it.
380     */
381    if (linger) {
382        int attempts = 10;
383        while (!EMPTY(stream) && attempts>0) {
384            CHECK_ERROR(leaveMutex(stream));
385            sysSleep(200);
386            CHECK_ERROR(enterMutex(stream, NULL));
387            attempts--;
388        }
389    }
390
391    CHECK_ERROR(leaveMutex(stream));
392    sysIPMutexClose(stream->mutex);
393    return SYS_OK;
394}
395
396/*
397 * Server creates stream.
398 */
399static int
400createStream(char *name, Stream *stream)
401{
402    jint error;
403    char prefix[MAX_IPC_PREFIX];
404
405    sprintf(prefix, "%s.mutex", name);
406    error = createWithGeneratedName(prefix, stream->shared->mutexName,
407                                    createMutex, &stream->mutex);
408    if (error != SYS_OK) {
409        return error;
410    }
411
412    sprintf(prefix, "%s.hasData", name);
413    error = createWithGeneratedName(prefix, stream->shared->hasDataEventName,
414                                    createEvent, &stream->hasData);
415    if (error != SYS_OK) {
416        (void)closeStream(stream, JNI_FALSE);
417        return error;
418    }
419
420    sprintf(prefix, "%s.hasSpace", name);
421    error = createWithGeneratedName(prefix, stream->shared->hasSpaceEventName,
422                                    createEvent, &stream->hasSpace);
423    if (error != SYS_OK) {
424        (void)closeStream(stream, JNI_FALSE);
425        return error;
426    }
427
428    stream->shared->readOffset = 0;
429    stream->shared->writeOffset = 0;
430    stream->shared->isFull = JNI_FALSE;
431    stream->state = STATE_OPEN;
432    return SYS_OK;
433}
434
435
436/*
437 * Initialization for the stream opened by the other process
438 */
439static int
440openStream(Stream *stream)
441{
442    jint error;
443
444    CHECK_ERROR(sysIPMutexOpen(stream->shared->mutexName, &stream->mutex));
445
446    error = sysEventOpen(stream->shared->hasDataEventName,
447                             &stream->hasData);
448    if (error != SYS_OK) {
449        setLastError(error);
450        (void)closeStream(stream, JNI_FALSE);
451        return error;
452    }
453
454    error = sysEventOpen(stream->shared->hasSpaceEventName,
455                             &stream->hasSpace);
456    if (error != SYS_OK) {
457        setLastError(error);
458        (void)closeStream(stream, JNI_FALSE);
459        return error;
460    }
461
462    stream->state = STATE_OPEN;
463
464    return SYS_OK;
465}
466
467/********************************************************************/
468
469static SharedMemoryConnection *
470allocConnection(void)
471{
472    /*
473     * TO DO: Track all allocated connections for clean shutdown?
474     */
475    SharedMemoryConnection *conn = (*callback->alloc)(sizeof(SharedMemoryConnection));
476    if (conn != NULL) {
477        memset(conn, 0, sizeof(SharedMemoryConnection));
478    }
479    return conn;
480}
481
482static void
483freeConnection(SharedMemoryConnection *connection)
484{
485    (*callback->free)(connection);
486}
487
488static void
489closeConnection(SharedMemoryConnection *connection)
490{
491    /*
492     * Signal all threads accessing this connection that we are
493     * shutting down.
494     */
495    if (connection->shutdown) {
496        sysEventSignal(connection->shutdown);
497    }
498
499
500    (void)closeStream(&connection->outgoing, JNI_TRUE);
501    (void)closeStream(&connection->incoming, JNI_FALSE);
502
503    if (connection->sharedMemory) {
504        sysSharedMemClose(connection->sharedMemory, connection->shared);
505    }
506    if (connection->otherProcess) {
507        sysProcessClose(connection->otherProcess);
508    }
509
510    /*
511     * Ideally we should close the connection->shutdown event and
512     * free the connection structure. However as closing the
513     * connection is asynchronous it means that other threads may
514     * still be accessing the connection structure. On Win32 this
515     * means we leak 132 bytes and one event per connection. This
516     * memory will be reclaim at process exit.
517     *
518     * if (connection->shutdown)
519     *     sysEventClose(connection->shutdown);
520     * freeConnection(connection);
521     */
522}
523
524
525/*
526 * For client: connect to the shared memory.  Open incoming and
527 * outgoing streams.
528 */
529static jint
530openConnection(SharedMemoryTransport *transport, jlong otherPID,
531               SharedMemoryConnection **connectionPtr)
532{
533    jint error;
534
535    SharedMemoryConnection *connection = allocConnection();
536    if (connection == NULL) {
537        return SYS_NOMEM;
538    }
539
540    sprintf(connection->name, "%s.%ld", transport->name, sysProcessGetID());
541    error = sysSharedMemOpen(connection->name, &connection->sharedMemory,
542                             &connection->shared);
543    if (error != SYS_OK) {
544        closeConnection(connection);
545        return error;
546    }
547
548    /* This process is the client */
549    connection->incoming.shared = &connection->shared->toClient;
550    connection->outgoing.shared = &connection->shared->toServer;
551
552    error = openStream(&connection->incoming);
553    if (error != SYS_OK) {
554        closeConnection(connection);
555        return error;
556    }
557
558    error = openStream(&connection->outgoing);
559    if (error != SYS_OK) {
560        closeConnection(connection);
561        return error;
562    }
563
564    error = sysProcessOpen(otherPID, &connection->otherProcess);
565    if (error != SYS_OK) {
566        setLastError(error);
567        closeConnection(connection);
568        return error;
569    }
570
571    /*
572     * Create an event that signals that the connection is shutting
573     * down. The event is unnamed as it's process local, and is
574     * manually reset (so that signalling the event will signal
575     * all threads waiting on it).
576     */
577    error = sysEventCreate(NULL, &connection->shutdown, JNI_TRUE);
578    if (error != SYS_OK) {
579        setLastError(error);
580        closeConnection(connection);
581        return error;
582    }
583
584    *connectionPtr = connection;
585    return SYS_OK;
586}
587
588/*
589 * For server: create the shared memory.  Create incoming and
590 * outgoing streams.
591 */
592static jint
593createConnection(SharedMemoryTransport *transport, jlong otherPID,
594                 SharedMemoryConnection **connectionPtr)
595{
596    jint error;
597    char streamPrefix[MAX_IPC_NAME];
598
599    SharedMemoryConnection *connection = allocConnection();
600    if (connection == NULL) {
601        return SYS_NOMEM;
602    }
603
604    sprintf(connection->name, "%s.%ld", transport->name, otherPID);
605    error = sysSharedMemCreate(connection->name, sizeof(SharedMemory),
606                               &connection->sharedMemory, &connection->shared);
607    if (error != SYS_OK) {
608        closeConnection(connection);
609        return error;
610    }
611
612    memset(connection->shared, 0, sizeof(SharedMemory));
613
614    /* This process is the server */
615    connection->incoming.shared = &connection->shared->toServer;
616    connection->outgoing.shared = &connection->shared->toClient;
617
618    strcpy(streamPrefix, connection->name);
619    strcat(streamPrefix, ".ctos");
620    error = createStream(streamPrefix, &connection->incoming);
621    if (error != SYS_OK) {
622        closeConnection(connection);
623        return error;
624    }
625
626    strcpy(streamPrefix, connection->name);
627    strcat(streamPrefix, ".stoc");
628    error = createStream(streamPrefix, &connection->outgoing);
629    if (error != SYS_OK) {
630        closeConnection(connection);
631        return error;
632    }
633
634    error = sysProcessOpen(otherPID, &connection->otherProcess);
635    if (error != SYS_OK) {
636        setLastError(error);
637        closeConnection(connection);
638        return error;
639    }
640
641    /*
642     * Create an event that signals that the connection is shutting
643     * down. The event is unnamed as it's process local, and is
644     * manually reset (so that a signalling the event will signal
645     * all threads waiting on it).
646     */
647    error = sysEventCreate(NULL, &connection->shutdown, JNI_TRUE);
648    if (error != SYS_OK) {
649        setLastError(error);
650        closeConnection(connection);
651        return error;
652    }
653
654    *connectionPtr = connection;
655    return SYS_OK;
656}
657
658/********************************************************************/
659
660static SharedMemoryTransport *
661allocTransport(void)
662{
663    /*
664     * TO DO: Track all allocated transports for clean shutdown?
665     */
666    return (*callback->alloc)(sizeof(SharedMemoryTransport));
667}
668
669static void
670freeTransport(SharedMemoryTransport *transport)
671{
672    (*callback->free)(transport);
673}
674
675static void
676closeTransport(SharedMemoryTransport *transport)
677{
678    sysIPMutexClose(transport->mutex);
679    sysEventClose(transport->acceptEvent);
680    sysEventClose(transport->attachEvent);
681    sysSharedMemClose(transport->sharedMemory, transport->shared);
682    freeTransport(transport);
683}
684
685static int
686openTransport(const char *address, SharedMemoryTransport **transportPtr)
687{
688    jint error;
689    SharedMemoryTransport *transport;
690
691    transport = allocTransport();
692    if (transport == NULL) {
693        return SYS_NOMEM;
694    }
695    memset(transport, 0, sizeof(*transport));
696
697    if (strlen(address) >= MAX_IPC_PREFIX) {
698        char buf[128];
699        sprintf(buf, "Error: address strings longer than %d characters are invalid\n", MAX_IPC_PREFIX);
700        setLastErrorMsg(buf);
701        closeTransport(transport);
702        return SYS_ERR;
703    }
704
705    error = sysSharedMemOpen(address, &transport->sharedMemory, &transport->shared);
706    if (error != SYS_OK) {
707        setLastError(error);
708        closeTransport(transport);
709        return error;
710    }
711    strcpy(transport->name, address);
712
713    error = sysIPMutexOpen(transport->shared->mutexName, &transport->mutex);
714    if (error != SYS_OK) {
715        setLastError(error);
716        closeTransport(transport);
717        return error;
718    }
719
720    error = sysEventOpen(transport->shared->acceptEventName,
721                             &transport->acceptEvent);
722    if (error != SYS_OK) {
723        setLastError(error);
724        closeTransport(transport);
725        return error;
726    }
727
728    error = sysEventOpen(transport->shared->attachEventName,
729                             &transport->attachEvent);
730    if (error != SYS_OK) {
731        setLastError(error);
732        closeTransport(transport);
733        return error;
734    }
735
736    *transportPtr = transport;
737    return SYS_OK;
738}
739
740static jint
741createTransport(const char *address, SharedMemoryTransport **transportPtr)
742{
743    SharedMemoryTransport *transport;
744    jint error;
745    char prefix[MAX_IPC_PREFIX];
746
747
748
749    transport = allocTransport();
750    if (transport == NULL) {
751        return SYS_NOMEM;
752    }
753    memset(transport, 0, sizeof(*transport));
754
755    if ((address == NULL) || (address[0] == '\0')) {
756        SharedMemoryArg arg;
757        arg.size = sizeof(SharedListener);
758        error = createWithGeneratedName("javadebug", transport->name,
759                                        createSharedMem, &arg);
760        transport->shared = arg.start;
761        transport->sharedMemory = arg.memory;
762    } else {
763        if (strlen(address) >= MAX_IPC_PREFIX) {
764            char buf[128];
765            sprintf(buf, "Error: address strings longer than %d characters are invalid\n", MAX_IPC_PREFIX);
766            setLastErrorMsg(buf);
767            closeTransport(transport);
768            return SYS_ERR;
769        }
770        strcpy(transport->name, address);
771        error = sysSharedMemCreate(address, sizeof(SharedListener),
772                                   &transport->sharedMemory, &transport->shared);
773    }
774    if (error != SYS_OK) {
775        setLastError(error);
776        closeTransport(transport);
777        return error;
778    }
779
780    memset(transport->shared, 0, sizeof(SharedListener));
781    transport->shared->acceptingPID = sysProcessGetID();
782
783    sprintf(prefix, "%s.mutex", transport->name);
784    error = createWithGeneratedName(prefix, transport->shared->mutexName,
785                                    createMutex, &transport->mutex);
786    if (error != SYS_OK) {
787        closeTransport(transport);
788        return error;
789    }
790
791    sprintf(prefix, "%s.accept", transport->name);
792    error = createWithGeneratedName(prefix, transport->shared->acceptEventName,
793                                    createEvent, &transport->acceptEvent);
794    if (error != SYS_OK) {
795        closeTransport(transport);
796        return error;
797    }
798
799    sprintf(prefix, "%s.attach", transport->name);
800    error = createWithGeneratedName(prefix, transport->shared->attachEventName,
801                                    createEvent, &transport->attachEvent);
802    if (error != SYS_OK) {
803        closeTransport(transport);
804        return error;
805    }
806
807    *transportPtr = transport;
808    return SYS_OK;
809}
810
811
812jint
813shmemBase_listen(const char *address, SharedMemoryTransport **transportPtr)
814{
815    int error;
816
817    clearLastError();
818
819    error = createTransport(address, transportPtr);
820    if (error == SYS_OK) {
821        (*transportPtr)->shared->isListening = JNI_TRUE;
822    }
823    return error;
824}
825
826
827jint
828shmemBase_accept(SharedMemoryTransport *transport,
829                 long timeout,
830                 SharedMemoryConnection **connectionPtr)
831{
832    jint error;
833    SharedMemoryConnection *connection;
834
835    clearLastError();
836
837    CHECK_ERROR(sysEventWait(NULL, transport->attachEvent, timeout));
838
839    error = createConnection(transport, transport->shared->attachingPID,
840                             &connection);
841    if (error != SYS_OK) {
842        /*
843         * Reject the attacher
844         */
845        transport->shared->isAccepted = JNI_FALSE;
846        sysEventSignal(transport->acceptEvent);
847
848        freeConnection(connection);
849        return error;
850    }
851
852    transport->shared->isAccepted = JNI_TRUE;
853    error = sysEventSignal(transport->acceptEvent);
854    if (error != SYS_OK) {
855        /*
856         * No real point trying to reject it.
857         */
858        closeConnection(connection);
859        return error;
860    }
861
862    *connectionPtr = connection;
863    return SYS_OK;
864}
865
866static jint
867doAttach(SharedMemoryTransport *transport, long timeout)
868{
869    transport->shared->attachingPID = sysProcessGetID();
870    CHECK_ERROR(sysEventSignal(transport->attachEvent));
871    CHECK_ERROR(sysEventWait(NULL, transport->acceptEvent, timeout));
872    return SYS_OK;
873}
874
875jint
876shmemBase_attach(const char *addressString, long timeout, SharedMemoryConnection **connectionPtr)
877{
878    int error;
879    SharedMemoryTransport *transport;
880    jlong acceptingPID;
881
882    clearLastError();
883
884    error = openTransport(addressString, &transport);
885    if (error != SYS_OK) {
886        return error;
887    }
888
889    /* lock transport - no additional event to wait on as no connection yet */
890    error = sysIPMutexEnter(transport->mutex, NULL);
891    if (error != SYS_OK) {
892        setLastError(error);
893        closeTransport(transport);
894        return error;
895    }
896
897    if (transport->shared->isListening) {
898        error = doAttach(transport, timeout);
899        if (error == SYS_OK) {
900            acceptingPID = transport->shared->acceptingPID;
901        }
902    } else {
903        /* Not listening: error */
904        error = SYS_ERR;
905    }
906
907    sysIPMutexExit(transport->mutex);
908    if (error != SYS_OK) {
909        closeTransport(transport);
910        return error;
911    }
912
913    error = openConnection(transport, acceptingPID, connectionPtr);
914
915    closeTransport(transport);
916
917    return error;
918}
919
920
921
922
923void
924shmemBase_closeConnection(SharedMemoryConnection *connection)
925{
926    clearLastError();
927    closeConnection(connection);
928}
929
930void
931shmemBase_closeTransport(SharedMemoryTransport *transport)
932{
933    clearLastError();
934    closeTransport(transport);
935}
936
937jint
938shmemBase_sendByte(SharedMemoryConnection *connection, jbyte data)
939{
940    Stream *stream = &connection->outgoing;
941    SharedStream *shared = stream->shared;
942    int offset;
943
944    clearLastError();
945
946    CHECK_ERROR(enterMutex(stream, connection->shutdown));
947    CHECK_ERROR(waitForSpace(connection, stream));
948    SHMEM_ASSERT(!FULL(stream));
949    offset = shared->writeOffset;
950    shared->buffer[offset] = data;
951    shared->writeOffset = ADD_OFFSET(offset, 1);
952    shared->isFull = (shared->readOffset == shared->writeOffset);
953
954    STREAM_INVARIANT(stream);
955    CHECK_ERROR(leaveMutex(stream));
956
957    CHECK_ERROR(signalData(stream));
958
959    return SYS_OK;
960}
961
962jint
963shmemBase_receiveByte(SharedMemoryConnection *connection, jbyte *data)
964{
965    Stream *stream = &connection->incoming;
966    SharedStream *shared = stream->shared;
967    int offset;
968
969    clearLastError();
970
971    CHECK_ERROR(enterMutex(stream, connection->shutdown));
972    CHECK_ERROR(waitForData(connection, stream));
973    SHMEM_ASSERT(!EMPTY(stream));
974    offset = shared->readOffset;
975    *data = shared->buffer[offset];
976    shared->readOffset = ADD_OFFSET(offset, 1);
977    shared->isFull = JNI_FALSE;
978
979    STREAM_INVARIANT(stream);
980    CHECK_ERROR(leaveMutex(stream));
981
982    CHECK_ERROR(signalSpace(stream));
983
984    return SYS_OK;
985}
986
987static jint
988sendBytes(SharedMemoryConnection *connection, const void *bytes, jint length)
989{
990    Stream *stream = &connection->outgoing;
991    SharedStream *shared = stream->shared;
992    jint fragmentStart;
993    jint fragmentLength;
994    jint index = 0;
995    jint maxLength;
996
997    clearLastError();
998
999    CHECK_ERROR(enterMutex(stream, connection->shutdown));
1000    while (index < length) {
1001        CHECK_ERROR(waitForSpace(connection, stream));
1002        SHMEM_ASSERT(!FULL(stream));
1003
1004        fragmentStart = shared->writeOffset;
1005
1006        if (fragmentStart < shared->readOffset) {
1007            maxLength = shared->readOffset - fragmentStart;
1008        } else {
1009            maxLength = SHARED_BUFFER_SIZE - fragmentStart;
1010        }
1011        fragmentLength = MIN(maxLength, length - index);
1012        memcpy(shared->buffer + fragmentStart, (jbyte *)bytes + index, fragmentLength);
1013        shared->writeOffset = ADD_OFFSET(fragmentStart, fragmentLength);
1014        index += fragmentLength;
1015
1016        shared->isFull = (shared->readOffset == shared->writeOffset);
1017
1018        STREAM_INVARIANT(stream);
1019        CHECK_ERROR(signalData(stream));
1020
1021    }
1022    CHECK_ERROR(leaveMutex(stream));
1023
1024    return SYS_OK;
1025}
1026
1027
1028/*
1029 * Send packet header followed by data.
1030 */
1031jint
1032shmemBase_sendPacket(SharedMemoryConnection *connection, const jdwpPacket *packet)
1033{
1034    jint data_length;
1035
1036    clearLastError();
1037
1038    CHECK_ERROR(sendBytes(connection, &packet->type.cmd.id, sizeof(jint)));
1039    CHECK_ERROR(sendBytes(connection, &packet->type.cmd.flags, sizeof(jbyte)));
1040
1041    if (packet->type.cmd.flags & JDWPTRANSPORT_FLAGS_REPLY) {
1042        CHECK_ERROR(sendBytes(connection, &packet->type.reply.errorCode, sizeof(jshort)));
1043    } else {
1044        CHECK_ERROR(sendBytes(connection, &packet->type.cmd.cmdSet, sizeof(jbyte)));
1045        CHECK_ERROR(sendBytes(connection, &packet->type.cmd.cmd, sizeof(jbyte)));
1046    }
1047
1048    data_length = packet->type.cmd.len - 11;
1049    SHMEM_GUARANTEE(data_length >= 0);
1050    CHECK_ERROR(sendBytes(connection, &data_length, sizeof(jint)));
1051
1052    if (data_length > 0) {
1053        CHECK_ERROR(sendBytes(connection, packet->type.cmd.data, data_length));
1054    }
1055
1056    return SYS_OK;
1057}
1058
1059static jint
1060receiveBytes(SharedMemoryConnection *connection, void *bytes, jint length)
1061{
1062    Stream *stream = &connection->incoming;
1063    SharedStream *shared = stream->shared;
1064    jint fragmentStart;
1065    jint fragmentLength;
1066    jint index = 0;
1067    jint maxLength;
1068
1069    clearLastError();
1070
1071    CHECK_ERROR(enterMutex(stream, connection->shutdown));
1072    while (index < length) {
1073        CHECK_ERROR(waitForData(connection, stream));
1074        SHMEM_ASSERT(!EMPTY(stream));
1075
1076        fragmentStart = shared->readOffset;
1077        if (fragmentStart < shared->writeOffset) {
1078            maxLength = shared->writeOffset - fragmentStart;
1079        } else {
1080            maxLength = SHARED_BUFFER_SIZE - fragmentStart;
1081        }
1082        fragmentLength = MIN(maxLength, length - index);
1083        memcpy((jbyte *)bytes + index, shared->buffer + fragmentStart, fragmentLength);
1084        shared->readOffset = ADD_OFFSET(fragmentStart, fragmentLength);
1085        index += fragmentLength;
1086
1087        shared->isFull = JNI_FALSE;
1088
1089        STREAM_INVARIANT(stream);
1090        CHECK_ERROR(signalSpace(stream));
1091    }
1092    CHECK_ERROR(leaveMutex(stream));
1093
1094    return SYS_OK;
1095}
1096
1097/*
1098 * Read packet header and insert into packet structure.
1099 * Allocate space for the data and fill it in.
1100 */
1101jint
1102shmemBase_receivePacket(SharedMemoryConnection *connection, jdwpPacket *packet)
1103{
1104    jint data_length;
1105    jint error;
1106
1107    clearLastError();
1108
1109    CHECK_ERROR(receiveBytes(connection, &packet->type.cmd.id, sizeof(jint)));
1110    CHECK_ERROR(receiveBytes(connection, &packet->type.cmd.flags, sizeof(jbyte)));
1111
1112    if (packet->type.cmd.flags & JDWPTRANSPORT_FLAGS_REPLY) {
1113        CHECK_ERROR(receiveBytes(connection, &packet->type.reply.errorCode, sizeof(jshort)));
1114    } else {
1115        CHECK_ERROR(receiveBytes(connection, &packet->type.cmd.cmdSet, sizeof(jbyte)));
1116        CHECK_ERROR(receiveBytes(connection, &packet->type.cmd.cmd, sizeof(jbyte)));
1117    }
1118
1119    CHECK_ERROR(receiveBytes(connection, &data_length, sizeof(jint)));
1120
1121    if (data_length < 0) {
1122        return SYS_ERR;
1123    } else if (data_length == 0) {
1124        packet->type.cmd.len = 11;
1125        packet->type.cmd.data = NULL;
1126    } else {
1127        packet->type.cmd.len = data_length + 11;
1128        packet->type.cmd.data = (*callback->alloc)(data_length);
1129        if (packet->type.cmd.data == NULL) {
1130            return SYS_ERR;
1131        }
1132
1133        error = receiveBytes(connection, packet->type.cmd.data, data_length);
1134        if (error != SYS_OK) {
1135            (*callback->free)(packet->type.cmd.data);
1136            return error;
1137        }
1138    }
1139
1140    return SYS_OK;
1141}
1142
1143jint
1144shmemBase_name(struct SharedMemoryTransport *transport, char **name)
1145{
1146    *name = transport->name;
1147    return SYS_OK;
1148}
1149
1150jint
1151shmemBase_getlasterror(char *msg, jint size) {
1152    char *errstr = (char *)sysTlsGet(tlsIndex);
1153    if (errstr != NULL) {
1154        strcpy(msg, errstr);
1155        return SYS_OK;
1156    } else {
1157        return SYS_ERR;
1158    }
1159}
1160
1161
1162void
1163exitTransportWithError(char *message, char *fileName,
1164                       char *date, int lineNumber)
1165{
1166    JNIEnv *env;
1167    jint error;
1168    char buffer[500];
1169
1170    sprintf(buffer, "Shared Memory Transport \"%s\" (%s), line %d: %s\n",
1171            fileName, date, lineNumber, message);
1172    error = (*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2);
1173    if (error != JNI_OK) {
1174        /*
1175         * We're forced into a direct call to exit()
1176         */
1177        fprintf(stderr, "%s", buffer);
1178        exit(-1);
1179    } else {
1180        (*env)->FatalError(env, buffer);
1181    }
1182}
1183