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