int lit_i_read_sections(lit_file * litfile ) { U8 *pNamelist; int status; int nbytes, num_sections, size, section, idx; status = lit_get_file(litfile, namelist_string, &pNamelist,&nbytes); if (status) return status; idx = 2; size = 2; if ((idx + size) > nbytes) goto bad; num_sections = READ_U16(pNamelist+idx); idx += 2; litfile->sections = malloc(num_sections * sizeof(section_type)); if (!litfile->sections) { lit_error(ERR_R|ERR_LIBC,"malloc(%d) failed!\n", num_sections*sizeof(section_type)); free(pNamelist); return E_LIT_OUT_OF_MEMORY; } memset(litfile->sections, 0, num_sections * sizeof(section_type)); litfile->num_sections = num_sections; for (section = 0; section < num_sections; section++) { int j; size = 2; if ((idx + size) > nbytes) goto bad; size = READ_U16(pNamelist + idx); idx += 2; if (size > MAX_SECTION_NAME) { lit_error(ERR_R, "litlib.c cannot handle a %d byte section name, fix MAX_SECTION_NAME (%d)\n", size, MAX_SECTION_NAME); return -1; } size = (size * 2) + 2; if ((idx + size) > nbytes) goto bad; for (j = 0; j < size; j+=2) { litfile->sections[section].name[j/2] = pNamelist[idx + j]; } litfile->sections[section].name[j/2] = '\0'; idx += size; } free(pNamelist); return 0; bad: lit_error(ERR_R, "Invalid or corrupt ::DataSpace/Namelist!\n" "\nTried to read %d bytes past length of (%ld)\n", size,nbytes); if (pNamelist) free(pNamelist); return -1; }
/*--[guid2string]-------------------------------------------------------------- | | Careful - uses a static string. Will be awkward if called the same | time in a statement. | Assumes GUID is in Little Endian Order | */ const char * guid2string(U8 * guid) { static char guid_buffer[7+8+4+4+4+12+1]; sprintf(guid_buffer, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", (U32)READ_U32(guid), (U16)READ_U16((guid+4)), (U16)READ_U16((guid+6)), (U8)*(guid+8), (U8)*(guid+9), /*-*/ (U8)*(guid+10), (U8)*(guid+11), (U8)*(guid+12), (U8)*(guid+13), (U8)*(guid+14), (U8)*(guid+15)); return guid_buffer; }
bool unabto_util_test(void) { uint8_t buf[] = {0x00,0x00,0x00,0x00,0x12, 0x34, 0x56, 0x78}; uint32_t* buf2 = (uint32_t*)buf; uint32_t testNr; uint16_t testu16; bool ret = true; READ_U32(testNr, buf+4); if (testNr != 305419896) { // 0x12345678 in host byte order NABTO_LOG_TRACE(("testNr: %i", testNr)); ret = false; } READ_U32(testNr, buf2+1); if (testNr != 0x12345678) { NABTO_LOG_TRACE(("testNr: %i", testNr)); ret = false; } READ_U16(testu16, buf+4); if (testu16 != 4660) { NABTO_LOG_TRACE(("testu16 read failed %i", testu16)); ret = false; } WRITE_U32(buf, 0x01020304); if (buf[0] != 0x01 || buf[1] != 0x02 || buf[2] != 0x03 || buf[3] != 0x04) { NABTO_LOG_TRACE(("WRITE u32 failed")); ret = false; } WRITE_U16(buf, 0x0506); if (buf[0] != 0x05 || buf[1] != 0x06) { NABTO_LOG_TRACE(("WRITE u16 failed")); ret = false; } return ret; }
static VC_CONTAINER_STATUS_T ps_read_system_header( VC_CONTAINER_T *ctx ) { uint8_t header[8]; uint32_t length; VC_CONTAINER_BITS_T bits; if(_READ_U32(ctx) != 0x1BB) return VC_CONTAINER_ERROR_CORRUPTED; LOG_FORMAT(ctx, "system_header"); ctx->priv->module->level++; length = READ_U16(ctx, "header_length"); if(length < 6) return VC_CONTAINER_ERROR_CORRUPTED; if(READ_BYTES(ctx, header, 6) != 6) return VC_CONTAINER_ERROR_EOS; BITS_INIT(ctx, &bits, header, 6); if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; BITS_SKIP(ctx, &bits, 22, "rate_bound"); if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; BITS_SKIP(ctx, &bits, 6, "audio_bound"); BITS_SKIP(ctx, &bits, 1, "fixed_flag"); BITS_SKIP(ctx, &bits, 1, "CSPS_flag"); BITS_SKIP(ctx, &bits, 1, "system_audio_lock_flag"); BITS_SKIP(ctx, &bits, 1, "system_video_lock_flag"); if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; BITS_SKIP(ctx, &bits, 5, "video_bound"); BITS_SKIP(ctx, &bits, 1, "packet_rate_restriction_flag"); BITS_SKIP(ctx, &bits, 7, "reserved_bits"); length -= 6; while(length >= 3 && (PEEK_U8(ctx) & 0x80)) { SKIP_U8(ctx, "stream_id"); SKIP_BYTES(ctx, 2); length -= 3; } SKIP_BYTES(ctx, length); ctx->priv->module->level--; return STREAM_STATUS(ctx); }
int CDVDOverlayCodecTX3G::Decode(BYTE* data, int size, double pts, double duration) { if (m_pOverlay) SAFE_RELEASE(m_pOverlay); m_pOverlay = new CDVDOverlayText(); m_pOverlay->iPTSStartTime = pts; m_pOverlay->iPTSStopTime = pts + duration; // do not move this. READ_XXXX macros modify pos. uint8_t *pos = data; uint8_t *end = pos + size; // Parse the packet as a TX3G TextSample. // Look for a single StyleBox ('styl') and // read all contained StyleRecords. // Ignore all other box types. // NOTE: Buffer overflows on read are not checked. // ALSO: READ_XXXX/SKIP_XXXX macros will modify pos. uint16_t textLength = READ_U16(); uint8_t *text = READ_ARRAY(textLength); int numStyleRecords = 0; uint8_t *bgnStyle = (uint8_t*)calloc(textLength, 1); uint8_t *endStyle = (uint8_t*)calloc(textLength, 1); int bgnColorIndex = 0, endColorIndex = 0; uint32_t textColorRGBA = m_textColor; while (pos < end) { // Read TextSampleModifierBox uint32_t size = READ_U32(); if (size == 0) size = pos - end; // extends to end of packet if (size == 1) { CLog::Log(LOGDEBUG, "CDVDOverlayCodecTX3G: TextSampleModifierBox has unsupported large size" ); break; } uint32_t type = READ_U32(); if (type == FOURCC("uuid")) { CLog::Log(LOGDEBUG, "CDVDOverlayCodecTX3G: TextSampleModifierBox has unsupported extended type" ); break; } if (type == FOURCC("styl")) { // Found a StyleBox. Parse the contained StyleRecords if ( numStyleRecords != 0 ) { CLog::Log(LOGDEBUG, "CDVDOverlayCodecTX3G: found additional StyleBoxes on subtitle; skipping" ); SKIP_ARRAY(size); continue; } numStyleRecords = READ_U16(); for (int i = 0; i < numStyleRecords; i++) { StyleRecord curRecord; curRecord.bgnChar = READ_U16(); curRecord.endChar = READ_U16(); curRecord.fontID = READ_U16(); curRecord.faceStyleFlags = READ_U8(); curRecord.fontSize = READ_U8(); curRecord.textColorRGBA = READ_U32(); bgnStyle[curRecord.bgnChar] |= curRecord.faceStyleFlags; endStyle[curRecord.endChar] |= curRecord.faceStyleFlags; bgnColorIndex = curRecord.bgnChar; endColorIndex = curRecord.endChar; textColorRGBA = curRecord.textColorRGBA; } } else { // Found some other kind of TextSampleModifierBox. Skip it. SKIP_ARRAY(size); } } // Copy text to out and add HTML markup for the style records int charIndex = 0; CStdStringA strUTF8; for (pos = text, end = text + textLength; pos < end; pos++) { if ((*pos & 0xC0) == 0x80) { // Is a non-first byte of a multi-byte UTF-8 character strUTF8.append((const char*)pos, 1); continue; // ...without incrementing 'charIndex' } uint8_t bgnStyles = bgnStyle[charIndex]; uint8_t endStyles = endStyle[charIndex]; // [B] or [/B] -> toggle bold on and off // [I] or [/I] -> toggle italics on and off // [COLOR ffab007f] or [/COLOR] -> toggle color on and off // [CAPS <option>] or [/CAPS] -> toggle capatilization on and off if (endStyles & BOLD) strUTF8.append("[/B]"); if (endStyles & ITALIC) strUTF8.append("[/I]"); // we do not support underline //if (endStyles & UNDERLINE) // strUTF8.append("[/U]"); if (endColorIndex == charIndex && textColorRGBA != m_textColor) strUTF8.append("[/COLOR]"); // invert the order from above so we bracket the text correctly. if (bgnColorIndex == charIndex && textColorRGBA != m_textColor) strUTF8.AppendFormat("[COLOR %8x]", textColorRGBA); // we do not support underline //if (bgnStyles & UNDERLINE) // strUTF8.append("[U]"); if (bgnStyles & ITALIC) strUTF8.append("[I]"); if (bgnStyles & BOLD) strUTF8.append("[B]"); // stuff the UTF8 char strUTF8.append((const char*)pos, 1); // this is a char index, not a byte index. charIndex++; } free(bgnStyle); free(endStyle); if (strUTF8.IsEmpty()) return OC_BUFFER; if (strUTF8[strUTF8.size()-1] == '\n') strUTF8.Delete(strUTF8.size()-1); // add a new text element to our container m_pOverlay->AddElement(new CDVDOverlayText::CElementText(strUTF8.c_str())); return OC_OVERLAY; }
int CDVDOverlayCodecTX3G::Decode(DemuxPacket *pPacket) { if (m_pOverlay) SAFE_RELEASE(m_pOverlay); m_pOverlay = new CDVDOverlayText(); CDVDOverlayCodec::GetAbsoluteTimes(m_pOverlay->iPTSStartTime, m_pOverlay->iPTSStopTime, pPacket, m_pOverlay->replace); // do not move this. READ_XXXX macros modify pos. uint8_t *pos = pPacket->pData; uint8_t *end = pPacket->pData + pPacket->iSize; // Parse the packet as a TX3G TextSample. // Look for a single StyleBox ('styl') and // read all contained StyleRecords. // Ignore all other box types. // NOTE: Buffer overflows on read are not checked. // ALSO: READ_XXXX/SKIP_XXXX macros will modify pos. LEN_CHECK(2); uint16_t textLength = READ_U16(); LEN_CHECK(textLength); uint8_t *text = READ_ARRAY(textLength); int numStyleRecords = 0; // reserve one more style slot for broken encoders XUTILS::auto_buffer bgnStyle(textLength+1); XUTILS::auto_buffer endStyle(textLength+1); memset(bgnStyle.get(), 0, textLength+1); memset(endStyle.get(), 0, textLength+1); int bgnColorIndex = 0, endColorIndex = 0; uint32_t textColorRGBA = m_textColor; while (pos < end) { // Read TextSampleModifierBox LEN_CHECK(4); uint32_t size = READ_U32(); if (size == 0) size = pos - end; // extends to end of packet if (size == 1) { CLog::Log(LOGDEBUG, "CDVDOverlayCodecTX3G: TextSampleModifierBox has unsupported large size" ); break; } LEN_CHECK(4); uint32_t type = READ_U32(); if (type == FOURCC("uuid")) { CLog::Log(LOGDEBUG, "CDVDOverlayCodecTX3G: TextSampleModifierBox has unsupported extended type" ); break; } if (type == FOURCC("styl")) { // Found a StyleBox. Parse the contained StyleRecords if ( numStyleRecords != 0 ) { CLog::Log(LOGDEBUG, "CDVDOverlayCodecTX3G: found additional StyleBoxes on subtitle; skipping" ); LEN_CHECK(size); SKIP_ARRAY(size); continue; } LEN_CHECK(2); numStyleRecords = READ_U16(); for (int i = 0; i < numStyleRecords; i++) { StyleRecord curRecord; LEN_CHECK(12); curRecord.bgnChar = READ_U16(); curRecord.endChar = READ_U16(); curRecord.fontID = READ_U16(); curRecord.faceStyleFlags = READ_U8(); curRecord.fontSize = READ_U8(); curRecord.textColorRGBA = READ_U32(); // clamp bgnChar/bgnChar to textLength, // we alloc enough space above and this // fixes borken encoders that do not handle // endChar correctly. if (curRecord.bgnChar > textLength) curRecord.bgnChar = textLength; if (curRecord.endChar > textLength) curRecord.endChar = textLength; bgnStyle.get()[curRecord.bgnChar] |= curRecord.faceStyleFlags; endStyle.get()[curRecord.endChar] |= curRecord.faceStyleFlags; bgnColorIndex = curRecord.bgnChar; endColorIndex = curRecord.endChar; textColorRGBA = curRecord.textColorRGBA; } } else { // Found some other kind of TextSampleModifierBox. Skip it. LEN_CHECK(size); SKIP_ARRAY(size); } } // Copy text to out and add HTML markup for the style records int charIndex = 0; std::string strUTF8; // index over textLength chars to include broken encoders, // so we pickup closing styles on broken encoders for (pos = text, end = text + textLength; pos <= end; pos++) { if ((*pos & 0xC0) == 0x80) { // Is a non-first byte of a multi-byte UTF-8 character strUTF8.append((const char*)pos, 1); continue; // ...without incrementing 'charIndex' } uint8_t bgnStyles = bgnStyle.get()[charIndex]; uint8_t endStyles = endStyle.get()[charIndex]; // [B] or [/B] -> toggle bold on and off // [I] or [/I] -> toggle italics on and off // [COLOR ffab007f] or [/COLOR] -> toggle color on and off // [CAPS <option>] or [/CAPS] -> toggle capatilization on and off if (endStyles & BOLD) strUTF8.append("[/B]"); if (endStyles & ITALIC) strUTF8.append("[/I]"); // we do not support underline //if (endStyles & UNDERLINE) // strUTF8.append("[/U]"); if (endColorIndex == charIndex && textColorRGBA != m_textColor) strUTF8.append("[/COLOR]"); // invert the order from above so we bracket the text correctly. if (bgnColorIndex == charIndex && textColorRGBA != m_textColor) strUTF8 += StringUtils::Format("[COLOR %8x]", textColorRGBA); // we do not support underline //if (bgnStyles & UNDERLINE) // strUTF8.append("[U]"); if (bgnStyles & ITALIC) strUTF8.append("[I]"); if (bgnStyles & BOLD) strUTF8.append("[B]"); // stuff the UTF8 char strUTF8.append((const char*)pos, 1); // this is a char index, not a byte index. charIndex++; } if (strUTF8.empty()) return OC_BUFFER; if (strUTF8[strUTF8.size()-1] == '\n') strUTF8.erase(strUTF8.size()-1); // add a new text element to our container m_pOverlay->AddElement(new CDVDOverlayText::CElementText(strUTF8.c_str())); return OC_OVERLAY; }
void unabto_tcp_fallback_read_packet(nabto_connect* con) { unabto_tcp_fallback_connection* fbConn = &fbConns[nabto_connection_index(con)]; while(true) { if (fbConn->recvBufferLength < 16) { int status = recv(fbConn->socket, fbConn->recvBuffer + fbConn->recvBufferLength, 16-fbConn->recvBufferLength, 0); int err = errno; if (status < 0) { if ((err == EAGAIN) || err == EWOULDBLOCK) { return; } else { NABTO_LOG_ERROR((PRI_tcp_fb "unabto_tcp_fallback_read_single_packet failed", TCP_FB_ARGS(con))); unabto_tcp_fallback_close(con); return; } } else if (status == 0) { NABTO_LOG_INFO((PRI_tcp_fb "TCP fallback connection closed by peer", TCP_FB_ARGS(con))); unabto_tcp_fallback_close(con); return; } else { fbConn->recvBufferLength+=status; } } if (fbConn->recvBufferLength >= 16) { uint16_t packetLength; int status; int err; READ_U16(packetLength, fbConn->recvBuffer+14); status = recv(fbConn->socket, fbConn->recvBuffer + fbConn->recvBufferLength, packetLength - fbConn->recvBufferLength, 0); err = errno; if (status < 0) { if ((err == EAGAIN) || err == EWOULDBLOCK) { return; } else { NABTO_LOG_ERROR((PRI_tcp_fb "Tcp read failed", TCP_FB_ARGS(con))); unabto_tcp_fallback_close(con); return; } } else if (status == 0) { NABTO_LOG_INFO((PRI_tcp_fb "TCP fallback connection closed by peer", TCP_FB_ARGS(con))); unabto_tcp_fallback_close(con); return; } else { fbConn->recvBufferLength += status; } if (fbConn->recvBufferLength == packetLength) { message_event event; event.type = MT_TCP_FALLBACK; memcpy(nabtoCommunicationBuffer, fbConn->recvBuffer, fbConn->recvBufferLength); NABTO_LOG_TRACE((PRI_tcp_fb "Received fallback packet length %" PRIsize, TCP_FB_ARGS(con), fbConn->recvBufferLength)); nabto_message_event(&event, fbConn->recvBufferLength); NABTO_LOG_TRACE((PRI_tcp_fb "fallback packet done\n==================================================", TCP_FB_ARGS(con))); fbConn->recvBufferLength = 0; } } } }
void unabto_sha256_final(sha256_ctx* context,sha2_byte digest[]) { sha2_word32 *d = (sha2_word32*)digest; unsigned int usedspace; /* Sanity check: */ // assert(context != (sha256_ctx*)0); /* If no digest buffer is passed, we don't bother doing this: */ if (digest != (sha2_byte*)0) { usedspace = context->byteCount % SHA256_BLOCK_LENGTH; if (usedspace > 0) { /* Begin padding with a 1 bit: */ context->buffer[usedspace++] = 0x80; if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) { /* Set-up for the last transform: */ MEMSET_BZERO(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace); } else { if (usedspace < SHA256_BLOCK_LENGTH) { MEMSET_BZERO(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace); } /* Do second-to-last transform: */ SHA256_Transform(context, (sha2_word32*)context->buffer); /* And set-up for the last transform: */ MEMSET_BZERO(context->buffer, SHA256_BLOCK_LENGTH); } } else { /* Set-up for the last transform: */ MEMSET_BZERO(context->buffer, SHA256_BLOCK_LENGTH); /* Begin padding with a 1 bit: */ *context->buffer = 0x80; } /* Set the bit count: */ /* Convert FROM host byte order */ { uint16_t tmp16; uint16_t tmp16_ = context->byteCount; tmp16_ <<= 3; READ_U16(tmp16, &tmp16_); memset(&context->buffer[SHA256_BLOCK_LENGTH - 8], 0, 6); *(uint16_t*)&context->buffer[SHA256_BLOCK_LENGTH - 2] = tmp16; } //print_sha256_ctx(context); /* Final transform: */ SHA256_Transform(context, (sha2_word32*)context->buffer); //print_sha256_ctx(context); { /* Convert TO host byte order */ uint8_t j; for (j = 0; j < 8; j++) { WRITE_U32(d, context->state[j]); d++; } } } /* Clean up state data: */ MEMSET_BZERO(context, sizeof(sha256_ctx)); usedspace = 0; }
bool rendezvous_event(message_event* event, nabto_packet_header* hdr) { uint8_t* end = nabtoCommunicationBuffer + hdr->len; uint16_t res = hdr->hlen; uint8_t* ptr; uint8_t type; nabto_endpoint epUD; nabto_connect* con = 0; nabto_endpoint src; uint32_t interval = 5000; src = event->udpMessage.peer; NABTO_LOG_TRACE((PRInsi " Received from " PRIep " seq=%" PRIu16, MAKE_NSI_PRINTABLE(0, hdr->nsi_sp, 0), MAKE_EP_PRINTABLE(src), hdr->seq)); ptr = nabtoCommunicationBuffer + res; res = nabto_rd_payload(ptr, end, &type); ptr += SIZE_PAYLOAD_HEADER; if (res != 6 || type != NP_PAYLOAD_TYPE_EP) { NABTO_LOG_TRACE(("Can't read first EP")); return false; } READ_U32(epUD.addr, ptr); ptr += 4; READ_U16(epUD.port, ptr); ptr += 2; res = nabto_rd_payload(ptr, end, &type); ptr += SIZE_PAYLOAD_HEADER; if (res == 6 && type == NP_PAYLOAD_TYPE_EP) { // The second EP is not neccessary since we read the destination ep from the udp packet. ptr += 6; res = nabto_rd_payload(ptr, end, &type); ptr += SIZE_PAYLOAD_HEADER; if (res == 4 && type == NP_PAYLOAD_TYPE_NONCE) { READ_U32(interval, ptr); NABTO_LOG_TRACE((PRInsi " Read interval from packet: %" PRIu32, MAKE_NSI_PRINTABLE(0, hdr->nsi_sp, 0), interval)); if (interval == 0) { NABTO_LOG_WARN(("Interval was 0, setting to 5000")); interval = 5000; } } } con = nabto_find_connection(hdr->nsi_sp); if (!con) { NABTO_LOG_ERROR(("Connection was not found, nsi: %i", hdr->nsi_sp)); } else { if (hdr->seq == 0) { send_rendezvous_socket(event->udpMessage.socket, con, 1, &src, &epUD); } else if (hdr->seq == 1) { send_rendezvous_socket(event->udpMessage.socket, con, 2, &src, &epUD); if (!conclude_connection(con, &src, interval)) { return false; } } else if (hdr->seq == 2) { if (!conclude_connection(con, &src, interval)) { return false; } } else { NABTO_LOG_ERROR(("Invalid Sequence Number")); } } return false; }
nabto_connect* nabto_init_connection(nabto_packet_header* hdr, uint32_t* nsi, uint32_t* ec, bool isLocal) { uint8_t type; uint8_t flags; /* NP_PAYLOAD_IPX_FLAG_* */ nabto_connect* con; const uint8_t* end = nabtoCommunicationBuffer + hdr->len; uint8_t* ptr = nabtoCommunicationBuffer + hdr->hlen; uint16_t res; uint16_t ipxPayloadLength; ipxPayloadLength = nabto_rd_payload(ptr, end, &type); ptr += SIZE_PAYLOAD_HEADER; *nsi = 0; *ec = 0; if ((ipxPayloadLength != IPX_PAYLOAD_LENGTH_WITHOUT_NSI) && (ipxPayloadLength != IPX_PAYLOAD_LENGTH_WITH_NSI) && (ipxPayloadLength != IPX_PAYLOAD_LENGTH_FULL_NSI)) { NABTO_LOG_TRACE(("Illegal payload size in U_CONNECT request from GSP: %" PRIu16 " %" PRIu8, ipxPayloadLength, type)); return 0; } if (type != NP_PAYLOAD_TYPE_IPX) { NABTO_LOG_TRACE(("Illegal payload type in U_CONNECT request from GSP: %" PRIu16 " %" PRIu8, ipxPayloadLength, type)); return 0; } if (ipxPayloadLength == IPX_PAYLOAD_LENGTH_WITH_NSI || ipxPayloadLength == IPX_PAYLOAD_LENGTH_FULL_NSI) { READ_U32(*nsi, ptr + 13); NABTO_LOG_TRACE(("IPX payload with NSI (SPNSI=%" PRIu32 ")", *nsi)); } else { *nsi = fresh_nsi(); NABTO_LOG_TRACE(("IPX payload without NSI (fresh NSI=%" PRIu32 ")", *nsi)); } if (*nsi == 0) { NABTO_LOG_ERROR(("Trying to create connection with spnsi == 0")); return 0; } if (nabto_find_connection(*nsi)) { NABTO_LOG_DEBUG((PRInsi " A connection already exists this is probably a retransmission", MAKE_NSI_PRINTABLE(0, *nsi, 0))); *ec = NOTIFY_CONNECT_OK; return 0; } con = nabto_init_connection_real(*nsi); if (con == 0) { if (nabto_find_connection(*nsi)) { NABTO_LOG_DEBUG((PRInsi " U_CONNECT: A connection resource is already pending new connection", MAKE_NSI_PRINTABLE(0, *nsi, 0))); } else { NABTO_LOG_INFO((PRInsi " U_CONNECT: No connection resources free for new connection", MAKE_NSI_PRINTABLE(0, *nsi, 0))); #if NABTO_ENABLE_DEVICE_BUSY_AS_FATAL NABTO_LOG_FATAL((PRInsi " U_CONNECT: No free connections configured to be considered fatal", MAKE_NSI_PRINTABLE(0, *nsi, 0))); #endif } *ec = NOTIFY_ERROR_BUSY_MICRO; return 0; } NABTO_LOG_DEBUG((PRInsi " U_CONNECT: Connecting using record %i", MAKE_NSI_PRINTABLE(0, *nsi, 0), nabto_connection_index(con))); READ_U32(con->cp.privateEndpoint.addr, ptr + 0); READ_U16(con->cp.privateEndpoint.port, ptr + 4); READ_U32(con->cp.globalEndpoint.addr, ptr + 6); READ_U16(con->cp.globalEndpoint.port, ptr + 10); READ_U8(flags, ptr + 12); /* the final word (4 bytes) has been read already (nsi) */ con->noRendezvous = (flags & NP_PAYLOAD_IPX_FLAG_NO_RENDEZVOUS) ? 1 : 0; con->cpEqual = EP_EQUAL(con->cp.privateEndpoint, con->cp.globalEndpoint); con->cpAsync = (flags & NP_PAYLOAD_IPX_FLAG_CP_ASYNC) ? 1 : 0; con->clientNatType = (flags & NP_PAYLOAD_IPX_NAT_MASK); con->isLocal = isLocal; NABTO_LOG_INFO((PRInsi " U_CONNECT: cp.private: " PRIep " cp.global: " PRIep ", noRdv=%" PRIu8 ", cpeq=%" PRIu8 ", asy=%" PRIu8 ", NATType: %" PRIu8 , MAKE_NSI_PRINTABLE(0, *nsi, 0), MAKE_EP_PRINTABLE(con->cp.privateEndpoint), MAKE_EP_PRINTABLE(con->cp.globalEndpoint), con->noRendezvous, con->cpEqual, con->cpAsync, con->clientNatType)); #if NABTO_ENABLE_TCP_FALLBACK if (ipxPayloadLength == IPX_PAYLOAD_LENGTH_FULL_NSI) { memcpy(con->consi, ptr+17, 8); con->nsico = con->consi; READ_U32(con->cpnsi, ptr+25); } #endif ptr += ipxPayloadLength; //IPX_PAYLOAD_LENGTH_WITHOUT_NSI or IPX_PAYLOAD_LENGTH_WITH_NSI con->clientId[0] = 0; res = nabto_rd_payload(ptr, end, &type); if (type == NP_PAYLOAD_TYPE_CP_ID) { uint8_t idType; ptr += SIZE_PAYLOAD_HEADER; if (res > 0) { READ_U8(idType, ptr); ++ptr; --res; if (idType == 1) { // 1 == EMAIL size_t sz = res; if (sz >= sizeof(con->clientId)) { if (sizeof(con->clientId) > 1) { NABTO_LOG_WARN(("Client ID truncated")); } sz = sizeof(con->clientId) - 1; } if (sz) { memcpy(con->clientId, (const void*) ptr, sz); } con->clientId[sz] = 0; } } NABTO_LOG_TRACE(("Connection opened from '%s' (to %s)", con->clientId, nmc.nabtoMainSetup.id)); ptr += res; } #if NABTO_ENABLE_CONNECTION_ESTABLISHMENT_ACL_CHECK if (!allow_client_access(con)) { *ec = NOTIFY_ERROR_CP_ACCESS; goto init_error; } #endif #if NABTO_ENABLE_TCP_FALLBACK { uint8_t* gatewayPtr = ptr; res = nabto_rd_payload(ptr, end, &type); if (type == NP_PAYLOAD_TYPE_GW && ipxPayloadLength == IPX_PAYLOAD_LENGTH_FULL_NSI) { uint8_t* gatewayEndPtr; size_t idLength; NABTO_LOG_TRACE(("The connect contains a gateway payload.")); ptr += res + SIZE_PAYLOAD_HEADER; gatewayPtr += SIZE_PAYLOAD_HEADER; gatewayEndPtr = ptr; READ_U32(con->fallbackHost.addr, gatewayPtr); gatewayPtr+=4; READ_U16(con->fallbackHost.port, gatewayPtr); gatewayPtr+=2; // skip the nsi gatewayPtr+=4; idLength = gatewayEndPtr-gatewayPtr; if (idLength != 20) { NABTO_LOG_FATAL(("The id length should be 20 bytes. bytes=%" PRIsize, idLength)); // todo } memcpy(con->gatewayId, gatewayPtr, 20); con->hasTcpFallbackCapabilities = true; } } #endif #if NABTO_ENABLE_UCRYPTO if (nmc.context.nonceSize == NONCE_SIZE) { uint8_t* decryptedDataStart; uint16_t decryptedDataLength; if (!unabto_connection_verify_and_decrypt_connect_packet(hdr, &decryptedDataStart, &decryptedDataLength)) { NABTO_LOG_TRACE(("Failed to read crypto payload in U_CONNECT")); } else { unabto_crypto_reinit_d(&con->cryptoctx, nmc.nabtoMainSetup.cryptoSuite, decryptedDataStart, decryptedDataLength); } } else #endif { NABTO_LOG_TRACE(("######## U_CONNECT without crypto payload")); unabto_crypto_reinit_d(&con->cryptoctx, CRYPT_W_NULL_DATA, 0, 0); } con->timeOut = CONNECTION_TIMEOUT; nabtoSetFutureStamp(&con->stamp, 20000); /* give much extra time during initialisation */ if (!verify_connection_encryption(con)) { goto init_crypto_error; } if (con->cpEqual) { NABTO_LOG_DEBUG((PRInsi " U_CONNECT: addr:" PRIep " rendezvous:%" PRIu8, MAKE_NSI_PRINTABLE(0, *nsi, 0), MAKE_EP_PRINTABLE(con->cp.privateEndpoint), !con->noRendezvous)); } else { NABTO_LOG_DEBUG((PRInsi " U_CONNECT: private:" PRIep ", global:" PRIep " rendezvous:%" PRIu8, MAKE_NSI_PRINTABLE(0, *nsi, 0), MAKE_EP_PRINTABLE(con->cp.privateEndpoint), MAKE_EP_PRINTABLE(con->cp.globalEndpoint), !con->noRendezvous)); } NABTO_LOG_INFO(("Connection opened from '%s' (to %s). Encryption code %i", con->clientId, nmc.nabtoMainSetup.id, con->cryptoctx.code)); return con; init_crypto_error: *ec = NOTIFY_ERROR_ENCR_MISMATCH; #if NABTO_ENABLE_CONNECTION_ESTABLISHMENT_ACL_CHECK init_error: nabto_release_connection(con); #endif return 0; }
void nabto_stream_event(nabto_connect* con, nabto_packet_header* hdr, uint8_t* info, //WINDOW payload with payload header uint8_t* start, int dlen, uint8_t* sackStart, uint16_t sackLength) { struct nabto_win_info win; struct nabto_stream_s* stream; struct nabto_stream_sack_data sackData; uint16_t len; // We must have a WINDOW payload to continue. if (!info) { NABTO_LOG_ERROR(("Stream %i, Packet has no WINDOW payload!", hdr->tag)); return; } READ_U16(len, info + 2); if (!nabto_stream_read_window(info + SIZE_PAYLOAD_HEADER, len - SIZE_PAYLOAD_HEADER, &win)) { NABTO_LOG_DEBUG(("ReadWin failure")); return; } { text msg; switch (win.type) { case NP_PAYLOAD_WINDOW_FLAG_SYN : msg = "SYN"; break; case NP_PAYLOAD_WINDOW_FLAG_SYN | NP_PAYLOAD_WINDOW_FLAG_ACK: msg = "SYN|ACK"; break; case NP_PAYLOAD_WINDOW_FLAG_FIN | NP_PAYLOAD_WINDOW_FLAG_ACK: msg = "FIN|ACK"; break; case NP_PAYLOAD_WINDOW_FLAG_RST : msg = "RST"; break; case NP_PAYLOAD_WINDOW_FLAG_ACK : msg = "DATA"; break; default : msg = "?"; NABTO_LOG_TRACE(("Type?: %" PRIu8, win.type)); break; } NABTO_NOT_USED(msg); NABTO_LOG_DEBUG(("%" PRIu16 " --> [%" PRIu32 ",%" PRIu32 "] %" PRItext ", %d bytes", hdr->tag, win.seq, win.ack, msg, dlen)); } stream = find_stream(hdr->tag, con); if (stream == NULL) { if (win.type == NP_PAYLOAD_WINDOW_FLAG_SYN) { stream = find_free_stream(hdr->tag, con); if (stream == NULL) { NABTO_LOG_DEBUG(("Stream with tag %i not accepted", hdr->tag)); } } else { NABTO_LOG_DEBUG(("Received non syn packet for stream which is not available tag %i", hdr->tag)); } } if (stream == NULL) { if (! (win.type & NP_PAYLOAD_WINDOW_FLAG_RST)) { build_and_send_rst_packet(con, hdr->tag, &win); } return; } if (!nabto_stream_validate_win(&win, stream)) { NABTO_LOG_ERROR(("Cannot validate received stream window.")); return; } NABTO_LOG_TRACE(("(.%i.) Stream with tag %i accepted, slot=%i", con->spnsi, hdr->tag, unabto_stream_index(stream))); stream->stats.receivedPackets++; memset(&sackData, 0, sizeof(sackData)); { uint8_t* ptr = sackStart; while(sackLength >= 8 && sackData.nPairs < NP_PAYLOAD_SACK_MAX_PAIRS) { uint32_t sackSeqStart; // start of sack uint32_t sackSeqEnd; // end of sack one larger than actual acked window. READ_FORWARD_U32(sackSeqStart, ptr); READ_FORWARD_U32(sackSeqEnd, ptr); sackLength -= 8; sackData.pairs[sackData.nPairs].start = sackSeqStart; sackData.pairs[sackData.nPairs].end = sackSeqEnd; sackData.nPairs++; } } nabto_stream_tcb_event(stream, &win, start, dlen, &sackData); }
uint16_t uip_nthos(uint16_t s) { uint16_t t; READ_U16(t , &s); return t; }
/*--[lit_i_read_directory]----------------------------------------------------- | | This reads the directory chunks from the piece and converts the list into | entry elements in the lit_file structure. | */ int lit_i_read_directory(lit_file * litfile, U8 * piece, int piece_size) { U8 * p = NULL; int nEntries, nRemaining, nChunks, chunk, idx, sizeChunk; entry_type * entry, * prev; if (!piece || (READ_U32(piece) != IFCM_TAG)) { lit_error(ERR_R, "Header Piece #3 is not the main directory! (TAG=%08lx)", (piece)?(READ_U32(piece)):0); return E_LIT_FORMAT_ERROR; } sizeChunk = READ_INT32(piece + 8); nChunks = READ_INT32(piece + 24); if ((32 + (nChunks * sizeChunk)) != piece_size) { lit_error(ERR_R, "IFCM HEADER (%d chunks of %d bytes) != %d total.", nChunks, sizeChunk, piece_size - 32); return E_LIT_FORMAT_ERROR; } prev = NULL; for (chunk = 0; chunk < nChunks; chunk++) { p = piece + 32 + (chunk * sizeChunk); /* This can either be AOLL or AOLI. * AOLI isn't useful for reading */ if (READ_U32(p) != AOLL_TAG) continue; nRemaining = READ_INT32(p + 4); if (nRemaining >= sizeChunk) { lit_error(ERR_R, "AOLL remaining count is NEGATIVE! (%d of %d) %x\n", (int)nRemaining, (int)sizeChunk, (int)nRemaining); return E_LIT_FORMAT_ERROR; } nRemaining = sizeChunk - (nRemaining + 48); nEntries = READ_U16(p + sizeChunk - 2); /* Sometimes, the nEntries doesn't get written. When this happens, * I don't know how many to read. Fortunately, there is "nRemaining", * and if everything is working fine, read_entry will consume JUST * enough bytes */ if (!nEntries) nEntries = 65535; p += 48; if (nRemaining < 0) return E_LIT_FORMAT_ERROR; for (idx = 0; idx < nEntries; idx ++) { if (nRemaining <= 0) break; entry = read_entry(&p, &nRemaining); if (!entry) { return E_LIT_FORMAT_ERROR; } if (!prev) { litfile->entry = entry; prev = entry; } else { prev->next = entry; prev = entry; } } } return 0; }
static hb_buffer_t *tx3g_decode_to_utf8( hb_buffer_t *in ) { uint8_t *pos = in->data; uint8_t *end = in->data + in->size; uint16_t numStyleRecords = 0; uint8_t *startStyle; uint8_t *endStyle; /* * Parse the packet as a TX3G TextSample. * * Look for a single StyleBox ('styl') and read all contained StyleRecords. * Ignore all other box types. * * NOTE: Buffer overflows on read are not checked. */ uint16_t textLength = READ_U16(); uint8_t *text = READ_ARRAY(textLength); startStyle = calloc( textLength, 1 ); endStyle = calloc( textLength, 1 ); while ( pos < end ) { /* * Read TextSampleModifierBox */ uint32_t size = READ_U32(); if ( size == 0 ) { size = pos - end; // extends to end of packet } if ( size == 1 ) { hb_log( "dectx3gsub: TextSampleModifierBox has unsupported large size" ); break; } uint32_t type = READ_U32(); if ( type == FOURCC("uuid") ) { hb_log( "dectx3gsub: TextSampleModifierBox has unsupported extended type" ); break; } if ( type == FOURCC("styl") ) { // Found a StyleBox. Parse the contained StyleRecords if ( numStyleRecords != 0 ) { hb_log( "dectx3gsub: found additional StyleBoxes on subtitle; skipping" ); SKIP_ARRAY(size); continue; } numStyleRecords = READ_U16(); int i; for (i=0; i<numStyleRecords; i++) { StyleRecord curRecord; curRecord.startChar = READ_U16(); curRecord.endChar = READ_U16(); curRecord.fontID = READ_U16(); curRecord.faceStyleFlags = READ_U8(); curRecord.fontSize = READ_U8(); curRecord.textColorRGBA = READ_U32(); startStyle[curRecord.startChar] |= curRecord.faceStyleFlags; endStyle[curRecord.endChar] |= curRecord.faceStyleFlags; } } else { // Found some other kind of TextSampleModifierBox. Skip it. SKIP_ARRAY(size); } } /* * Copy text to output buffer, and add HTML markup for the style records */ int maxOutputSize = textLength + (numStyleRecords * NUM_FACE_STYLE_FLAGS * (MAX_OPEN_TAG_SIZE + MAX_CLOSE_TAG_SIZE)); hb_buffer_t *out = hb_buffer_init( maxOutputSize ); if ( out == NULL ) goto fail; uint8_t *dst = out->data; int charIndex = 0; for ( pos = text, end = text + textLength; pos < end; pos++ ) { if (IS_10xxxxxx(*pos)) { // Is a non-first byte of a multi-byte UTF-8 character WRITE_CHAR(*pos); continue; // ...without incrementing 'charIndex' } uint8_t plusStyles = startStyle[charIndex]; uint8_t minusStyles = endStyle[charIndex]; if (minusStyles & UNDERLINE) WRITE_END_TAG('u'); if (minusStyles & ITALIC) WRITE_END_TAG('i'); if (minusStyles & BOLD) WRITE_END_TAG('b'); if (plusStyles & BOLD) WRITE_START_TAG('b'); if (plusStyles & ITALIC) WRITE_START_TAG('i'); if (plusStyles & UNDERLINE) WRITE_START_TAG('u'); WRITE_CHAR(*pos); charIndex++; } // Trim output buffer to the actual amount of data written out->size = dst - out->data; // Copy metadata from the input packet to the output packet out->s.start = in->s.start; out->s.stop = in->s.stop; fail: free( startStyle ); free( endStyle ); return out; }