static int as_command_bytes_to_int(uint8_t *buf, int sz, int64_t *value) { if (sz == 8) { // No need to worry about sign extension *value = cf_swap_from_be64(*(uint64_t *)buf); return 0; } // The server always returns sz == 8, so the rest of this function is just for legacy reasons. if (sz == 0) { *value = 0; return 0; } if (sz > 8) { return -1; } if (sz == 1 && *buf < 0x7f) { *value = *buf; return 0; } // Negative numbers must be sign extended if (*buf & 0x80) { uint8_t lg_buf[8]; int i; for (i = 0; i < 8 - sz; i++) { lg_buf[i]=0xff; } memcpy(&lg_buf[i], buf, sz); *value = cf_swap_from_be64(*(uint64_t *)buf); return 0; } // Positive numbers don't. else { int64_t v = 0; for (int i = 0; i < sz; i++, buf++) { v <<= 8; v |= *buf; } *value = v; return 0; } return 0; }
// Byte swap proto from network byte order (big endian) to current machine byte order. void as_proto_swap_from_be(as_proto *p) { uint8_t version = p->version; uint8_t type = p->type; p->version = p->type = 0; p->sz = cf_swap_from_be64(*(uint64_t*)p); p->version = version; p->type = type; }
static int as_read_user_blocks(int fd, uint8_t* buffer, uint64_t deadline_ms, int timeout_ms, as_vector* /*<as_user_roles*>*/ users) { int buffer_size = STACK_BUF_SZ; uint8_t* buf = buffer; uint64_t proto; int status = 0; int size; while (status == 0) { if (cf_socket_read_timeout(fd, buf, 8, deadline_ms, timeout_ms)) { status = -1; break; } proto = cf_swap_from_be64(*(uint64_t*)buf); size = (int)(proto & 0xFFFFFFFFFFFFL); if (size > 0) { if (size > buffer_size) { buffer_size = size; if (buf != buffer) { cf_free(buf); } buf = cf_malloc(size); } if (cf_socket_read_timeout(fd, buf, size, deadline_ms, timeout_ms)) { status = -1; break; } status = as_parse_users(buf, size, users); } else { break; } } if (buf != buffer) { cf_free(buf); } return (status == QUERY_END)? 0 : status; }
// Local utility. static as_val * as_val_from_flat_key(uint8_t * flat_key, uint32_t size) { uint8_t type = *flat_key; uint8_t * key = flat_key + 1; switch ( type ) { case AS_PARTICLE_TYPE_INTEGER: // TODO - verify size is (1 + 8) ??? // Flat integer keys are in big-endian order. return (as_val *) as_integer_new(cf_swap_from_be64(*(int64_t *)key)); case AS_PARTICLE_TYPE_STRING: { // Key length is size - 1, then +1 for null-termination. char * buf = cf_malloc(size); if (! buf) { return NULL; } uint32_t len = size - 1; memcpy(buf, key, len); buf[len] = '\0'; return (as_val *) as_string_new(buf, true); } case AS_PARTICLE_TYPE_BLOB: { uint32_t blob_size = size - 1; uint8_t *buf = cf_malloc(blob_size); if (! buf) { return NULL; } memcpy(buf, key, blob_size); return (as_val *) as_bytes_new_wrap(buf, blob_size, true); } default: return NULL; } }