Ejemplo n.º 1
0
ICOImageDecoder::IconDirectoryEntry ICOImageDecoder::readDirectoryEntry() {
  // Read icon data.
  // The following calls to readUint8() return a uint8_t, which is appropriate
  // because that's the on-disk type of the width and height values.  Storing
  // them in ints (instead of matching uint8_ts) is so we can record dimensions
  // of size 256 (which is what a zero byte really means).
  int width = readUint8(0);
  if (!width)
    width = 256;
  int height = readUint8(1);
  if (!height)
    height = 256;
  IconDirectoryEntry entry;
  entry.m_size = IntSize(width, height);
  if (m_fileType == CURSOR) {
    entry.m_bitCount = 0;
    entry.m_hotSpot = IntPoint(readUint16(4), readUint16(6));
  } else {
    entry.m_bitCount = readUint16(6);
    entry.m_hotSpot = IntPoint();
  }
  entry.m_byteSize = readUint32(8);
  entry.m_imageOffset = readUint32(12);

  // Some icons don't have a bit depth, only a color count.  Convert the
  // color count to the minimum necessary bit depth.  It doesn't matter if
  // this isn't quite what the bitmap info header says later, as we only use
  // this value to determine which icon entry is best.
  if (!entry.m_bitCount) {
    int colorCount = readUint8(2);
    if (!colorCount)
      colorCount = 256;  // Vague in the spec, needed by real-world icons.
    for (--colorCount; colorCount; colorCount >>= 1)
      ++entry.m_bitCount;
  }
Ejemplo n.º 2
0
TOptIAPrefix::TOptIAPrefix(const char * buf, size_t len, TMsg* parent)
    :TOpt(OPTION_IAPREFIX, parent), Valid_(false)
{
    if (len >= 25)
    {
        PrefLifetime_ = readUint32(buf);
        buf += sizeof(uint32_t);
        len -= sizeof(uint32_t);

        ValidLifetime_ = readUint32(buf);
        buf += sizeof(uint32_t);
        len -= sizeof(uint32_t);

        PrefixLength_  = *buf;
        buf += 1;
        len -= 1;

        Prefix_ = new TIPv6Addr(buf);
        buf += 16;
        len -= 16;

        Valid_ = parseOptions(SubOptions, buf, len, parent, OPTION_IAPREFIX,
                              "IAPrefix option");
    }
}
Ejemplo n.º 3
0
IsoMediaFile::Auxiliary WriterConfig::readAuxiliary(const Json::Value& auxValues) const
{
    IsoMediaFile::Auxiliary aux;
    aux.file_path = auxValues["file_path"].asString();
    aux.idxs_list = parseIndexList(auxValues["idxs_list"]);
    aux.refs_list = parseRefsList(auxValues["refs_list"]);
    aux.uniq_bsid = readOptionalUint(auxValues["uniq_bsid"]);
    aux.disp_xdim = readUint32(auxValues, "disp_xdim");
    aux.disp_ydim = readUint32(auxValues, "disp_ydim");
    aux.hidden = readBool(auxValues["hidden"], true);

    aux.urn = auxValues["urn"].asString();

    return aux;
}
Ejemplo n.º 4
0
bool BMPImageReader::readInfoHeaderSize() {
  // Get size of info header.
  ASSERT(m_decodedOffset == m_headerOffset);
  if ((m_decodedOffset > m_data->size()) ||
      ((m_data->size() - m_decodedOffset) < 4))
    return false;
  m_infoHeader.biSize = readUint32(0);
  // Don't increment m_decodedOffset here, it just makes the code in
  // processInfoHeader() more confusing.

  // Don't allow the header to overflow (which would be harmless here, but
  // problematic or at least confusing in other places), or to overrun the
  // image data.
  const size_t headerEnd = m_headerOffset + m_infoHeader.biSize;
  if ((headerEnd < m_headerOffset) ||
      (m_imgDataOffset && (m_imgDataOffset < headerEnd)))
    return m_parent->setFailed();

  // See if this is a header size we understand:
  // OS/2 1.x: 12
  if (m_infoHeader.biSize == 12)
    m_isOS21x = true;
  // Windows V3: 40
  else if ((m_infoHeader.biSize == 40) || isWindowsV4Plus())
    ;
  // OS/2 2.x: any multiple of 4 between 16 and 64, inclusive, or 42 or 46
  else if ((m_infoHeader.biSize >= 16) && (m_infoHeader.biSize <= 64) &&
           (!(m_infoHeader.biSize & 3) || (m_infoHeader.biSize == 42) ||
            (m_infoHeader.biSize == 46)))
    m_isOS22x = true;
  else
    return m_parent->setFailed();

  return true;
}
Ejemplo n.º 5
0
CudaDecodedContext *decodeGpu(DecoderMetadata decoderMetadata) {
    if (useDynamicParallelism) {
        return decodeGpuDynamic(decoderMetadata);
    }
    uint8_t *pduBuffers = decoderMetadata.pduBuffers;
    uint32_t size = decoderMetadata.size;
    uint64_t bufferCapacity = decoderMetadata.bufferCapacity;
    uint32_t correlationIdLength = decoderMetadata.correlationIdLength;
    ByteBufferContext byteBufferContext = {pduBuffers, 0, (uint64_t) bufferCapacity};
    CudaPduContext *pduContexts = cudaPduContext;
    int i;
    int startPosition = 0;
    for (i = 0; i < size; i++) {
        byteBufferContext.readIndex += 12;
        char *correlationId = readStringByLength(&byteBufferContext, correlationIdLength);
        uint32_t pduLength = readUint32(&byteBufferContext);
        int startIndex = startPosition + correlationIdLength + 12;
        strncpy(pduContexts[i].correlationId, correlationId, sizeof(char) * (correlationIdLength + 1));
        pduContexts[i].start = (uint32_t) startIndex;
        pduContexts[i].length = pduLength;
        startPosition += (correlationIdLength + pduLength + 12);
        byteBufferContext.readIndex = (uint64_t) startPosition;
    }

    CudaDecodedContext *decodedPduStructList = malloc(sizeof(CudaDecodedContext) * size);
    CudaMetadata metadata = {size, pduBuffers, pduContexts, decodedPduStructList, (uint64_t) bufferCapacity,
                             decoderMetadata.blockDim, decoderMetadata.gridDim};
    decodeCuda(metadata);
    return decodedPduStructList;
}
Ejemplo n.º 6
0
static bool checkExifHeader(jpeg_saved_marker_ptr marker, bool& isBigEndian, unsigned& ifdOffset)
{
    // For exif data, the APP1 block is followed by 'E', 'x', 'i', 'f', '\0',
    // then a fill byte, and then a tiff file that contains the metadata.
    // A tiff file starts with 'I', 'I' (intel / little endian byte order) or
    // 'M', 'M' (motorola / big endian byte order), followed by (uint16_t)42,
    // followed by an uint32_t with the offset to the tag block, relative to the
    // tiff file start.
    const unsigned exifHeaderSize = 14;
    if (!(marker->marker == exifMarker
        && marker->data_length >= exifHeaderSize
        && marker->data[0] == 'E'
        && marker->data[1] == 'x'
        && marker->data[2] == 'i'
        && marker->data[3] == 'f'
        && marker->data[4] == '\0'
        // data[5] is a fill byte
        && ((marker->data[6] == 'I' && marker->data[7] == 'I')
            || (marker->data[6] == 'M' && marker->data[7] == 'M'))))
        return false;

    isBigEndian = marker->data[6] == 'M';
    if (readUint16(marker->data + 8, isBigEndian) != 42)
        return false;

    ifdOffset = readUint32(marker->data + 10, isBigEndian);
    return true;
}
Ejemplo n.º 7
0
WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
    : ObjectFile(Binary::ID_Wasm, Buffer) {
  ErrorAsOutParameter ErrAsOutParam(&Err);
  Header.Magic = getData().substr(0, 4);
  if (Header.Magic != StringRef("\0asm", 4)) {
    Err = make_error<StringError>("Bad magic number",
                                  object_error::parse_failed);
    return;
  }
  const uint8_t *Ptr = getPtr(4);
  Header.Version = readUint32(Ptr);
  if (Header.Version != wasm::WasmVersion) {
    Err = make_error<StringError>("Bad version number",
                                  object_error::parse_failed);
    return;
  }

  const uint8_t *Eof = getPtr(getData().size());
  wasm::WasmSection Sec;
  while (Ptr < Eof) {
    if ((Err = readSection(Sec, Ptr, getPtr(0))))
      return;
    if (Sec.Type == wasm::WASM_SEC_USER) {
      if ((Err = parseUserSection(Sec, Sec.Content.data(), Sec.Content.size())))
        return;
    }
    Sections.push_back(Sec);
  }
}
Ejemplo n.º 8
0
ICOImageDecoder::IconDirectoryEntry ICOImageDecoder::readDirectoryEntry()
{
    // Read icon data.
    // The casts to uint8_t in the next few lines are because that's the on-disk
    // type of the width and height values.  Storing them in ints (instead of
    // matching uint8_ts) is so we can record dimensions of size 256 (which is
    // what a zero byte really means).
    int width = static_cast<uint8_t>(m_data->data()[m_decodedOffset]);
    if (!width)
        width = 256;
    int height = static_cast<uint8_t>(m_data->data()[m_decodedOffset + 1]);
    if (!height)
        height = 256;
    IconDirectoryEntry entry;
    entry.m_size = IntSize(width, height);
    if (m_fileType == CURSOR) {
        entry.m_bitCount = 0;
        entry.m_hotSpot = IntPoint(readUint16(4), readUint16(6));
    } else {
        entry.m_bitCount = readUint16(6);
        entry.m_hotSpot = IntPoint();
    }
    entry.m_imageOffset = readUint32(12);

    // Some icons don't have a bit depth, only a color count.  Convert the
    // color count to the minimum necessary bit depth.  It doesn't matter if
    // this isn't quite what the bitmap info header says later, as we only use
    // this value to determine which icon entry is best.
    if (!entry.m_bitCount) {
        int colorCount = static_cast<uint8_t>(m_data->data()[m_decodedOffset + 2]);
        if (!colorCount)
            colorCount = 256;  // Vague in the spec, needed by real-world icons.
        for (--colorCount; colorCount; colorCount >>= 1)
            ++entry.m_bitCount;
    }
Ejemplo n.º 9
0
float IFileStream::readFloat()
{
	Uint32 tmp = readUint32();
	float tmp2;
	memcpy(&tmp2,&tmp,sizeof(Uint32)); // workaround for a strange optimization in gcc 4.1
	return tmp2;
}
Ejemplo n.º 10
0
bool BMPImageDecoder::processFileHeader(size_t* imgDataOffset)
{
    ASSERT(imgDataOffset);

    // Read file header.
    ASSERT(!m_decodedOffset);
    if (m_data->size() < sizeOfFileHeader)
        return false;
    const uint16_t fileType = (m_data->data()[0] << 8) | static_cast<uint8_t>(m_data->data()[1]);
    *imgDataOffset = readUint32(10);
    m_decodedOffset = sizeOfFileHeader;

    // See if this is a bitmap filetype we understand.
    enum {
        BMAP = 0x424D,  // "BM"
        // The following additional OS/2 2.x header values (see
        // http://www.fileformat.info/format/os2bmp/egff.htm ) aren't widely
        // decoded, and are unlikely to be in much use.
        /*
        ICON = 0x4943,  // "IC"
        POINTER = 0x5054,  // "PT"
        COLORICON = 0x4349,  // "CI"
        COLORPOINTER = 0x4350,  // "CP"
        BITMAPARRAY = 0x4241,  // "BA"
        */
    };
    return (fileType == BMAP) || setFailed();
}
Ejemplo n.º 11
0
TOptIAAddress::TOptIAAddress(char * &buf, int& n, TMsg* parent)
    :TOpt(OPTION_IAADDR, parent), Valid_(false)
{
    if ( n >= 24) {
        Addr_ = new TIPv6Addr(buf);
        buf += 16;
        n -= 16;
        PrefLifetime_ = readUint32(buf);
        buf += sizeof(uint32_t);
        n -= sizeof(uint32_t);
        ValidLifetime_ = readUint32(buf);
        buf += sizeof(uint32_t);
        n -= sizeof(uint32_t);

        Valid_ = true;
    }
}
Ejemplo n.º 12
0
void loadModules(void * payloadStart, void ** targetModuleAddress)
{
	int i;
	uint8_t * currentModule = (uint8_t*)payloadStart;
	uint32_t moduleCount = readUint32(&currentModule);

	for (i = 0; i < moduleCount; i++)
		loadModule(&currentModule, targetModuleAddress[i]);
}
Ejemplo n.º 13
0
/*
 * edpCommandReqParse
 * 按照EDP命令请求协议,解析数据
 */
int edpCommandReqParse(edp_pkt* pkt, char *id, char *cmd, int32 *rmlen, int32 *id_len, int32 *cmd_len)
{
  readUint8(pkt);     /* 包类型 */
  *rmlen = readRemainlen(pkt);    /* 剩余长度 */
  *id_len = readUint16(pkt);      /* ID长度 */
  readStr(pkt, id, *id_len);      /* 命令ID */
  *cmd_len = readUint32(pkt);     /* 命令长度 */
  readStr(pkt, cmd, *cmd_len);    /* 命令内容 */
}
Ejemplo n.º 14
0
glm::vec4 kit::readVec4i(std::istream & s)
{
  glm::ivec4 v;
  for (int x = 0; x < 4; x++)
  {
    v[x] = readUint32(s);
  }

  return v;
}
Ejemplo n.º 15
0
uint cVirtualMemoryAccesser::readUint(addressNumericValue address) const
{
    // If this change, than the implementation must be changed also
    ASSERT(sizeof(uint) == sizeof(uint32));

    uint8 buf[4];
    if (!memread(address, &buf, sizeof(buf), NULL))
        XSTL_THROW(cException, EXCEPTION_OUT_OF_RANGE);

    return readUint32(buf);
}
Ejemplo n.º 16
0
DecodedContext *decodePthread(DecoderMetadata decoderMetadata) {

    uint8_t *pduBuffers = decoderMetadata.pduBuffers;
    uint32_t size = decoderMetadata.size;
    uint64_t bufferCapacity = decoderMetadata.bufferCapacity;
    uint32_t correlationIdLength = decoderMetadata.correlationIdLength;

    ByteBufferContext byteBufferContext = {pduBuffers, 0, bufferCapacity};
    DirectPduContext *pduContexts = malloc(sizeof(DirectPduContext) * size);
    int i;
    int startPosition = 0;
    for (i = 0; i < size; i++) {
        byteBufferContext.readIndex += 12;
        char *correlationId = readStringByLength(&byteBufferContext, correlationIdLength);
        uint32_t pduLength = readUint32(&byteBufferContext);
        int startIndex = startPosition + correlationIdLength + 12;
        pduContexts[i].correlationId = correlationId;
        pduContexts[i].pduBuffer = pduBuffers;
        pduContexts[i].start = startIndex;
        pduContexts[i].length = pduLength;
        startPosition += (correlationIdLength + pduLength + 12);
        byteBufferContext.readIndex = startPosition;
    }

    int nThread = nCpuCores;
    int index = 0;
    int batchSize = size > nThread ? size / nThread : size;
    DecodedContext *decodedPduStructList = malloc(sizeof(DecodedContext) * size);
    ThreadParam *threadParams[nThread];

    pthread_t threads[nThread];
    int threadIndex = 0;
    while (index < size) {
        int startIndex = index;
        int length = (size - index) <= batchSize ? (size - index) : batchSize;
        index += length;
        ThreadParam *threadParam = malloc(sizeof(ThreadParam));
        threadParam->startIndex = startIndex;
        threadParam->length = length;
        threadParam->pduContexts = pduContexts;
        threadParam->decodedPduStructList = decodedPduStructList;
        threadParams[threadIndex] = threadParam;
        int state = pthread_create(&threads[threadIndex], NULL, decode, (void *) threadParam);
        threadIndex++;
    }

    for (i = 0; i < threadIndex; i++) {
        pthread_join(threads[i], NULL);
    }
    free(pduContexts);
    return decodedPduStructList;
}
Ejemplo n.º 17
0
std::string BufferObjectReader::readString()
{
   // Note: If you change this, you need to change STRING_LENGTH_SIZE
   vpr::Uint32 str_len = readUint32();
   std::string ret_val;
   char tempChar;
   for(vpr::Uint32 i=0; i<str_len;++i)
   {
      tempChar = static_cast<char>(*readRaw(1));
      ret_val += tempChar;
   }
   return ret_val;
}
Ejemplo n.º 18
0
char* State_Payload_read(struct Packet* p, char* buffer, int ascii) {
    if (!ascii) {
        buffer = readUint32(&(p->seq), buffer);
        buffer = readUint16((uint16_t*)&(p->state.leftEncoder), buffer);
        buffer = readUint16((uint16_t*)&(p->state.rightEncoder), buffer);
    } else {
        long int a, b, c = 0;
        sscanf(buffer, "%ld %ld %ld", &a, &b, &c);
        p->seq = (uint32_t) a;
        p->state.leftEncoder = (uint16_t) b;
        p->state.rightEncoder = (uint16_t) c;

    }
    return buffer;
}
Ejemplo n.º 19
0
static void loadModule(uint8_t ** module, void * targetModuleAddress)
{
	uint32_t moduleSize = readUint32(module);

	ncPrint("  Will copy module at 0x");
	ncPrintHex((uint64_t)*module);
	ncPrint(" to 0x");
	ncPrintHex((uint64_t)targetModuleAddress);
	ncPrint(" (");
	ncPrintDec(moduleSize);
	ncPrint(" bytes)");

	memcpy(targetModuleAddress, *module, moduleSize);
	*module += moduleSize;

	ncPrint(" [Done]");
	ncNewline();
}
Ejemplo n.º 20
0
eaio::size_type eaio::readString(IStream* pIS, char8_t* pBuffer, size_type nMaxCount, eaio::Endian endianSource)
{
    const off_type ninitialPosition(pIS->getPosition());

    char8_t   cCurrent;
    uint32_t  nLength(0);
    size_type nCount(0); // Number of chars returned to user.
    size_type nResult;

    if(!readUint32(pIS, nLength, endianSource))
        return kSizeTypeError;

    // If no buffer has been provided, just reset the stream and return the length.
    if(!pBuffer)
    {
        pIS->setPosition(ninitialPosition);
        return (size_type)nLength;
    }

    // Determine how many characters we'll actually read into the buffer.
    // 'nMaxCount - 1' because we want to leave room for terminating NUL.
    size_type nreadLength = (nLength < nMaxCount - 1) ? nLength : nMaxCount - 1;

    while(pBuffer && (nCount < nreadLength)) 
    {
        nResult = pIS->read(&cCurrent, sizeof(cCurrent));

        if(nResult != sizeof(cCurrent))
            break;

        *pBuffer++ = cCurrent;
        ++nCount;
    }

    // We may not have been able to read the entire string out of the stream
    // due to the nMaxCount limit, but we still want to advance the stream's
    // position to the end of the string.
    pIS->setPosition(ninitialPosition + (off_type)sizeof(uint32_t) + (off_type)nLength);

    if(pBuffer)
        *pBuffer = '\0';

    return nLength; // Note that we return nLength and not nCount.
}
Ejemplo n.º 21
0
static ImageOrientation readImageOrientation(jpeg_decompress_struct* info)
{
    // The JPEG decoder looks at EXIF metadata.
    // FIXME: Possibly implement XMP and IPTC support.
    const unsigned orientationTag = 0x112;
    const unsigned shortType = 3;
    for (jpeg_saved_marker_ptr marker = info->marker_list; marker; marker = marker->next) {
        bool isBigEndian;
        unsigned ifdOffset;
        if (!checkExifHeader(marker, isBigEndian, ifdOffset))
            continue;
        const unsigned offsetToTiffData = 6; // Account for 'Exif\0<fill byte>' header.
        if (marker->data_length < offsetToTiffData || ifdOffset >= marker->data_length - offsetToTiffData)
            continue;
        ifdOffset += offsetToTiffData;

        // The jpeg exif container format contains a tiff block for metadata.
        // A tiff image file directory (ifd) consists of a uint16_t describing
        // the number of ifd entries, followed by that many entries.
        // When touching this code, it's useful to look at the tiff spec:
        // http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf
        JOCTET* ifd = marker->data + ifdOffset;
        JOCTET* end = marker->data + marker->data_length;
        if (end - ifd < 2)
            continue;
        unsigned tagCount = readUint16(ifd, isBigEndian);
        ifd += 2; // Skip over the uint16 that was just read.

        // Every ifd entry is 2 bytes of tag, 2 bytes of contents datatype,
        // 4 bytes of number-of-elements, and 4 bytes of either offset to the
        // tag data, or if the data is small enough, the inlined data itself.
        const int ifdEntrySize = 12;
        for (unsigned i = 0; i < tagCount && end - ifd >= ifdEntrySize; ++i, ifd += ifdEntrySize) {
            unsigned tag = readUint16(ifd, isBigEndian);
            unsigned type = readUint16(ifd + 2, isBigEndian);
            unsigned count = readUint32(ifd + 4, isBigEndian);
            if (tag == orientationTag && type == shortType && count == 1)
                return ImageOrientation::fromEXIFValue(readUint16(ifd + 8, isBigEndian));
        }
    }

    return ImageOrientation();
}
TOptVendorSpecInfo::TOptVendorSpecInfo(int type, char * buf,  int n, TMsg* parent)
    :TOpt(type, parent)
{
    int optionCode = 0, optionLen = 0;
    if (n<4) {
	Log(Error) << "Unable to parse truncated vendor-spec info option." << LogEnd;
	this->Vendor = 0;
        Valid = false;
	return;
    }

    this->Vendor = readUint32(buf); // enterprise number
    buf += sizeof(uint32_t);
    n   -= sizeof(uint32_t);

    while (n>=4) {
        optionCode = readUint16(buf);
        buf += sizeof(uint16_t); n -= sizeof(uint16_t);
        optionLen  =  readUint16(buf);
        buf += sizeof(uint16_t); n -= sizeof(uint16_t);
        if (optionLen>n) {
            Log(Warning) << "Malformed vendor-spec info option. Suboption " << optionCode
                         << " truncated." << LogEnd;
            Valid = false;
            return;
        }

        SPtr<TOpt> opt = new TOptGeneric(optionCode, buf, optionLen, parent);
        addOption(opt);
        buf += optionLen;
        n   -= optionLen;
    }
    if (n) {
        Log(Warning) << "Extra " << n << " bytes, after parsing suboption " << optionCode
                     << " in vendor-spec info option." << LogEnd;
        Valid = false;
        return;
    }
    Valid = true;
}
ScriptWrappable* V8ScriptValueDeserializerForModules::readDOMObject(
    SerializationTag tag) {
  // Give the core/ implementation a chance to try first.
  // If it didn't recognize the kind of wrapper, try the modules types.
  if (ScriptWrappable* wrappable =
          V8ScriptValueDeserializer::readDOMObject(tag))
    return wrappable;

  switch (tag) {
    case CryptoKeyTag:
      return readCryptoKey();
    case DOMFileSystemTag: {
      uint32_t rawType;
      String name;
      String rootURL;
      if (!readUint32(&rawType) || rawType > FileSystemTypeLast ||
          !readUTF8String(&name) || !readUTF8String(&rootURL))
        return nullptr;
      return DOMFileSystem::create(getScriptState()->getExecutionContext(),
                                   name, static_cast<FileSystemType>(rawType),
                                   KURL(ParsedURLString, rootURL));
    }
    case RTCCertificateTag: {
      String pemPrivateKey;
      String pemCertificate;
      if (!readUTF8String(&pemPrivateKey) || !readUTF8String(&pemCertificate))
        return nullptr;
      std::unique_ptr<WebRTCCertificateGenerator> certificateGenerator(
          Platform::current()->createRTCCertificateGenerator());
      std::unique_ptr<WebRTCCertificate> certificate =
          certificateGenerator->fromPEM(pemPrivateKey, pemCertificate);
      return new RTCCertificate(std::move(certificate));
    }
    default:
      break;
  }
  return nullptr;
}
Ejemplo n.º 24
0
std::string IFileStream::readString()
{
	Uint32 length;

	length = readUint32();

    if(length == 0) {
        return "";
    } else {
        std::string str;

        str.resize(length);

        if(fread(&str[0],length,1,fp) != 1) {
            if(feof(fp) != 0) {
                throw InputStream::eof("IFileStream::readString(): End-of-File reached!");
            } else {
                throw InputStream::error("IFileStream::readString(): An I/O-Error occurred!");
            }
        }

        return str;
    }
}
Ejemplo n.º 25
0
	/*
	 * Copies a module to the target address
	 */
static void loadModule(uint8_t ** module, void * targetModuleAddress)
{
	uint32_t moduleSize = readUint32(module);
	memcpy(targetModuleAddress, *module, moduleSize);
	*module += moduleSize;
}
CryptoKey* V8ScriptValueDeserializerForModules::readCryptoKey() {
  // Read params.
  uint8_t rawKeyType;
  if (!readOneByte(&rawKeyType))
    return nullptr;
  WebCryptoKeyAlgorithm algorithm;
  WebCryptoKeyType keyType = WebCryptoKeyTypeSecret;
  switch (rawKeyType) {
    case AesKeyTag: {
      uint32_t rawId;
      WebCryptoAlgorithmId id;
      uint32_t lengthBytes;
      if (!readUint32(&rawId) || !algorithmIdFromWireFormat(rawId, &id) ||
          !readUint32(&lengthBytes) ||
          lengthBytes > std::numeric_limits<unsigned short>::max() / 8u)
        return nullptr;
      algorithm = WebCryptoKeyAlgorithm::createAes(id, lengthBytes * 8);
      keyType = WebCryptoKeyTypeSecret;
      break;
    }
    case HmacKeyTag: {
      uint32_t lengthBytes;
      uint32_t rawHash;
      WebCryptoAlgorithmId hash;
      if (!readUint32(&lengthBytes) ||
          lengthBytes > std::numeric_limits<unsigned>::max() / 8 ||
          !readUint32(&rawHash) || !algorithmIdFromWireFormat(rawHash, &hash))
        return nullptr;
      algorithm = WebCryptoKeyAlgorithm::createHmac(hash, lengthBytes * 8);
      keyType = WebCryptoKeyTypeSecret;
      break;
    }
    case RsaHashedKeyTag: {
      uint32_t rawId;
      WebCryptoAlgorithmId id;
      uint32_t rawKeyType;
      uint32_t modulusLengthBits;
      uint32_t publicExponentSize;
      const void* publicExponentBytes;
      uint32_t rawHash;
      WebCryptoAlgorithmId hash;
      if (!readUint32(&rawId) || !algorithmIdFromWireFormat(rawId, &id) ||
          !readUint32(&rawKeyType) ||
          !asymmetricKeyTypeFromWireFormat(rawKeyType, &keyType) ||
          !readUint32(&modulusLengthBits) || !readUint32(&publicExponentSize) ||
          !readRawBytes(publicExponentSize, &publicExponentBytes) ||
          !readUint32(&rawHash) || !algorithmIdFromWireFormat(rawHash, &hash))
        return nullptr;
      algorithm = WebCryptoKeyAlgorithm::createRsaHashed(
          id, modulusLengthBits,
          reinterpret_cast<const unsigned char*>(publicExponentBytes),
          publicExponentSize, hash);
      break;
    }
    case EcKeyTag: {
      uint32_t rawId;
      WebCryptoAlgorithmId id;
      uint32_t rawKeyType;
      uint32_t rawNamedCurve;
      WebCryptoNamedCurve namedCurve;
      if (!readUint32(&rawId) || !algorithmIdFromWireFormat(rawId, &id) ||
          !readUint32(&rawKeyType) ||
          !asymmetricKeyTypeFromWireFormat(rawKeyType, &keyType) ||
          !readUint32(&rawNamedCurve) ||
          !namedCurveFromWireFormat(rawNamedCurve, &namedCurve))
        return nullptr;
      algorithm = WebCryptoKeyAlgorithm::createEc(id, namedCurve);
      break;
    }
    case NoParamsKeyTag: {
      uint32_t rawId;
      WebCryptoAlgorithmId id;
      if (!readUint32(&rawId) || !algorithmIdFromWireFormat(rawId, &id))
        return nullptr;
      algorithm = WebCryptoKeyAlgorithm::createWithoutParams(id);
      break;
    }
  }
  if (algorithm.isNull())
    return nullptr;

  // Read key usages.
  uint32_t rawUsages;
  WebCryptoKeyUsageMask usages;
  bool extractable;
  if (!readUint32(&rawUsages) ||
      !keyUsagesFromWireFormat(rawUsages, &usages, &extractable))
    return nullptr;

  // Read key data.
  uint32_t keyDataLength;
  const void* keyData;
  if (!readUint32(&keyDataLength) || !readRawBytes(keyDataLength, &keyData))
    return nullptr;

  WebCryptoKey key = WebCryptoKey::createNull();
  if (!Platform::current()->crypto()->deserializeKeyForClone(
          algorithm, keyType, extractable, usages,
          reinterpret_cast<const unsigned char*>(keyData), keyDataLength, key))
    return nullptr;

  return CryptoKey::create(key);
}
Ejemplo n.º 27
0
void CPacketProcessor::packetReceived(ENetEvent & event)
{
	if (event.packet->dataLength > 0) {
		//First byte is the packet type
		switch (*(event.packet->data))
		{
		case PacketTypes::ENTITY_UPDATE:
		{
			double timeStamp = 0;
			memcpy(&timeStamp, event.packet->data + 1, sizeof(double));
			//Current position in data
			unsigned int index = 9;

			//Process all entity updates
			bool reachedEnd = false;
			while (!reachedEnd)
			{
				//Check to see if there is enough data for entity ID and payload length
				if (event.packet->dataLength - index >= 6)
				{
					uint32_t entityID = readUint32((event.packet->data + index));
					index += 4;
					uint16_t payloadSize = readUint16((event.packet->data + index));
					index += 2;
					IEntity* entity = gSys->pEntitySystem->getEntity(entityID);
					if (entity == nullptr)
					{
						gSys->log("Entity does not exist");
						return;
					}

					entity->parsePacket((event.packet->data + index), payloadSize, timeStamp);
					index += payloadSize;
				}
				else
				{
					reachedEnd = true;
				}
			}
		}
		break;
		case PacketTypes::ENTITY_CREATE:
		{
			unsigned int index = 1;
			uint32_t id = readUint32(event.packet->data + index);

			//Player is already created
			if (id == gSys->pPlayer->getID())
				return;

			index += sizeof(id);
			IEntity* entity;
			switch (*(event.packet->data + index))
			{
			case EntityTypes::PLAYER:
				entity = new CPlayer(id);
				break;
			case EntityTypes::ZOMBIE:
				entity = new CZombie(id);
				break;
			}



			uint16_t payloadSize = readUint16(event.packet->data + index);
			index += sizeof(payloadSize);
			//TODO TIMESTAMP CREATE PACKETS
			entity->parsePacket(event.packet->data + index, payloadSize, 0);
		}
		break;
		case PacketTypes::ENTITY_DELETE:
		{
			if(IEntity* pEntity = gSys->pEntitySystem->getEntity(readUint32(event.packet->data + 1)))
			{
				gSys->pEntitySystem->deleteEntity(pEntity);
			}
		}
		break;
		case PacketTypes::PLAYER_SHOOT:
		{
			uint32_t playerID = readUint32(event.packet->data + 1);
			
			if (CPlayer* pPlayer = static_cast<CPlayer*>(gSys->pEntitySystem->getEntity(readUint32(event.packet->data + 1))))
			{
				pPlayer->fire(readFloat(event.packet->data + 5));
			}
		}
		break;
		case PacketTypes::PLAYER_HIT:
		{
			uint32_t playerID = readUint32(event.packet->data + 1);
			float angle = readFloat(event.packet->data + 5);
			if (IEntity* pEnt = gSys->pEntitySystem->getEntity(readUint32(event.packet->data + 1)))
			{
				pEnt->hit(angle);
			}

			if (CPlayer* pPlayer = static_cast<CPlayer*>(gSys->pEntitySystem->getEntity(readUint32(event.packet->data + 1))))
			{
				CSprite* bloodSprite = gSys->pSpriteRenderer->addSprite(0.5f, 0.2f, 0, 1, 1, 0, "data/blood_splatter.png", false);
				bloodSprite->m_pos = pPlayer->m_pos.getLerp(gSys->pGame->gameTime - 0.1) + glm::vec2(cos(angle), sin(angle)) * 0.4f;
				bloodSprite->m_rotPointOffset = glm::vec2(0, 0.1f);
				bloodSprite->m_rotation = angle;
			}
		}
		break;
		case PacketTypes::REQUEST_TIME:
		{
			double serverTime = 0;
			memcpy(&serverTime, event.packet->data + 1, sizeof(double));

			//Add half of round-trip
			//serverTime += (glfwGetTime() - gSys->lastTimeRequest) / 2;

			gSys->pGame->serverTimeDelta = serverTime - glfwGetTime();
		}
		break;
		default:
			fprintf(stderr, "Unknown packet type: %u", *(event.packet->data));
			break;
		}
	}
}
Ejemplo n.º 28
0
bool BMPImageReader::readInfoHeader()
{
    // Pre-initialize some fields that not all headers set.
    m_infoHeader.biCompression = RGB;
    m_infoHeader.biClrUsed = 0;

    if (m_isOS21x) {
        m_infoHeader.biWidth = readUint16(4);
        m_infoHeader.biHeight = readUint16(6);
        ASSERT(m_andMaskState == None);  // ICO is a Windows format, not OS/2!
        m_infoHeader.biBitCount = readUint16(10);
        return true;
    }

    m_infoHeader.biWidth = readUint32(4);
    m_infoHeader.biHeight = readUint32(8);
    if (m_andMaskState != None)
        m_infoHeader.biHeight /= 2;
    m_infoHeader.biBitCount = readUint16(14);

    // Read compression type, if present.
    if (m_infoHeader.biSize >= 20) {
        uint32_t biCompression = readUint32(16);

        // Detect OS/2 2.x-specific compression types.
        if ((biCompression == 3) && (m_infoHeader.biBitCount == 1)) {
            m_infoHeader.biCompression = HUFFMAN1D;
            m_isOS22x = true;
        } else if ((biCompression == 4) && (m_infoHeader.biBitCount == 24)) {
            m_infoHeader.biCompression = RLE24;
            m_isOS22x = true;
        } else if (biCompression > 5)
            return setFailed();  // Some type we don't understand.
        else
            m_infoHeader.biCompression = static_cast<CompressionType>(biCompression);
    }

    // Read colors used, if present.
    if (m_infoHeader.biSize >= 36)
        m_infoHeader.biClrUsed = readUint32(32);

    // Windows V4+ can safely read the four bitmasks from 40-56 bytes in, so do
    // that here.  If the bit depth is less than 16, these values will be
    // ignored by the image data decoders.  If the bit depth is at least 16 but
    // the compression format isn't BITFIELDS, these values will be ignored and
    // overwritten* in processBitmasks().
    // NOTE: We allow alpha here.  Microsoft doesn't really document this well,
    // but some BMPs appear to use it.
    //
    // For non-Windows V4+, m_bitMasks[] et. al will be initialized later
    // during processBitmasks().
    //
    // *Except the alpha channel.  Bizarrely, some RGB bitmaps expect decoders
    // to pay attention to the alpha mask here, so there's a special case in
    // processBitmasks() that doesn't always overwrite that value.
    if (isWindowsV4Plus()) {
        m_bitMasks[0] = readUint32(40);
        m_bitMasks[1] = readUint32(44);
        m_bitMasks[2] = readUint32(48);
        m_bitMasks[3] = readUint32(52);
    }

    // Detect top-down BMPs.
    if (m_infoHeader.biHeight < 0) {
        m_isTopDown = true;
        m_infoHeader.biHeight = -m_infoHeader.biHeight;
    }

    return true;
}
Ejemplo n.º 29
0
bool BMPImageReader::processBitmasks()
{
    // Create m_bitMasks[] values.
    if (m_infoHeader.biCompression != BITFIELDS) {
        // The format doesn't actually use bitmasks.  To simplify the decode
        // logic later, create bitmasks for the RGB data.  For Windows V4+,
        // this overwrites the masks we read from the header, which are
        // supposed to be ignored in non-BITFIELDS cases.
        // 16 bits:    MSB <-                     xRRRRRGG GGGBBBBB -> LSB
        // 24/32 bits: MSB <- [AAAAAAAA] RRRRRRRR GGGGGGGG BBBBBBBB -> LSB
        const int numBits = (m_infoHeader.biBitCount == 16) ? 5 : 8;
        for (int i = 0; i <= 2; ++i)
            m_bitMasks[i] = ((static_cast<uint32_t>(1) << (numBits * (3 - i))) - 1) ^ ((static_cast<uint32_t>(1) << (numBits * (2 - i))) - 1);

        // For Windows V4+ 32-bit RGB, don't overwrite the alpha mask from the
        // header (see note in readInfoHeader()).
        if (m_infoHeader.biBitCount < 32)
            m_bitMasks[3] = 0;
        else if (!isWindowsV4Plus())
            m_bitMasks[3] = static_cast<uint32_t>(0xff000000);
    } else if (!isWindowsV4Plus()) {
        // For Windows V4+ BITFIELDS mode bitmaps, this was already done when
        // we read the info header.

        // Fail if we don't have enough file space for the bitmasks.
        static const size_t SIZEOF_BITMASKS = 12;
        if (((m_headerOffset + m_infoHeader.biSize + SIZEOF_BITMASKS) < (m_headerOffset + m_infoHeader.biSize)) || (m_imgDataOffset && (m_imgDataOffset < (m_headerOffset + m_infoHeader.biSize + SIZEOF_BITMASKS))))
            return setFailed();

        // Read bitmasks.
        if ((m_data->size() - m_decodedOffset) < SIZEOF_BITMASKS)
            return false;
        m_bitMasks[0] = readUint32(0);
        m_bitMasks[1] = readUint32(4);
        m_bitMasks[2] = readUint32(8);
        // No alpha in anything other than Windows V4+.
        m_bitMasks[3] = 0;

        m_decodedOffset += SIZEOF_BITMASKS;
    }

    // We've now decoded all the non-image data we care about.  Skip anything
    // else before the actual raster data.
    if (m_imgDataOffset)
        m_decodedOffset = m_imgDataOffset;
    m_needToProcessBitmasks = false;

    // Check masks and set shift values.
    for (int i = 0; i < 4; ++i) {
        // Trim the mask to the allowed bit depth.  Some Windows V4+ BMPs
        // specify a bogus alpha channel in bits that don't exist in the pixel
        // data (for example, bits 25-31 in a 24-bit RGB format).
        if (m_infoHeader.biBitCount < 32)
            m_bitMasks[i] &= ((static_cast<uint32_t>(1) << m_infoHeader.biBitCount) - 1);

        // For empty masks (common on the alpha channel, especially after the
        // trimming above), quickly clear the shifts and continue, to avoid an
        // infinite loop in the counting code below.
        uint32_t tempMask = m_bitMasks[i];
        if (!tempMask) {
            m_bitShiftsRight[i] = m_bitShiftsLeft[i] = 0;
            continue;
        }

        // Make sure bitmask does not overlap any other bitmasks.
        for (int j = 0; j < i; ++j) {
            if (tempMask & m_bitMasks[j])
                return setFailed();
        }

        // Count offset into pixel data.
        for (m_bitShiftsRight[i] = 0; !(tempMask & 1); tempMask >>= 1)
            ++m_bitShiftsRight[i];

        // Count size of mask.
        for (m_bitShiftsLeft[i] = 8; tempMask & 1; tempMask >>= 1)
            --m_bitShiftsLeft[i];

        // Make sure bitmask is contiguous.
        if (tempMask)
            return setFailed();

        // Since RGBABuffer tops out at 8 bits per channel, adjust the shift
        // amounts to use the most significant 8 bits of the channel.
        if (m_bitShiftsLeft[i] < 0) {
            m_bitShiftsRight[i] -= m_bitShiftsLeft[i];
            m_bitShiftsLeft[i] = 0;
        }
    }

    return true;
}
Ejemplo n.º 30
0
int processChannelControlMessage( INOUT SESSION_INFO *sessionInfoPtr,
								  INOUT STREAM *stream )
	{
	SSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;
	const long prevChannelNo = \
				getCurrentChannelNo( sessionInfoPtr, CHANNEL_READ );
	long channelNo;
	int status;

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
	assert( isWritePtr( stream, sizeof( STREAM ) ) );

	/* See what we've got.  SSH has a whole pile of no-op equivalents that 
	   we have to handle as well as the obvious no-ops.  We can also get 
	   global and channel requests for assorted reasons and a constant 
	   stream of window adjusts to implement the SSH performance handbrake */
	switch( sshInfo->packetType )
		{
		case SSH2_MSG_GLOBAL_REQUEST:
			status = processChannelRequest( sessionInfoPtr, stream,
											CRYPT_UNUSED );
			if( cryptStatusError( status ) && status != OK_SPECIAL )
				return( status );
			return( OK_SPECIAL );

		case SSH2_MSG_CHANNEL_OPEN:
			/* Process the channel-open request.  In theory we could 
			   immediately reject any attempts by the server to open a
			   channel to the client at this point, but unfortunately we
			   have to process a considerable portion of the channel-open
			   request in order to use the information in it to send a
			   request-denied response back to the server */
			status = processChannelOpen( sessionInfoPtr, stream );
			if( cryptStatusError( status ) )
				return( status );

			/* Tell the caller that they have to process the new channel
			   information before they can continue */
			return( CRYPT_ENVELOPE_RESOURCE );

		case SSH2_MSG_IGNORE:
		case SSH2_MSG_DEBUG:
			/* Nothing to see here, move along, move along:

				byte	SSH2_MSG_IGNORE
				string	data

				byte	SSH2_MSG_DEBUG
				boolean	always_display
				string	message
				string	language_tag */
			return( OK_SPECIAL );

		case SSH2_MSG_DISCONNECT:
			/* This only really seems to be used during the handshake phase,
			   once a channel is open it (and the session as a whole) is
			   disconnected with a channel EOF/close, but we handle it here
			   anyway just in case */
			return( getDisconnectInfo( sessionInfoPtr, stream ) );

#ifdef KPYM_HACK
		case SSH2_MSG_KEXDH_INIT/*SSH2_MSG_KEXDH_GEX_REQUEST_OLD*/:
		case SSH2_MSG_KEXDH_GEX_INIT:
		case SSH2_MSG_KEXDH_GEX_REQUEST_NEW:
		case SSH2_MSG_KEXINIT:
		case SSH2_MSG_NEWKEYS:
			{
				int status = ke_DH_ROUTER(sessionInfoPtr, stream, sshInfo->packetType);
				if( status == CRYPT_OK )return( OK_SPECIAL );
				else return status;
			}
#else
		case SSH2_MSG_KEXINIT:
#endif
			/* The SSH spec is extremely vague about the sequencing of
			   operations during a rehandshake.  Unlike SSL there's no real 
			   indication of what happens to the connection-layer transfers 
			   while a transport-layer rehandshake is in progress.  Also 
			   unlike SSL we can't refuse a rehandshake by ignoring the 
			   request, so once we've fallen we can't get up any more.  This 
			   is most obvious with ssh.com's server, which starting with 
			   version 2.3.0 would do a rehandshake every hour (for a basic 
			   encrypted telnet session, while a high-volume IPsec link can 
			   run for hours before it feels the need to do this).  To make 
			   things even messier, neither side can block for too long 
			   waiting for the rehandshake to complete before sending new 
			   data because the lack of WINDOW_ADJUSTs (in an implementation 
			   that sends these with almost every packet, as most do) will 
			   screw up flow control and lead to deadlock.  This problem got 
			   so bad that as of 2.4.0 the ssh.com implementation would 
			   detect OpenSSH (the other main implementation at the time) 
			   and disable the rehandshake when it was talking to it, but it 
			   may not do this for other implementations.

			   To avoid falling into this hole, or at least to fail
			   obviously when the two sides can't agree on how to handle the
			   layering mismatch problem, we report a rehandshake request as
			   an error.  Trying to handle it properly results in hard-to-
			   diagnose errors (it depends on what the layers are doing at
			   the time of the problem), typically some bad-packet error
			   when the other side tries to interpret a connection-layer
			   packet as part of the rehandshake, or when the two sides
			   disagree on when to switch keys and one of the two decrypts 
			   with the wrong keys and gets a garbled packet type */
			retExt( CRYPT_ERROR_BADDATA,
					( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
					  "Unexpected KEXINIT request received" ) );

		case SSH2_MSG_CHANNEL_DATA:
		case SSH2_MSG_CHANNEL_EXTENDED_DATA:
		case SSH2_MSG_CHANNEL_REQUEST:
		case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
		case SSH2_MSG_CHANNEL_EOF:
		case SSH2_MSG_CHANNEL_CLOSE:
			/* All channel-specific messages end up here */
			channelNo = readUint32( stream );
			if( cryptStatusError( channelNo ) )
				{
				/* We can't send an error response to a channel request at
				   this point both because we haven't got to the response-
				   required flag yet and because SSH doesn't provide a
				   mechanism for returning an error response without an
				   accompanying channel number.  The best that we can do is
				   to quietly ignore the packet */
				retExt( CRYPT_ERROR_BADDATA,
						( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
						  "Invalid channel number in channel-specific packet "
						  "type %d", sshInfo->packetType ) );
				}
			if( channelNo != getCurrentChannelNo( sessionInfoPtr, \
												  CHANNEL_READ ) )
				{
				/* It's a request on something other than the current
				   channel, try and select the new channel */
				status = selectChannel( sessionInfoPtr, channelNo,
										CHANNEL_READ );
				if( cryptStatusError( status ) )
					{
					/* As before for error handling */
					retExt( CRYPT_ERROR_BADDATA,
							( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
							  "Invalid channel number %lX in "
							  "channel-specific packet type %d, current "
							  "channel is %lX", channelNo,
							  sshInfo->packetType, prevChannelNo ) );
					}
				}
			break;

		default:
			{
			BYTE buffer[ 16 + 8 ];
			int length;

			/* We got something unexpected, throw an exception in the debug
			   version and let the caller know the details */
			DEBUG_DIAG(( "Unexpected control packet %d", 
						 sshInfo->packetType ));
			assert( DEBUG_WARN );
			status = length = sread( stream, buffer, 8 );
			if( cryptStatusError( status ) || length < 8 )
				{
				/* There's not enough data present to dump the start of the
				   packet, provide a more generic response */
				retExt( CRYPT_ERROR_BADDATA,
						( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
						  "Unexpected control packet type %d received",
						  sshInfo->packetType ) );
				}
			retExt( CRYPT_ERROR_BADDATA,
					( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
					  "Unexpected control packet type %d received, "
					  "beginning %02X %02X %02X %02X %02X %02X %02X %02X",
					  sshInfo->packetType,
					  buffer[ 0 ], buffer[ 1 ], buffer[ 2 ], buffer[ 3 ],
					  buffer[ 4 ], buffer[ 5 ], buffer[ 6 ], buffer[ 7 ] ) );
			}
		}

	/* From here on we're processing a channel-specific message that applies
	   to the currently selected channel */
	switch( sshInfo->packetType )
		{
		case SSH2_MSG_CHANNEL_DATA:
		case SSH2_MSG_CHANNEL_EXTENDED_DATA:
			{
			int length;

			/* Get the payload length and make sure that it's
			   (approximately) valid, more exact checking has already been
			   done by the caller so we don't need to return extended error
			   information as this is just a backup check */
			status = length = readUint32( stream );
			if( cryptStatusError( status ) || \
				length < 0 || length > sessionInfoPtr->receiveBufSize )
				return( CRYPT_ERROR_BADDATA );

			/* These are messages that consume window space, adjust the data 
			   window and communicate changes to the other side if 
			   necessary */
			status = handleWindowAdjust( sessionInfoPtr, channelNo, length );
			if( cryptStatusError( status ) )
				return( status );

			/* If it's a standard data packet, we're done */
			if( sshInfo->packetType == SSH2_MSG_CHANNEL_DATA )
				return( CRYPT_OK );

			/* The extended data message is used for out-of-band data sent
			   over a channel, specifically output sent to stderr from a
			   shell command.  What to do with this is somewhat uncertain,
			   the only possible action that we could take apart from just
			   ignoring it is to convert it back to in-band data.  However,
			   something running a shell command may not expect to get
			   anything returned in this manner (see the comment for the
			   port-forwarding channel open in the client-side channel-open
			   code for more on this) so for now we just ignore it and 
			   assume that the user will rely on results sent as in-band
			   data.  This should be fairly safe since this message type
			   seems to be rarely (if ever) used, so apps will function
			   without it */
			return( OK_SPECIAL );
			}

		case SSH2_MSG_CHANNEL_REQUEST:
			status = processChannelRequest( sessionInfoPtr, stream,
											prevChannelNo );
			if( cryptStatusError( status ) && status != OK_SPECIAL )
				return( status );
			return( OK_SPECIAL );

		case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
			/* Another noop-equivalent (but a very performance-affecting
			   one) */
			return( OK_SPECIAL );

		case SSH2_MSG_CHANNEL_EOF:
			/* According to the SSH docs the EOF packet is mostly a courtesy
			   notification, however many implementations seem to use a
			   channel EOF in place of a close before sending a disconnect
			   message */
#ifdef KPYM_HACK
#else
			return( OK_SPECIAL );
#endif
		case SSH2_MSG_CHANNEL_CLOSE:
			/* The peer has closed their side of the channel, if our side
			   isn't already closed (in other words if this message isn't
			   a response to a close that we sent), close our side as well */
			if( getChannelStatusByChannelNo( sessionInfoPtr, 
											 channelNo ) == CHANNEL_BOTH )
				{
#ifdef KPYM_HACK
				status = sendChannelClose( sessionInfoPtr, channelNo,
										   CHANNEL_BOTH, TRUE );

				/* We've already closed our side of the channel, delete it */
				status = deleteChannel( sessionInfoPtr, channelNo,
										CHANNEL_BOTH, TRUE );
#else
				status = sendChannelClose( sessionInfoPtr, channelNo,
										   CHANNEL_BOTH, TRUE );
#endif
				}
			else
				{
				/* We've already closed our side of the channel, delete it */
				status = deleteChannel( sessionInfoPtr, channelNo,
										CHANNEL_BOTH, TRUE );
				}

			/* If this wasn't the last channel, we're done */
			if( status != OK_SPECIAL )
				return( OK_SPECIAL );

			/* We've closed the last channel, indicate that the overall
			   connection is now closed.  This behaviour isn't mentioned in
			   the spec but it seems to be the standard way of handling 
			   things, particularly for the most common case where
			   channel == session */
			sessionInfoPtr->flags |= SESSION_SENDCLOSED;
			retExt( CRYPT_ERROR_COMPLETE,
					( CRYPT_ERROR_COMPLETE, SESSION_ERRINFO, 
					  "Remote system closed last remaining SSH channel" ) );
		}

	retIntError();
	}