/* * Dump the contents of a packet to stdout. */ static void dumpPacket(const unsigned char* packetBuf, const char* srcName, const char* dstName) { const unsigned char* buf = packetBuf; char prefix[3]; u4 length, id; u1 flags, cmdSet=0, cmd=0; JdwpError error = ERR_NONE; bool reply; int dataLen; length = get4BE(buf+0); id = get4BE(buf+4); flags = get1(buf+8); if ((flags & kJDWPFlagReply) != 0) { reply = true; error = static_cast<JdwpError>(get2BE(buf+9)); } else { reply = false; cmdSet = get1(buf+9); cmd = get1(buf+10); } buf += kJDWPHeaderLen; dataLen = length - (buf - packetBuf); if (!reply) { prefix[0] = srcName[0]; prefix[1] = '>'; } else { prefix[0] = dstName[0]; prefix[1] = '<'; } prefix[2] = '\0'; int min, sec; getCurrentTime(&min, &sec); if (!reply) { printf("%s REQUEST dataLen=%-5u id=0x%08x flags=0x%02x cmd=%d/%d [%02d:%02d]\n", prefix, dataLen, id, flags, cmdSet, cmd, min, sec); printf("%s --> %s\n", prefix, getCommandName(cmdSet, cmd)); } else { printf("%s REPLY dataLen=%-5u id=0x%08x flags=0x%02x err=%d (%s) [%02d:%02d]\n", prefix, dataLen, id, flags, error, dvmJdwpErrorStr(error), min,sec); } if (dataLen > 0) printHexDump2(buf, dataLen, prefix); printf("%s ----------\n", prefix); }
/* * Handle a packet. Returns "false" if we encounter a connection-fatal error. */ static bool handlePacket(Peer* pDst, Peer* pSrc) { const unsigned char* buf = pSrc->inputBuffer; u4 length; u1 flags; int cc; length = get4BE(buf+0); flags = get1(buf+9); assert((int) length <= pSrc->inputCount); dumpPacket(buf, pSrc->label, pDst->label); cc = write(pDst->sock, buf, length); if (cc != (int) length) { fprintf(stderr, "Failed sending packet: %s\n", strerror(errno)); return false; } /*printf("*** wrote %d bytes from %c to %c\n", cc, pSrc->label[0], pDst->label[0]);*/ consumeBytes(pSrc, length); return true; }
void MrwDecoder::parseHeader() { const unsigned char* data = mFile->getData(0); if (mFile->getSize() < 30) ThrowRDE("Not a valid MRW file (size too small)"); if (!isMRW(mFile)) ThrowRDE("This isn't actually a MRW file, why are you calling me?"); data_offset = get4BE(data,4)+8; if (!mFile->isValid(data_offset)) ThrowRDE("MRW: Data offset is invalid"); // Make sure all values have at least been initialized raw_width = raw_height = packed = 0; wb_coeffs[0] = wb_coeffs[1] = wb_coeffs[2] = wb_coeffs[3] = NAN; uint32 currpos = 8; while (currpos < data_offset) { uint32 tag = get4BE(data,currpos); uint32 len = get4BE(data,currpos+4); switch(tag) { case 0x505244: // PRD raw_height = get2BE(data,currpos+16); raw_width = get2BE(data,currpos+18); packed = (data[currpos+24] == 12); case 0x574247: // WBG for(uint32 i=0; i<4; i++) wb_coeffs[i] = (float)get2BE(data, currpos+12+i*2); break; case 0x545457: // TTW // Base value for offsets needs to be at the beginning of the TIFF block, not the file FileMap *f = new FileMap(mFile->getDataWrt(currpos+8), mFile->getSize()-currpos-8); if (little == getHostEndianness()) tiff_meta = new TiffIFDBE(f, 8); else tiff_meta = new TiffIFD(f, 8); delete f; break; } currpos += MAX(len+8,1); // MAX(,1) to make sure we make progress } }
/* * Figure out if we have a full packet in the buffer. */ static bool haveFullPacket(JdwpNetState* netState) { long length; if (netState->awaitingHandshake) return (netState->inputCount >= (int) kMagicHandshakeLen); if (netState->inputCount < 4) return false; length = get4BE(netState->inputBuffer); return (netState->inputCount >= length); }
/* * Figure out if we have a full packet in the buffer. */ static bool haveFullPacket(Peer* pPeer) { long length; if (pPeer->awaitingHandshake) return (pPeer->inputCount >= kMagicHandshakeLen); if (pPeer->inputCount < 4) return false; length = get4BE(pPeer->inputBuffer); return (pPeer->inputCount >= length); }
/* * "buf" contains a full JDWP packet, possibly with multiple chunks. We * need to process each, accumulate the replies, and ship the whole thing * back. * * Returns "true" if we have a reply. The reply buffer is newly allocated, * and includes the chunk type/length, followed by the data. * * TODO: we currently assume that the request and reply include a single * chunk. If this becomes inconvenient we will need to adapt. */ bool dvmDdmHandlePacket(const u1* buf, int dataLen, u1** pReplyBuf, int* pReplyLen) { Thread* self = dvmThreadSelf(); const int kChunkHdrLen = 8; ArrayObject* dataArray = NULL; bool result = false; assert(dataLen >= 0); /* * Prep DdmServer. We could throw this in gDvm. */ ClassObject* ddmServerClass; Method* dispatch; ddmServerClass = dvmFindClass("Lorg/apache/harmony/dalvik/ddmc/DdmServer;", NULL); if (ddmServerClass == NULL) { LOGW("Unable to find org.apache.harmony.dalvik.ddmc.DdmServer\n"); goto bail; } dispatch = dvmFindDirectMethodByDescriptor(ddmServerClass, "dispatch", "(I[BII)Lorg/apache/harmony/dalvik/ddmc/Chunk;"); if (dispatch == NULL) { LOGW("Unable to find DdmServer.dispatch\n"); goto bail; } /* * Prep Chunk. */ int chunkTypeOff, chunkDataOff, chunkOffsetOff, chunkLengthOff; ClassObject* chunkClass; chunkClass = dvmFindClass("Lorg/apache/harmony/dalvik/ddmc/Chunk;", NULL); if (chunkClass == NULL) { LOGW("Unable to find org.apache.harmony.dalvik.ddmc.Chunk\n"); goto bail; } chunkTypeOff = dvmFindFieldOffset(chunkClass, "type", "I"); chunkDataOff = dvmFindFieldOffset(chunkClass, "data", "[B"); chunkOffsetOff = dvmFindFieldOffset(chunkClass, "offset", "I"); chunkLengthOff = dvmFindFieldOffset(chunkClass, "length", "I"); if (chunkTypeOff < 0 || chunkDataOff < 0 || chunkOffsetOff < 0 || chunkLengthOff < 0) { LOGW("Unable to find all chunk fields\n"); goto bail; } /* * The chunk handlers are written in the Java programming language, so * we need to convert the buffer to a byte array. */ dataArray = dvmAllocPrimitiveArray('B', dataLen, ALLOC_DEFAULT); if (dataArray == NULL) { LOGW("array alloc failed (%d)\n", dataLen); dvmClearException(self); goto bail; } memcpy(dataArray->contents, buf, dataLen); /* * Run through and find all chunks. [Currently just find the first.] */ unsigned int offset, length, type; type = get4BE((u1*)dataArray->contents + 0); length = get4BE((u1*)dataArray->contents + 4); offset = kChunkHdrLen; if (offset+length > (unsigned int) dataLen) { LOGW("WARNING: bad chunk found (len=%u pktLen=%d)\n", length, dataLen); goto bail; } /* * Call the handler. */ JValue callRes; dvmCallMethod(self, dispatch, NULL, &callRes, type, dataArray, offset, length); if (dvmCheckException(self)) { LOGI("Exception thrown by dispatcher for 0x%08x\n", type); dvmLogExceptionStackTrace(); dvmClearException(self); goto bail; } Object* chunk; ArrayObject* replyData; chunk = (Object*) callRes.l; if (chunk == NULL) goto bail; /* * Pull the pieces out of the chunk. We copy the results into a * newly-allocated buffer that the caller can free. We don't want to * continue using the Chunk object because nothing has a reference to it. * (If we do an alloc in here, we need to dvmAddTrackedAlloc it.) * * We could avoid this by returning type/data/offset/length and having * the caller be aware of the object lifetime issues, but that * integrates the JDWP code more tightly into the VM, and doesn't work * if we have responses for multiple chunks. * * So we're pretty much stuck with copying data around multiple times. */ type = dvmGetFieldInt(chunk, chunkTypeOff); replyData = (ArrayObject*) dvmGetFieldObject(chunk, chunkDataOff); offset = dvmGetFieldInt(chunk, chunkOffsetOff); length = dvmGetFieldInt(chunk, chunkLengthOff); LOGV("DDM reply: type=0x%08x data=%p offset=%d length=%d\n", type, replyData, offset, length); if (length == 0 || replyData == NULL) goto bail; if (offset + length > replyData->length) { LOGW("WARNING: chunk off=%d len=%d exceeds reply array len %d\n", offset, length, replyData->length); goto bail; } u1* reply; reply = (u1*) malloc(length + kChunkHdrLen); if (reply == NULL) { LOGW("malloc %d failed\n", length+kChunkHdrLen); goto bail; } set4BE(reply + 0, type); set4BE(reply + 4, length); memcpy(reply+kChunkHdrLen, (const u1*)replyData->contents + offset, length); *pReplyBuf = reply; *pReplyLen = length + kChunkHdrLen; result = true; LOGV("dvmHandleDdm returning type=%.4s buf=%p len=%d\n", (char*) reply, reply, length); bail: dvmReleaseTrackedAlloc((Object*) dataArray, NULL); return result; }