/*** * Turn a multibase decoded string of bytes into a Cid struct * @param incoming the multibase decoded array * @param incoming_size the size of the array * @param cid the Cid structure to fill */ int ipfs_cid_cast(const unsigned char* incoming, size_t incoming_size, struct Cid* cid) { if (incoming_size == 34 && incoming[0] == 18 && incoming[1] == 32) { // this is a multihash cid->hash_length = mh_multihash_length(incoming, incoming_size); cid->codec = CID_PROTOBUF; cid->version = 0; mh_multihash_digest(incoming, incoming_size, &cid->hash, &cid->hash_length); return 1; } // This is not a multihash. Perhaps it is using varints. Try to peel the information out of the bytes. // first the version int pos = 0; size_t num_bytes = 0; cid->version = varint_decode(&incoming[pos], incoming_size - pos, &num_bytes); if (num_bytes == 0 || cid->version > 1 || cid->version < 0) return 0; pos = num_bytes; // now the codec uint32_t codec = 0; codec = varint_decode(&incoming[pos], incoming_size - pos, &num_bytes); if (num_bytes == 0) return 0; cid->codec = codec; pos += num_bytes; // now what is left cid->hash_length = incoming_size - pos; cid->hash = (unsigned char*)(&incoming[pos]); return 1; }
static void decode(uint8_t buffer[10]) { struct longlong r; int s = varint_decode(buffer,&r); printf("[%d] %x %x\n",s, r.low, r.hi); }
int ipfs_cid_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Cid** output) { // short cut for nulls if (buffer_length == 0) { *output = NULL; return 1; } size_t pos = 0; int version = 0; unsigned char* hash; size_t hash_length; char codec = 0; int retVal = 0; while(pos < buffer_length) { size_t bytes_read = 0; int field_no; enum WireType field_type; if (protobuf_decode_field_and_type(&buffer[pos], buffer_length, &field_no, &field_type, &bytes_read) == 0) { return 0; } pos += bytes_read; switch(field_no) { case (1): version = varint_decode(&buffer[pos], buffer_length - pos, &bytes_read); pos += bytes_read; break; case (2): codec = varint_decode(&buffer[pos], buffer_length - pos, &bytes_read); pos += bytes_read; break; case (3): retVal = protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&hash, &hash_length, &bytes_read); if (retVal == 0) return 0; pos += bytes_read; break; } } retVal = ipfs_cid_new(version, hash, hash_length, codec, output); free(hash); return retVal; }
uint64_t db_read_uint64(DB_val *const val) { db_assert(val->size >= 1); size_t const len = varint_size(val->data); db_assert(val->size >= len); uint64_t const x = varint_decode(val->data, val->size); val->data += len; val->size -= len; return x; }
static void zigzag(int64_t n) { printf("%llx\n",n); uint8_t zigzag[10]; dump(zigzag, varint_zigzag(n,zigzag)); struct longlong r; varint_decode(zigzag,&r); varint_dezigzag64(&r); printf("%x%08x\n",r.hi, r.low); }
static void udp_cb(uv_udp_ssl_t *conn, void *data, char *buf, size_t len) { mumble_audio_t *audio = (mumble_audio_t*)data; audio_packet_t decoded; if (*buf == 0x20) { // If it's a ping packet, parse and notify pinger uint64_t timestamp; int ret = varint_decode(buf + 1, len - 1, ×tamp); assert(ret > 0); mumble_udp_ping_recv(&audio->pinger, timestamp); } else { // If it's an audio packet, fwd to decoder mumble_audio_decoder_decode(&audio->decoder, buf, len, &decoded); } }
int varint_decode(const uint8_t *buf, int size, uint64_t *result) { if (size == 0) { return 0; } int position = 0; *result = 0; if ((buf[position] & 0x80) == 0x00) { *result = (uint8_t)buf[position] & 0x7F; } else if ((buf[position] & 0xC0) == 0x80) { if (size < 2) { return -1; } *result = ((buf[position] & 0x3F) << 8) | buf[++position]; } else if ((buf[position] & 0xF0) == 0xF0) { switch (buf[position] & 0xFC) { case 0xF0: *result = buf[++position] << 24 | buf[++position] << 16 | buf[++position] << 8 | buf[++position]; break; case 0xF4: *result = (uint64_t)buf[++position] << 56 | (uint64_t)buf[++position] << 48 | (uint64_t)buf[++position] << 40 | (uint64_t)buf[++position] << 32 | buf[++position] << 24 | buf[++position] << 16 | buf[++position] << 8 | buf[++position]; break; case 0xF8: ; int r_result = varint_decode(buf + position, size - position, result); if (r_result != 0) { return r_result; } *result = ~*result; break; case 0xFC: *result = buf[position] & 0x03; *result = ~*result; break; default: return -2; break; } } else if ((buf[position] & 0xF0) == 0xE0) { *result = (buf[position] & 0x0F) << 24 | buf[++position] << 16 | buf[++position] << 8 | buf[++position]; } else if ((buf[position] & 0xE0) == 0xC0) { *result = (buf[position] & 0x1F) << 16 | buf[++position] << 8 | buf[++position]; } return position + 1; }
static size_t varint_encode(uint8_t *const data, size_t const size, uint64_t const x) { assert(size >= DB_VARINT_MAX); size_t rem = 8; size_t out = 0; while(rem--) { uint8_t const y = 0xff & (x >> (8 * rem)); if(out) { data[out++] = y; } else if(y && y <= 0x0f) { data[out++] = ((rem+0) << 4) | (y & 0x0f); } else if(y) { data[out++] = ((rem+1) << 4) | 0; data[out++] = y; } } if(!out) data[out++] = 0; assert(varint_decode(data, size) == x); return out; }
uint64_t io_get_uvarint(Input* in) { VARINT_STACK(v, 10); if (!varint_decode(v, in)) RAISE(MALFORMED); return varint_to_uint(v); }