xref: /aosp_15_r20/external/oj-libjdwp/src/share/back/outStream.c (revision e82f7db8c62aed3c168547abe4f9f4aeceaebfc7)
1*e82f7db8SAndroid Build Coastguard Worker /*
2*e82f7db8SAndroid Build Coastguard Worker  * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
3*e82f7db8SAndroid Build Coastguard Worker  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*e82f7db8SAndroid Build Coastguard Worker  *
5*e82f7db8SAndroid Build Coastguard Worker  * This code is free software; you can redistribute it and/or modify it
6*e82f7db8SAndroid Build Coastguard Worker  * under the terms of the GNU General Public License version 2 only, as
7*e82f7db8SAndroid Build Coastguard Worker  * published by the Free Software Foundation.  Oracle designates this
8*e82f7db8SAndroid Build Coastguard Worker  * particular file as subject to the "Classpath" exception as provided
9*e82f7db8SAndroid Build Coastguard Worker  * by Oracle in the LICENSE file that accompanied this code.
10*e82f7db8SAndroid Build Coastguard Worker  *
11*e82f7db8SAndroid Build Coastguard Worker  * This code is distributed in the hope that it will be useful, but WITHOUT
12*e82f7db8SAndroid Build Coastguard Worker  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*e82f7db8SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14*e82f7db8SAndroid Build Coastguard Worker  * version 2 for more details (a copy is included in the LICENSE file that
15*e82f7db8SAndroid Build Coastguard Worker  * accompanied this code).
16*e82f7db8SAndroid Build Coastguard Worker  *
17*e82f7db8SAndroid Build Coastguard Worker  * You should have received a copy of the GNU General Public License version
18*e82f7db8SAndroid Build Coastguard Worker  * 2 along with this work; if not, write to the Free Software Foundation,
19*e82f7db8SAndroid Build Coastguard Worker  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20*e82f7db8SAndroid Build Coastguard Worker  *
21*e82f7db8SAndroid Build Coastguard Worker  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22*e82f7db8SAndroid Build Coastguard Worker  * or visit www.oracle.com if you need additional information or have any
23*e82f7db8SAndroid Build Coastguard Worker  * questions.
24*e82f7db8SAndroid Build Coastguard Worker  */
25*e82f7db8SAndroid Build Coastguard Worker 
26*e82f7db8SAndroid Build Coastguard Worker #include "util.h"
27*e82f7db8SAndroid Build Coastguard Worker #include "stream.h"
28*e82f7db8SAndroid Build Coastguard Worker #include "outStream.h"
29*e82f7db8SAndroid Build Coastguard Worker #include "inStream.h"
30*e82f7db8SAndroid Build Coastguard Worker #include "transport.h"
31*e82f7db8SAndroid Build Coastguard Worker #include "commonRef.h"
32*e82f7db8SAndroid Build Coastguard Worker #include "bag.h"
33*e82f7db8SAndroid Build Coastguard Worker #include "FrameID.h"
34*e82f7db8SAndroid Build Coastguard Worker 
35*e82f7db8SAndroid Build Coastguard Worker #define INITIAL_ID_ALLOC  50
36*e82f7db8SAndroid Build Coastguard Worker #define SMALLEST(a, b) ((a) < (b)) ? (a) : (b)
37*e82f7db8SAndroid Build Coastguard Worker 
38*e82f7db8SAndroid Build Coastguard Worker static void
commonInit(PacketOutputStream * stream)39*e82f7db8SAndroid Build Coastguard Worker commonInit(PacketOutputStream *stream)
40*e82f7db8SAndroid Build Coastguard Worker {
41*e82f7db8SAndroid Build Coastguard Worker     stream->current = &stream->initialSegment[0];
42*e82f7db8SAndroid Build Coastguard Worker     stream->left = sizeof(stream->initialSegment);
43*e82f7db8SAndroid Build Coastguard Worker     stream->segment = &stream->firstSegment;
44*e82f7db8SAndroid Build Coastguard Worker     stream->segment->length = 0;
45*e82f7db8SAndroid Build Coastguard Worker     stream->segment->data = &stream->initialSegment[0];
46*e82f7db8SAndroid Build Coastguard Worker     stream->segment->next = NULL;
47*e82f7db8SAndroid Build Coastguard Worker     stream->error = JDWP_ERROR(NONE);
48*e82f7db8SAndroid Build Coastguard Worker     stream->sent = JNI_FALSE;
49*e82f7db8SAndroid Build Coastguard Worker     stream->ids = bagCreateBag(sizeof(jlong), INITIAL_ID_ALLOC);
50*e82f7db8SAndroid Build Coastguard Worker     if (stream->ids == NULL) {
51*e82f7db8SAndroid Build Coastguard Worker         stream->error = JDWP_ERROR(OUT_OF_MEMORY);
52*e82f7db8SAndroid Build Coastguard Worker     }
53*e82f7db8SAndroid Build Coastguard Worker }
54*e82f7db8SAndroid Build Coastguard Worker 
55*e82f7db8SAndroid Build Coastguard Worker void
outStream_initCommand(PacketOutputStream * stream,jint id,jbyte flags,jbyte commandSet,jbyte command)56*e82f7db8SAndroid Build Coastguard Worker outStream_initCommand(PacketOutputStream *stream, jint id,
57*e82f7db8SAndroid Build Coastguard Worker                       jbyte flags, jbyte commandSet, jbyte command)
58*e82f7db8SAndroid Build Coastguard Worker {
59*e82f7db8SAndroid Build Coastguard Worker     commonInit(stream);
60*e82f7db8SAndroid Build Coastguard Worker 
61*e82f7db8SAndroid Build Coastguard Worker     /*
62*e82f7db8SAndroid Build Coastguard Worker      * Command-specific initialization
63*e82f7db8SAndroid Build Coastguard Worker      */
64*e82f7db8SAndroid Build Coastguard Worker     stream->packet.type.cmd.id = id;
65*e82f7db8SAndroid Build Coastguard Worker     stream->packet.type.cmd.cmdSet = commandSet;
66*e82f7db8SAndroid Build Coastguard Worker     stream->packet.type.cmd.cmd = command;
67*e82f7db8SAndroid Build Coastguard Worker 
68*e82f7db8SAndroid Build Coastguard Worker     stream->packet.type.cmd.flags = flags;
69*e82f7db8SAndroid Build Coastguard Worker }
70*e82f7db8SAndroid Build Coastguard Worker 
71*e82f7db8SAndroid Build Coastguard Worker void
outStream_initReply(PacketOutputStream * stream,jint id)72*e82f7db8SAndroid Build Coastguard Worker outStream_initReply(PacketOutputStream *stream, jint id)
73*e82f7db8SAndroid Build Coastguard Worker {
74*e82f7db8SAndroid Build Coastguard Worker     commonInit(stream);
75*e82f7db8SAndroid Build Coastguard Worker 
76*e82f7db8SAndroid Build Coastguard Worker     /*
77*e82f7db8SAndroid Build Coastguard Worker      * Reply-specific initialization
78*e82f7db8SAndroid Build Coastguard Worker      */
79*e82f7db8SAndroid Build Coastguard Worker     stream->packet.type.reply.id = id;
80*e82f7db8SAndroid Build Coastguard Worker     stream->packet.type.reply.errorCode = 0x0;
81*e82f7db8SAndroid Build Coastguard Worker     stream->packet.type.cmd.flags = (jbyte)JDWPTRANSPORT_FLAGS_REPLY;
82*e82f7db8SAndroid Build Coastguard Worker }
83*e82f7db8SAndroid Build Coastguard Worker 
84*e82f7db8SAndroid Build Coastguard Worker jint
outStream_id(PacketOutputStream * stream)85*e82f7db8SAndroid Build Coastguard Worker outStream_id(PacketOutputStream *stream)
86*e82f7db8SAndroid Build Coastguard Worker {
87*e82f7db8SAndroid Build Coastguard Worker     return stream->packet.type.cmd.id;
88*e82f7db8SAndroid Build Coastguard Worker }
89*e82f7db8SAndroid Build Coastguard Worker 
90*e82f7db8SAndroid Build Coastguard Worker jbyte
outStream_command(PacketOutputStream * stream)91*e82f7db8SAndroid Build Coastguard Worker outStream_command(PacketOutputStream *stream)
92*e82f7db8SAndroid Build Coastguard Worker {
93*e82f7db8SAndroid Build Coastguard Worker     /* Only makes sense for commands */
94*e82f7db8SAndroid Build Coastguard Worker     JDI_ASSERT(!(stream->packet.type.cmd.flags & JDWPTRANSPORT_FLAGS_REPLY));
95*e82f7db8SAndroid Build Coastguard Worker     return stream->packet.type.cmd.cmd;
96*e82f7db8SAndroid Build Coastguard Worker }
97*e82f7db8SAndroid Build Coastguard Worker 
98*e82f7db8SAndroid Build Coastguard Worker static jdwpError
writeBytes(PacketOutputStream * stream,void * source,int size)99*e82f7db8SAndroid Build Coastguard Worker writeBytes(PacketOutputStream *stream, void *source, int size)
100*e82f7db8SAndroid Build Coastguard Worker {
101*e82f7db8SAndroid Build Coastguard Worker     jbyte *bytes = (jbyte *)source;
102*e82f7db8SAndroid Build Coastguard Worker 
103*e82f7db8SAndroid Build Coastguard Worker     if (stream->error) {
104*e82f7db8SAndroid Build Coastguard Worker         return stream->error;
105*e82f7db8SAndroid Build Coastguard Worker     }
106*e82f7db8SAndroid Build Coastguard Worker     while (size > 0) {
107*e82f7db8SAndroid Build Coastguard Worker         jint count;
108*e82f7db8SAndroid Build Coastguard Worker         if (stream->left == 0) {
109*e82f7db8SAndroid Build Coastguard Worker             jint segSize = SMALLEST(2 * stream->segment->length, MAX_SEGMENT_SIZE);
110*e82f7db8SAndroid Build Coastguard Worker             jbyte *newSeg = jvmtiAllocate(segSize);
111*e82f7db8SAndroid Build Coastguard Worker             struct PacketData *newHeader = jvmtiAllocate(sizeof(*newHeader));
112*e82f7db8SAndroid Build Coastguard Worker             if ((newSeg == NULL) || (newHeader == NULL)) {
113*e82f7db8SAndroid Build Coastguard Worker                 jvmtiDeallocate(newSeg);
114*e82f7db8SAndroid Build Coastguard Worker                 jvmtiDeallocate(newHeader);
115*e82f7db8SAndroid Build Coastguard Worker                 stream->error = JDWP_ERROR(OUT_OF_MEMORY);
116*e82f7db8SAndroid Build Coastguard Worker                 return stream->error;
117*e82f7db8SAndroid Build Coastguard Worker             }
118*e82f7db8SAndroid Build Coastguard Worker             newHeader->length = 0;
119*e82f7db8SAndroid Build Coastguard Worker             newHeader->data = newSeg;
120*e82f7db8SAndroid Build Coastguard Worker             newHeader->next = NULL;
121*e82f7db8SAndroid Build Coastguard Worker             stream->segment->next = newHeader;
122*e82f7db8SAndroid Build Coastguard Worker             stream->segment = newHeader;
123*e82f7db8SAndroid Build Coastguard Worker             stream->current = newHeader->data;
124*e82f7db8SAndroid Build Coastguard Worker             stream->left = segSize;
125*e82f7db8SAndroid Build Coastguard Worker         }
126*e82f7db8SAndroid Build Coastguard Worker         count = SMALLEST(size, stream->left);
127*e82f7db8SAndroid Build Coastguard Worker         (void)memcpy(stream->current, bytes, count);
128*e82f7db8SAndroid Build Coastguard Worker         stream->current += count;
129*e82f7db8SAndroid Build Coastguard Worker         stream->left -= count;
130*e82f7db8SAndroid Build Coastguard Worker         stream->segment->length += count;
131*e82f7db8SAndroid Build Coastguard Worker         size -= count;
132*e82f7db8SAndroid Build Coastguard Worker         bytes += count;
133*e82f7db8SAndroid Build Coastguard Worker     }
134*e82f7db8SAndroid Build Coastguard Worker     return JDWP_ERROR(NONE);
135*e82f7db8SAndroid Build Coastguard Worker }
136*e82f7db8SAndroid Build Coastguard Worker 
137*e82f7db8SAndroid Build Coastguard Worker jdwpError
outStream_writeBoolean(PacketOutputStream * stream,jboolean val)138*e82f7db8SAndroid Build Coastguard Worker outStream_writeBoolean(PacketOutputStream *stream, jboolean val)
139*e82f7db8SAndroid Build Coastguard Worker {
140*e82f7db8SAndroid Build Coastguard Worker     jbyte byte = (val != 0) ? 1 : 0;
141*e82f7db8SAndroid Build Coastguard Worker     return writeBytes(stream, &byte, sizeof(byte));
142*e82f7db8SAndroid Build Coastguard Worker }
143*e82f7db8SAndroid Build Coastguard Worker 
144*e82f7db8SAndroid Build Coastguard Worker jdwpError
outStream_writeByte(PacketOutputStream * stream,jbyte val)145*e82f7db8SAndroid Build Coastguard Worker outStream_writeByte(PacketOutputStream *stream, jbyte val)
146*e82f7db8SAndroid Build Coastguard Worker {
147*e82f7db8SAndroid Build Coastguard Worker     return writeBytes(stream, &val, sizeof(val));
148*e82f7db8SAndroid Build Coastguard Worker }
149*e82f7db8SAndroid Build Coastguard Worker 
150*e82f7db8SAndroid Build Coastguard Worker jdwpError
outStream_writeChar(PacketOutputStream * stream,jchar val)151*e82f7db8SAndroid Build Coastguard Worker outStream_writeChar(PacketOutputStream *stream, jchar val)
152*e82f7db8SAndroid Build Coastguard Worker {
153*e82f7db8SAndroid Build Coastguard Worker     val = HOST_TO_JAVA_CHAR(val);
154*e82f7db8SAndroid Build Coastguard Worker     return writeBytes(stream, &val, sizeof(val));
155*e82f7db8SAndroid Build Coastguard Worker }
156*e82f7db8SAndroid Build Coastguard Worker 
157*e82f7db8SAndroid Build Coastguard Worker jdwpError
outStream_writeShort(PacketOutputStream * stream,jshort val)158*e82f7db8SAndroid Build Coastguard Worker outStream_writeShort(PacketOutputStream *stream, jshort val)
159*e82f7db8SAndroid Build Coastguard Worker {
160*e82f7db8SAndroid Build Coastguard Worker     val = HOST_TO_JAVA_SHORT(val);
161*e82f7db8SAndroid Build Coastguard Worker     return writeBytes(stream, &val, sizeof(val));
162*e82f7db8SAndroid Build Coastguard Worker }
163*e82f7db8SAndroid Build Coastguard Worker 
164*e82f7db8SAndroid Build Coastguard Worker jdwpError
outStream_writeInt(PacketOutputStream * stream,jint val)165*e82f7db8SAndroid Build Coastguard Worker outStream_writeInt(PacketOutputStream *stream, jint val)
166*e82f7db8SAndroid Build Coastguard Worker {
167*e82f7db8SAndroid Build Coastguard Worker     val = HOST_TO_JAVA_INT(val);
168*e82f7db8SAndroid Build Coastguard Worker     return writeBytes(stream, &val, sizeof(val));
169*e82f7db8SAndroid Build Coastguard Worker }
170*e82f7db8SAndroid Build Coastguard Worker 
171*e82f7db8SAndroid Build Coastguard Worker jdwpError
outStream_writeLong(PacketOutputStream * stream,jlong val)172*e82f7db8SAndroid Build Coastguard Worker outStream_writeLong(PacketOutputStream *stream, jlong val)
173*e82f7db8SAndroid Build Coastguard Worker {
174*e82f7db8SAndroid Build Coastguard Worker     val = HOST_TO_JAVA_LONG(val);
175*e82f7db8SAndroid Build Coastguard Worker     return writeBytes(stream, &val, sizeof(val));
176*e82f7db8SAndroid Build Coastguard Worker }
177*e82f7db8SAndroid Build Coastguard Worker 
178*e82f7db8SAndroid Build Coastguard Worker jdwpError
outStream_writeFloat(PacketOutputStream * stream,jfloat val)179*e82f7db8SAndroid Build Coastguard Worker outStream_writeFloat(PacketOutputStream *stream, jfloat val)
180*e82f7db8SAndroid Build Coastguard Worker {
181*e82f7db8SAndroid Build Coastguard Worker     val = HOST_TO_JAVA_FLOAT(val);
182*e82f7db8SAndroid Build Coastguard Worker     return writeBytes(stream, &val, sizeof(val));
183*e82f7db8SAndroid Build Coastguard Worker }
184*e82f7db8SAndroid Build Coastguard Worker 
185*e82f7db8SAndroid Build Coastguard Worker jdwpError
outStream_writeDouble(PacketOutputStream * stream,jdouble val)186*e82f7db8SAndroid Build Coastguard Worker outStream_writeDouble(PacketOutputStream *stream, jdouble val)
187*e82f7db8SAndroid Build Coastguard Worker {
188*e82f7db8SAndroid Build Coastguard Worker     val = HOST_TO_JAVA_DOUBLE(val);
189*e82f7db8SAndroid Build Coastguard Worker     return writeBytes(stream, &val, sizeof(val));
190*e82f7db8SAndroid Build Coastguard Worker }
191*e82f7db8SAndroid Build Coastguard Worker 
192*e82f7db8SAndroid Build Coastguard Worker jdwpError
outStream_writeObjectTag(JNIEnv * env,PacketOutputStream * stream,jobject val)193*e82f7db8SAndroid Build Coastguard Worker outStream_writeObjectTag(JNIEnv *env, PacketOutputStream *stream, jobject val)
194*e82f7db8SAndroid Build Coastguard Worker {
195*e82f7db8SAndroid Build Coastguard Worker     return outStream_writeByte(stream, specificTypeKey(env, val));
196*e82f7db8SAndroid Build Coastguard Worker }
197*e82f7db8SAndroid Build Coastguard Worker 
198*e82f7db8SAndroid Build Coastguard Worker jdwpError
outStream_writeObjectRef(JNIEnv * env,PacketOutputStream * stream,jobject val)199*e82f7db8SAndroid Build Coastguard Worker outStream_writeObjectRef(JNIEnv *env, PacketOutputStream *stream, jobject val)
200*e82f7db8SAndroid Build Coastguard Worker {
201*e82f7db8SAndroid Build Coastguard Worker     jlong id;
202*e82f7db8SAndroid Build Coastguard Worker     jlong *idPtr;
203*e82f7db8SAndroid Build Coastguard Worker 
204*e82f7db8SAndroid Build Coastguard Worker     if (stream->error) {
205*e82f7db8SAndroid Build Coastguard Worker         return stream->error;
206*e82f7db8SAndroid Build Coastguard Worker     }
207*e82f7db8SAndroid Build Coastguard Worker 
208*e82f7db8SAndroid Build Coastguard Worker     if (val == NULL) {
209*e82f7db8SAndroid Build Coastguard Worker         id = NULL_OBJECT_ID;
210*e82f7db8SAndroid Build Coastguard Worker     } else {
211*e82f7db8SAndroid Build Coastguard Worker         /* Convert the object to an object id */
212*e82f7db8SAndroid Build Coastguard Worker         id = commonRef_refToID(env, val);
213*e82f7db8SAndroid Build Coastguard Worker         if (id == NULL_OBJECT_ID) {
214*e82f7db8SAndroid Build Coastguard Worker             stream->error = JDWP_ERROR(OUT_OF_MEMORY);
215*e82f7db8SAndroid Build Coastguard Worker             return stream->error;
216*e82f7db8SAndroid Build Coastguard Worker         }
217*e82f7db8SAndroid Build Coastguard Worker 
218*e82f7db8SAndroid Build Coastguard Worker         /* Track the common ref in case we need to release it on a future error */
219*e82f7db8SAndroid Build Coastguard Worker         idPtr = bagAdd(stream->ids);
220*e82f7db8SAndroid Build Coastguard Worker         if (idPtr == NULL) {
221*e82f7db8SAndroid Build Coastguard Worker             commonRef_release(env, id);
222*e82f7db8SAndroid Build Coastguard Worker             stream->error = JDWP_ERROR(OUT_OF_MEMORY);
223*e82f7db8SAndroid Build Coastguard Worker             return stream->error;
224*e82f7db8SAndroid Build Coastguard Worker         } else {
225*e82f7db8SAndroid Build Coastguard Worker             *idPtr = id;
226*e82f7db8SAndroid Build Coastguard Worker         }
227*e82f7db8SAndroid Build Coastguard Worker 
228*e82f7db8SAndroid Build Coastguard Worker         /* Add the encoded object id to the stream */
229*e82f7db8SAndroid Build Coastguard Worker         id = HOST_TO_JAVA_LONG(id);
230*e82f7db8SAndroid Build Coastguard Worker     }
231*e82f7db8SAndroid Build Coastguard Worker 
232*e82f7db8SAndroid Build Coastguard Worker     return writeBytes(stream, &id, sizeof(id));
233*e82f7db8SAndroid Build Coastguard Worker }
234*e82f7db8SAndroid Build Coastguard Worker 
235*e82f7db8SAndroid Build Coastguard Worker jdwpError
outStream_writeFrameID(PacketOutputStream * stream,FrameID val)236*e82f7db8SAndroid Build Coastguard Worker outStream_writeFrameID(PacketOutputStream *stream, FrameID val)
237*e82f7db8SAndroid Build Coastguard Worker {
238*e82f7db8SAndroid Build Coastguard Worker     /*
239*e82f7db8SAndroid Build Coastguard Worker      * Not good - we're writing a pointer as a jint.  Need
240*e82f7db8SAndroid Build Coastguard Worker      * to write as a jlong if sizeof(FrameID) == 8.
241*e82f7db8SAndroid Build Coastguard Worker      */
242*e82f7db8SAndroid Build Coastguard Worker     if (sizeof(FrameID) == 8) {
243*e82f7db8SAndroid Build Coastguard Worker         /*LINTED*/
244*e82f7db8SAndroid Build Coastguard Worker         return outStream_writeLong(stream, (jlong)val);
245*e82f7db8SAndroid Build Coastguard Worker     } else {
246*e82f7db8SAndroid Build Coastguard Worker         /*LINTED*/
247*e82f7db8SAndroid Build Coastguard Worker         return outStream_writeInt(stream, (jint)val);
248*e82f7db8SAndroid Build Coastguard Worker     }
249*e82f7db8SAndroid Build Coastguard Worker }
250*e82f7db8SAndroid Build Coastguard Worker 
251*e82f7db8SAndroid Build Coastguard Worker jdwpError
outStream_writeMethodID(PacketOutputStream * stream,jmethodID val)252*e82f7db8SAndroid Build Coastguard Worker outStream_writeMethodID(PacketOutputStream *stream, jmethodID val)
253*e82f7db8SAndroid Build Coastguard Worker {
254*e82f7db8SAndroid Build Coastguard Worker     /*
255*e82f7db8SAndroid Build Coastguard Worker      * Not good - we're writing a pointer as a jint.  Need
256*e82f7db8SAndroid Build Coastguard Worker      * to write as a jlong if sizeof(jmethodID) == 8.
257*e82f7db8SAndroid Build Coastguard Worker      */
258*e82f7db8SAndroid Build Coastguard Worker     if (sizeof(jmethodID) == 8) {
259*e82f7db8SAndroid Build Coastguard Worker         /*LINTED*/
260*e82f7db8SAndroid Build Coastguard Worker         return outStream_writeLong(stream, (jlong)(intptr_t)val);
261*e82f7db8SAndroid Build Coastguard Worker     } else {
262*e82f7db8SAndroid Build Coastguard Worker         /*LINTED*/
263*e82f7db8SAndroid Build Coastguard Worker         return outStream_writeInt(stream, (jint)(intptr_t)val);
264*e82f7db8SAndroid Build Coastguard Worker     }
265*e82f7db8SAndroid Build Coastguard Worker }
266*e82f7db8SAndroid Build Coastguard Worker 
267*e82f7db8SAndroid Build Coastguard Worker jdwpError
outStream_writeFieldID(PacketOutputStream * stream,jfieldID val)268*e82f7db8SAndroid Build Coastguard Worker outStream_writeFieldID(PacketOutputStream *stream, jfieldID val)
269*e82f7db8SAndroid Build Coastguard Worker {
270*e82f7db8SAndroid Build Coastguard Worker     /*
271*e82f7db8SAndroid Build Coastguard Worker      * Not good - we're writing a pointer as a jint.  Need
272*e82f7db8SAndroid Build Coastguard Worker      * to write as a jlong if sizeof(jfieldID) == 8.
273*e82f7db8SAndroid Build Coastguard Worker      */
274*e82f7db8SAndroid Build Coastguard Worker     if (sizeof(jfieldID) == 8) {
275*e82f7db8SAndroid Build Coastguard Worker         /*LINTED*/
276*e82f7db8SAndroid Build Coastguard Worker         return outStream_writeLong(stream, (jlong)(intptr_t)val);
277*e82f7db8SAndroid Build Coastguard Worker     } else {
278*e82f7db8SAndroid Build Coastguard Worker         /*LINTED*/
279*e82f7db8SAndroid Build Coastguard Worker         return outStream_writeInt(stream, (jint)(intptr_t)val);
280*e82f7db8SAndroid Build Coastguard Worker     }
281*e82f7db8SAndroid Build Coastguard Worker }
282*e82f7db8SAndroid Build Coastguard Worker 
283*e82f7db8SAndroid Build Coastguard Worker jdwpError
outStream_writeLocation(PacketOutputStream * stream,jlocation val)284*e82f7db8SAndroid Build Coastguard Worker outStream_writeLocation(PacketOutputStream *stream, jlocation val)
285*e82f7db8SAndroid Build Coastguard Worker {
286*e82f7db8SAndroid Build Coastguard Worker     return outStream_writeLong(stream, (jlong)val);
287*e82f7db8SAndroid Build Coastguard Worker }
288*e82f7db8SAndroid Build Coastguard Worker 
289*e82f7db8SAndroid Build Coastguard Worker jdwpError
outStream_writeByteArray(PacketOutputStream * stream,jint length,jbyte * bytes)290*e82f7db8SAndroid Build Coastguard Worker outStream_writeByteArray(PacketOutputStream*stream, jint length,
291*e82f7db8SAndroid Build Coastguard Worker                          jbyte *bytes)
292*e82f7db8SAndroid Build Coastguard Worker {
293*e82f7db8SAndroid Build Coastguard Worker     (void)outStream_writeInt(stream, length);
294*e82f7db8SAndroid Build Coastguard Worker     return writeBytes(stream, bytes, length);
295*e82f7db8SAndroid Build Coastguard Worker }
296*e82f7db8SAndroid Build Coastguard Worker 
297*e82f7db8SAndroid Build Coastguard Worker jdwpError
outStream_writeString(PacketOutputStream * stream,char * string)298*e82f7db8SAndroid Build Coastguard Worker outStream_writeString(PacketOutputStream *stream, char *string)
299*e82f7db8SAndroid Build Coastguard Worker {
300*e82f7db8SAndroid Build Coastguard Worker     jdwpError error;
301*e82f7db8SAndroid Build Coastguard Worker     jint      length = string != NULL ? (int)strlen(string) : 0;
302*e82f7db8SAndroid Build Coastguard Worker 
303*e82f7db8SAndroid Build Coastguard Worker     /* Options utf8=y/n controls if we want Standard UTF-8 or Modified */
304*e82f7db8SAndroid Build Coastguard Worker     if ( gdata->modifiedUtf8 ) {
305*e82f7db8SAndroid Build Coastguard Worker         (void)outStream_writeInt(stream, length);
306*e82f7db8SAndroid Build Coastguard Worker         error = writeBytes(stream, (jbyte *)string, length);
307*e82f7db8SAndroid Build Coastguard Worker     } else {
308*e82f7db8SAndroid Build Coastguard Worker         jint      new_length;
309*e82f7db8SAndroid Build Coastguard Worker 
310*e82f7db8SAndroid Build Coastguard Worker         new_length = (gdata->npt->utf8mToUtf8sLength)
311*e82f7db8SAndroid Build Coastguard Worker                             (gdata->npt->utf, (jbyte*)string, length);
312*e82f7db8SAndroid Build Coastguard Worker         if ( new_length == length ) {
313*e82f7db8SAndroid Build Coastguard Worker             (void)outStream_writeInt(stream, length);
314*e82f7db8SAndroid Build Coastguard Worker             error = writeBytes(stream, (jbyte *)string, length);
315*e82f7db8SAndroid Build Coastguard Worker         } else {
316*e82f7db8SAndroid Build Coastguard Worker             char *new_string;
317*e82f7db8SAndroid Build Coastguard Worker 
318*e82f7db8SAndroid Build Coastguard Worker             new_string = jvmtiAllocate(new_length+1);
319*e82f7db8SAndroid Build Coastguard Worker             (gdata->npt->utf8mToUtf8s)
320*e82f7db8SAndroid Build Coastguard Worker                             (gdata->npt->utf, (jbyte*)string, length,
321*e82f7db8SAndroid Build Coastguard Worker                              (jbyte*)new_string, new_length);
322*e82f7db8SAndroid Build Coastguard Worker             (void)outStream_writeInt(stream, new_length);
323*e82f7db8SAndroid Build Coastguard Worker             error = writeBytes(stream, (jbyte *)new_string, new_length);
324*e82f7db8SAndroid Build Coastguard Worker             jvmtiDeallocate(new_string);
325*e82f7db8SAndroid Build Coastguard Worker         }
326*e82f7db8SAndroid Build Coastguard Worker     }
327*e82f7db8SAndroid Build Coastguard Worker     return error;
328*e82f7db8SAndroid Build Coastguard Worker }
329*e82f7db8SAndroid Build Coastguard Worker 
330*e82f7db8SAndroid Build Coastguard Worker jdwpError
outStream_writeValue(JNIEnv * env,PacketOutputStream * out,jbyte typeKey,jvalue value)331*e82f7db8SAndroid Build Coastguard Worker outStream_writeValue(JNIEnv *env, PacketOutputStream *out,
332*e82f7db8SAndroid Build Coastguard Worker                      jbyte typeKey, jvalue value)
333*e82f7db8SAndroid Build Coastguard Worker {
334*e82f7db8SAndroid Build Coastguard Worker     if (typeKey == JDWP_TAG(OBJECT)) {
335*e82f7db8SAndroid Build Coastguard Worker         (void)outStream_writeByte(out, specificTypeKey(env, value.l));
336*e82f7db8SAndroid Build Coastguard Worker     } else {
337*e82f7db8SAndroid Build Coastguard Worker         (void)outStream_writeByte(out, typeKey);
338*e82f7db8SAndroid Build Coastguard Worker     }
339*e82f7db8SAndroid Build Coastguard Worker     if (isObjectTag(typeKey)) {
340*e82f7db8SAndroid Build Coastguard Worker         (void)outStream_writeObjectRef(env, out, value.l);
341*e82f7db8SAndroid Build Coastguard Worker     } else {
342*e82f7db8SAndroid Build Coastguard Worker         switch (typeKey) {
343*e82f7db8SAndroid Build Coastguard Worker             case JDWP_TAG(BYTE):
344*e82f7db8SAndroid Build Coastguard Worker                 return outStream_writeByte(out, value.b);
345*e82f7db8SAndroid Build Coastguard Worker 
346*e82f7db8SAndroid Build Coastguard Worker             case JDWP_TAG(CHAR):
347*e82f7db8SAndroid Build Coastguard Worker                 return outStream_writeChar(out, value.c);
348*e82f7db8SAndroid Build Coastguard Worker 
349*e82f7db8SAndroid Build Coastguard Worker             case JDWP_TAG(FLOAT):
350*e82f7db8SAndroid Build Coastguard Worker                 return outStream_writeFloat(out, value.f);
351*e82f7db8SAndroid Build Coastguard Worker 
352*e82f7db8SAndroid Build Coastguard Worker             case JDWP_TAG(DOUBLE):
353*e82f7db8SAndroid Build Coastguard Worker                 return outStream_writeDouble(out, value.d);
354*e82f7db8SAndroid Build Coastguard Worker 
355*e82f7db8SAndroid Build Coastguard Worker             case JDWP_TAG(INT):
356*e82f7db8SAndroid Build Coastguard Worker                 return outStream_writeInt(out, value.i);
357*e82f7db8SAndroid Build Coastguard Worker 
358*e82f7db8SAndroid Build Coastguard Worker             case JDWP_TAG(LONG):
359*e82f7db8SAndroid Build Coastguard Worker                 return outStream_writeLong(out, value.j);
360*e82f7db8SAndroid Build Coastguard Worker 
361*e82f7db8SAndroid Build Coastguard Worker             case JDWP_TAG(SHORT):
362*e82f7db8SAndroid Build Coastguard Worker                 return outStream_writeShort(out, value.s);
363*e82f7db8SAndroid Build Coastguard Worker 
364*e82f7db8SAndroid Build Coastguard Worker             case JDWP_TAG(BOOLEAN):
365*e82f7db8SAndroid Build Coastguard Worker                 return outStream_writeBoolean(out, value.z);
366*e82f7db8SAndroid Build Coastguard Worker 
367*e82f7db8SAndroid Build Coastguard Worker             case JDWP_TAG(VOID):  /* happens with function return values */
368*e82f7db8SAndroid Build Coastguard Worker                 /* write nothing */
369*e82f7db8SAndroid Build Coastguard Worker                 return JDWP_ERROR(NONE);
370*e82f7db8SAndroid Build Coastguard Worker 
371*e82f7db8SAndroid Build Coastguard Worker             default:
372*e82f7db8SAndroid Build Coastguard Worker                 EXIT_ERROR(AGENT_ERROR_INVALID_OBJECT,"Invalid type key");
373*e82f7db8SAndroid Build Coastguard Worker                 break;
374*e82f7db8SAndroid Build Coastguard Worker         }
375*e82f7db8SAndroid Build Coastguard Worker     }
376*e82f7db8SAndroid Build Coastguard Worker     return JDWP_ERROR(NONE);
377*e82f7db8SAndroid Build Coastguard Worker }
378*e82f7db8SAndroid Build Coastguard Worker 
379*e82f7db8SAndroid Build Coastguard Worker jdwpError
outStream_skipBytes(PacketOutputStream * stream,jint count)380*e82f7db8SAndroid Build Coastguard Worker outStream_skipBytes(PacketOutputStream *stream, jint count)
381*e82f7db8SAndroid Build Coastguard Worker {
382*e82f7db8SAndroid Build Coastguard Worker     int i;
383*e82f7db8SAndroid Build Coastguard Worker     for (i = 0; i < count; i++) {
384*e82f7db8SAndroid Build Coastguard Worker         (void)outStream_writeByte(stream, 0);
385*e82f7db8SAndroid Build Coastguard Worker     }
386*e82f7db8SAndroid Build Coastguard Worker     return stream->error;
387*e82f7db8SAndroid Build Coastguard Worker }
388*e82f7db8SAndroid Build Coastguard Worker 
389*e82f7db8SAndroid Build Coastguard Worker jdwpError
outStream_error(PacketOutputStream * stream)390*e82f7db8SAndroid Build Coastguard Worker outStream_error(PacketOutputStream *stream)
391*e82f7db8SAndroid Build Coastguard Worker {
392*e82f7db8SAndroid Build Coastguard Worker     return stream->error;
393*e82f7db8SAndroid Build Coastguard Worker }
394*e82f7db8SAndroid Build Coastguard Worker 
395*e82f7db8SAndroid Build Coastguard Worker void
outStream_setError(PacketOutputStream * stream,jdwpError error)396*e82f7db8SAndroid Build Coastguard Worker outStream_setError(PacketOutputStream *stream, jdwpError error)
397*e82f7db8SAndroid Build Coastguard Worker {
398*e82f7db8SAndroid Build Coastguard Worker     if (stream->error == JDWP_ERROR(NONE)) {
399*e82f7db8SAndroid Build Coastguard Worker         stream->error = error;
400*e82f7db8SAndroid Build Coastguard Worker         LOG_MISC(("outStream_setError error=%s(%d)", jdwpErrorText(error), error));
401*e82f7db8SAndroid Build Coastguard Worker     }
402*e82f7db8SAndroid Build Coastguard Worker }
403*e82f7db8SAndroid Build Coastguard Worker 
404*e82f7db8SAndroid Build Coastguard Worker static jint
outStream_send(PacketOutputStream * stream)405*e82f7db8SAndroid Build Coastguard Worker outStream_send(PacketOutputStream *stream) {
406*e82f7db8SAndroid Build Coastguard Worker 
407*e82f7db8SAndroid Build Coastguard Worker     jint rc;
408*e82f7db8SAndroid Build Coastguard Worker     jint len = 0;
409*e82f7db8SAndroid Build Coastguard Worker     PacketData *segment;
410*e82f7db8SAndroid Build Coastguard Worker     jbyte *data, *posP;
411*e82f7db8SAndroid Build Coastguard Worker 
412*e82f7db8SAndroid Build Coastguard Worker     /*
413*e82f7db8SAndroid Build Coastguard Worker      * If there's only 1 segment then we just send the
414*e82f7db8SAndroid Build Coastguard Worker      * packet.
415*e82f7db8SAndroid Build Coastguard Worker      */
416*e82f7db8SAndroid Build Coastguard Worker     if (stream->firstSegment.next == NULL) {
417*e82f7db8SAndroid Build Coastguard Worker         stream->packet.type.cmd.len = 11 + stream->firstSegment.length;
418*e82f7db8SAndroid Build Coastguard Worker         stream->packet.type.cmd.data = stream->firstSegment.data;
419*e82f7db8SAndroid Build Coastguard Worker         rc = transport_sendPacket(&stream->packet);
420*e82f7db8SAndroid Build Coastguard Worker         return rc;
421*e82f7db8SAndroid Build Coastguard Worker     }
422*e82f7db8SAndroid Build Coastguard Worker 
423*e82f7db8SAndroid Build Coastguard Worker     /*
424*e82f7db8SAndroid Build Coastguard Worker      * Multiple segments
425*e82f7db8SAndroid Build Coastguard Worker      */
426*e82f7db8SAndroid Build Coastguard Worker     len = 0;
427*e82f7db8SAndroid Build Coastguard Worker     segment = (PacketData *)&(stream->firstSegment);
428*e82f7db8SAndroid Build Coastguard Worker     do {
429*e82f7db8SAndroid Build Coastguard Worker         len += segment->length;
430*e82f7db8SAndroid Build Coastguard Worker         segment = segment->next;
431*e82f7db8SAndroid Build Coastguard Worker     } while (segment != NULL);
432*e82f7db8SAndroid Build Coastguard Worker 
433*e82f7db8SAndroid Build Coastguard Worker     data = jvmtiAllocate(len);
434*e82f7db8SAndroid Build Coastguard Worker     if (data == NULL) {
435*e82f7db8SAndroid Build Coastguard Worker         return JDWP_ERROR(OUT_OF_MEMORY);
436*e82f7db8SAndroid Build Coastguard Worker     }
437*e82f7db8SAndroid Build Coastguard Worker 
438*e82f7db8SAndroid Build Coastguard Worker     posP = data;
439*e82f7db8SAndroid Build Coastguard Worker     segment = (PacketData *)&(stream->firstSegment);
440*e82f7db8SAndroid Build Coastguard Worker     while (segment != NULL) {
441*e82f7db8SAndroid Build Coastguard Worker         (void)memcpy(posP, segment->data, segment->length);
442*e82f7db8SAndroid Build Coastguard Worker         posP += segment->length;
443*e82f7db8SAndroid Build Coastguard Worker         segment = segment->next;
444*e82f7db8SAndroid Build Coastguard Worker     }
445*e82f7db8SAndroid Build Coastguard Worker 
446*e82f7db8SAndroid Build Coastguard Worker     stream->packet.type.cmd.len = 11 + len;
447*e82f7db8SAndroid Build Coastguard Worker     stream->packet.type.cmd.data = data;
448*e82f7db8SAndroid Build Coastguard Worker     rc = transport_sendPacket(&stream->packet);
449*e82f7db8SAndroid Build Coastguard Worker     stream->packet.type.cmd.data = NULL;
450*e82f7db8SAndroid Build Coastguard Worker     jvmtiDeallocate(data);
451*e82f7db8SAndroid Build Coastguard Worker 
452*e82f7db8SAndroid Build Coastguard Worker     return rc;
453*e82f7db8SAndroid Build Coastguard Worker }
454*e82f7db8SAndroid Build Coastguard Worker 
455*e82f7db8SAndroid Build Coastguard Worker void
outStream_sendReply(PacketOutputStream * stream)456*e82f7db8SAndroid Build Coastguard Worker outStream_sendReply(PacketOutputStream *stream)
457*e82f7db8SAndroid Build Coastguard Worker {
458*e82f7db8SAndroid Build Coastguard Worker     jint rc;
459*e82f7db8SAndroid Build Coastguard Worker     if (stream->error) {
460*e82f7db8SAndroid Build Coastguard Worker         /*
461*e82f7db8SAndroid Build Coastguard Worker          * Don't send any collected stream data on an error reply
462*e82f7db8SAndroid Build Coastguard Worker          */
463*e82f7db8SAndroid Build Coastguard Worker         stream->packet.type.reply.len = 0;
464*e82f7db8SAndroid Build Coastguard Worker         stream->packet.type.reply.errorCode = (jshort)stream->error;
465*e82f7db8SAndroid Build Coastguard Worker     }
466*e82f7db8SAndroid Build Coastguard Worker     rc = outStream_send(stream);
467*e82f7db8SAndroid Build Coastguard Worker     if (rc == 0) {
468*e82f7db8SAndroid Build Coastguard Worker         stream->sent = JNI_TRUE;
469*e82f7db8SAndroid Build Coastguard Worker     }
470*e82f7db8SAndroid Build Coastguard Worker }
471*e82f7db8SAndroid Build Coastguard Worker 
472*e82f7db8SAndroid Build Coastguard Worker void
outStream_sendCommand(PacketOutputStream * stream)473*e82f7db8SAndroid Build Coastguard Worker outStream_sendCommand(PacketOutputStream *stream)
474*e82f7db8SAndroid Build Coastguard Worker {
475*e82f7db8SAndroid Build Coastguard Worker     jint rc;
476*e82f7db8SAndroid Build Coastguard Worker     if (!stream->error) {
477*e82f7db8SAndroid Build Coastguard Worker         rc = outStream_send(stream);
478*e82f7db8SAndroid Build Coastguard Worker         if (rc == 0) {
479*e82f7db8SAndroid Build Coastguard Worker             stream->sent = JNI_TRUE;
480*e82f7db8SAndroid Build Coastguard Worker         }
481*e82f7db8SAndroid Build Coastguard Worker     }
482*e82f7db8SAndroid Build Coastguard Worker }
483*e82f7db8SAndroid Build Coastguard Worker 
484*e82f7db8SAndroid Build Coastguard Worker 
485*e82f7db8SAndroid Build Coastguard Worker static jboolean
releaseID(void * elementPtr,void * arg)486*e82f7db8SAndroid Build Coastguard Worker releaseID(void *elementPtr, void *arg)
487*e82f7db8SAndroid Build Coastguard Worker {
488*e82f7db8SAndroid Build Coastguard Worker     jlong *idPtr = elementPtr;
489*e82f7db8SAndroid Build Coastguard Worker     commonRef_release(getEnv(), *idPtr);
490*e82f7db8SAndroid Build Coastguard Worker     return JNI_TRUE;
491*e82f7db8SAndroid Build Coastguard Worker }
492*e82f7db8SAndroid Build Coastguard Worker 
493*e82f7db8SAndroid Build Coastguard Worker void
outStream_destroy(PacketOutputStream * stream)494*e82f7db8SAndroid Build Coastguard Worker outStream_destroy(PacketOutputStream *stream)
495*e82f7db8SAndroid Build Coastguard Worker {
496*e82f7db8SAndroid Build Coastguard Worker     struct PacketData *next;
497*e82f7db8SAndroid Build Coastguard Worker 
498*e82f7db8SAndroid Build Coastguard Worker     if (stream->error || !stream->sent) {
499*e82f7db8SAndroid Build Coastguard Worker         (void)bagEnumerateOver(stream->ids, releaseID, NULL);
500*e82f7db8SAndroid Build Coastguard Worker     }
501*e82f7db8SAndroid Build Coastguard Worker 
502*e82f7db8SAndroid Build Coastguard Worker     next = stream->firstSegment.next;
503*e82f7db8SAndroid Build Coastguard Worker     while (next != NULL) {
504*e82f7db8SAndroid Build Coastguard Worker         struct PacketData *p = next;
505*e82f7db8SAndroid Build Coastguard Worker         next = p->next;
506*e82f7db8SAndroid Build Coastguard Worker         jvmtiDeallocate(p->data);
507*e82f7db8SAndroid Build Coastguard Worker         jvmtiDeallocate(p);
508*e82f7db8SAndroid Build Coastguard Worker     }
509*e82f7db8SAndroid Build Coastguard Worker     bagDestroyBag(stream->ids);
510*e82f7db8SAndroid Build Coastguard Worker }
511