bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value) { const uint64_t *words = (const uint64_t*)value; uint_least8_t bytes[8]; #ifdef __BIG_ENDIAN__ bytes[0] = (uint_least8_t)(*words >> 56) & 0xFF; bytes[1] = (uint_least8_t)(*words >> 48) & 0xFF; bytes[2] = (uint_least8_t)(*words >> 40) & 0xFF; bytes[3] = (uint_least8_t)(*words >> 32) & 0xFF; bytes[4] = (uint_least8_t)(*words >> 24) & 0xFF; bytes[5] = (uint_least8_t)(*words >> 16) & 0xFF; bytes[6] = (uint_least8_t)(*words >> 8) & 0xFF; bytes[7] = (uint_least8_t)(*words) & 0xFF; return pb_write(stream, bytes, 8); #else bytes[7] = (uint_least8_t)(*words >> 56) & 0xFF; bytes[6] = (uint_least8_t)(*words >> 48) & 0xFF; bytes[5] = (uint_least8_t)(*words >> 40) & 0xFF; bytes[4] = (uint_least8_t)(*words >> 32) & 0xFF; bytes[3] = (uint_least8_t)(*words >> 24) & 0xFF; bytes[2] = (uint_least8_t)(*words >> 16) & 0xFF; bytes[1] = (uint_least8_t)(*words >> 8) & 0xFF; bytes[0] = (uint_least8_t)(*words) & 0xFF; return pb_write(stream, bytes, 8); #endif }
/* Read a string from the pbuf, update pos and return 0 on success */ void pb_write_str(struct pbuf* pbuf, const char* str, uint32_t len, int* pos) { uint32_t padding = 0; /* Write the string length and string */ pb_write_arrl(pbuf, &len, sizeof(len), pos); pb_write(pbuf, str, len, pos); /* Write the padding */ pb_write(pbuf, &padding, ROUNDUP(*pos, 4) - *pos, pos); }
bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src) { #ifdef __BIG_ENDIAN__ uint8_t bytes[4] = {0}; memcpy(bytes, src, 4); uint8_t lebytes[4] = {bytes[3], bytes[2], bytes[1], bytes[0]}; return pb_write(stream, lebytes, 4); #else return pb_write(stream, (uint8_t*)src, 4); #endif }
/* Encode a fixed32, sfixed32 or float value. * You need to pass a pointer to a 4-byte wide C variable. */ static int pb_encode_fixed32(pb_ostream_t *stream, const void *value) { #ifdef __BIG_ENDIAN__ const uint8_t *bytes = value; uint8_t lebytes[4]; lebytes[0] = bytes[3]; lebytes[1] = bytes[2]; lebytes[2] = bytes[1]; lebytes[3] = bytes[0]; return pb_write(stream, lebytes, 4); #else return pb_write(stream, (const uint8_t *) value, 4); #endif }
bool checkreturn pb_encode_string(pb_ostream_t *stream, const uint8_t *buffer, size_t size) { if (!pb_encode_varint(stream, (uint64_t)size)) return false; return pb_write(stream, buffer, size); }
/* Encode an integer in the varint format. * This works for bool, enum, int32, int64, uint32 and uint64 field types. */ static int pb_encode_varint(pb_ostream_t *stream, uint64_t value) { uint8_t buffer[10]; size_t i = 0; if (value == 0) return pb_write(stream, (uint8_t *) &value, 1); while (value) { buffer[i] = (uint8_t)((value & 0x7F) | 0x80); value >>= 7; i++; } buffer[i - 1] &= 0x7F; /* Unset top bit on last byte */ return pb_write(stream, buffer, i); }
/* Encode a string or bytes type field. For strings, pass strlen(s) as size. */ static int pb_encode_string(pb_ostream_t *stream, const uint8_t *buffer, size_t size) { if (!pb_encode_varint(stream, (uint64_t) size)) return 0; return pb_write(stream, buffer, size); }
/* Encode a fixed64, sfixed64 or double value. * You need to pass a pointer to a 8-byte wide C variable. */ static int checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value) { #ifdef __BIG_ENDIAN__ const uint8_t *bytes = value; uint8_t lebytes[8]; lebytes[0] = bytes[7]; lebytes[1] = bytes[6]; lebytes[2] = bytes[5]; lebytes[3] = bytes[4]; lebytes[4] = bytes[3]; lebytes[5] = bytes[2]; lebytes[6] = bytes[1]; lebytes[7] = bytes[0]; return pb_write(stream, lebytes, 8); #else return pb_write(stream, (const uint8_t *) value, 8); #endif }
bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value) { const uint32_t *words = (const uint32_t*)value; uint_least8_t bytes[4]; #ifdef __BIG_ENDIAN__ bytes[0] = (uint_least8_t)(*words >> 24) & 0xFF; bytes[1] = (uint_least8_t)(*words >> 16) & 0xFF; bytes[2] = (uint_least8_t)(*words >> 8) & 0xFF; bytes[3] = (uint_least8_t)(*words) & 0xFF; return pb_write(stream, bytes, 4); #else bytes[3] = (uint_least8_t)(*words >> 24) & 0xFF; bytes[2] = (uint_least8_t)(*words >> 16) & 0xFF; bytes[1] = (uint_least8_t)(*words >> 8) & 0xFF; bytes[0] = (uint_least8_t)(*words) & 0xFF; return pb_write(stream, bytes, 4); #endif }
bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value) { uint32_t val = *(const uint32_t*)value; pb_byte_t bytes[4]; bytes[0] = (pb_byte_t)(val & 0xFF); bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); return pb_write(stream, bytes, 4); }
void pb_write_arrl(struct pbuf* pbuf, const uint32_t* arr, int size, int* pos) { uint32_t nl_arr[size/sizeof(uint32_t)]; int i; for(i = 0; i < size/sizeof(uint32_t); i++){ nl_arr[i] = htonl(arr[i]); } pb_write(pbuf, nl_arr, sizeof(nl_arr), pos); }
/******************** * Helper functions * ********************/ bool checkreturn pb_encode_varint(pb_ostream_t *stream, uint64_t value) { pb_byte_t buffer[10]; size_t i = 0; if (value <= 0x7F) { pb_byte_t v = (pb_byte_t)value; return pb_write(stream, &v, 1); } while (value) { buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80); value >>= 7; i++; } buffer[i-1] &= 0x7F; /* Unset top bit on last byte */ return pb_write(stream, buffer, i); }
bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value) { uint64_t val = *(const uint64_t*)value; pb_byte_t bytes[8]; bytes[0] = (pb_byte_t)(val & 0xFF); bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); bytes[4] = (pb_byte_t)((val >> 32) & 0xFF); bytes[5] = (pb_byte_t)((val >> 40) & 0xFF); bytes[6] = (pb_byte_t)((val >> 48) & 0xFF); bytes[7] = (pb_byte_t)((val >> 56) & 0xFF); return pb_write(stream, bytes, 8); }
/** * close the SACD device and clean up. */ static int sacd_net_input_close(sacd_input_t dev) { if (!dev) { return 0; } else { ServerRequest request; ServerResponse response; pb_istream_t input = pb_istream_from_socket(&dev->fd); pb_ostream_t output = pb_ostream_from_socket(&dev->fd); uint8_t zero = 0; request.type = ServerRequest_Type_DISC_CLOSE; if (!pb_encode(&output, ServerRequest_fields, &request)) { goto error; } pb_write(&output, &zero, 1); if (!pb_decode(&input, ServerResponse_fields, &response)) { goto error; } if (response.result == 0 || response.type != ServerResponse_Type_DISC_CLOSED) { goto error; } } error: if(dev) { socket_destroy(&dev->fd); socket_close(); if (dev->input_buffer) { free(dev->input_buffer); dev->input_buffer = 0; } free(dev); dev = 0; } return 0; }
bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) { /* First calculate the message size using a non-writing substream. */ pb_ostream_t substream = PB_OSTREAM_SIZING; size_t size; bool status; if (!pb_encode(&substream, fields, src_struct)) { #ifndef PB_NO_ERRMSG stream->errmsg = substream.errmsg; #endif return false; } size = substream.bytes_written; if (!pb_encode_varint(stream, (uint64_t)size)) return false; if (stream->callback == NULL) return pb_write(stream, NULL, size); /* Just sizing */ if (stream->bytes_written + size > stream->max_size) PB_RETURN_ERROR(stream, "stream full"); /* Use a substream to verify that a callback doesn't write more than * what it did the first time. */ substream.callback = stream->callback; substream.state = stream->state; substream.max_size = size; substream.bytes_written = 0; #ifndef PB_NO_ERRMSG substream.errmsg = NULL; #endif status = pb_encode(&substream, fields, src_struct); stream->bytes_written += substream.bytes_written; stream->state = substream.state; #ifndef PB_NO_ERRMSG stream->errmsg = substream.errmsg; #endif if (substream.bytes_written != size) PB_RETURN_ERROR(stream, "submsg size changed"); return status; }
void send_printer_status() { uint8_t out[16]; uint8_t type; pb_ostream_t stream = pb_ostream_from_buffer(out, sizeof(out)); bool status; PrinterStatus record; type = PRINTER_STATUS; pb_write(&stream, &type, 1); record.cardInserted = 1; record.keyInserted = get_interlock_state(); record.overrideSwitch = get_interlock_state(); record.laserOn = g_laser_gating; record.laserPowerFeedback = 42; status = pb_encode(&stream, PrinterStatus_fields, &record); if (status) { serialio_write(out, stream.bytes_written); } }
/* Eecode submessage in __messages protos */ static int pb_encode_submessage(pb_ostream_t *stream, const pc_JSON *gprotos, const pc_JSON *protos, pc_JSON *value) { /* First calculate the message size using a non-writing substream. */ pb_ostream_t substream = { 0, 0, 0, 0 }; size_t size; int status; if (!pb_encode(&substream, gprotos, protos, value)) { return 0; } size = substream.bytes_written; if (!pb_encode_varint(stream, (uint64_t) size)) { return 0; } if (stream->callback == NULL ) return pb_write(stream, NULL, size); /* Just sizing */ if (stream->bytes_written + size > stream->max_size) return 0; /* Use a substream to verify that a callback doesn't write more than * what it did the first time. */ substream.callback = stream->callback; substream.state = stream->state; substream.max_size = size; substream.bytes_written = 0; status = pb_encode(&substream, gprotos, protos, value); stream->bytes_written += substream.bytes_written; stream->state = substream.state; if (substream.bytes_written != size) { return 0; } return status; }
bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src) { pb_ostream_t substream = {0}; size_t size; bool status; if (field->ptr == NULL) return false; if (!pb_encode(&substream, (pb_field_t*)field->ptr, src)) return false; size = substream.bytes_written; if (!pb_encode_varint(stream, size)) return false; if (stream->callback == NULL) return pb_write(stream, NULL, size); /* Just sizing */ if (stream->bytes_written + size > stream->max_size) return false; /* Use a substream to verify that a callback doesn't write more than * what it did the first time. */ substream.callback = stream->callback; substream.state = stream->state; substream.max_size = size; substream.bytes_written = 0; status = pb_encode(&substream, (pb_field_t*)field->ptr, src); stream->bytes_written += substream.bytes_written; if (substream.bytes_written != size) return false; return status; }
int cmd_retrieve(struct arguments *args) { int rc; struct db *db; char pass[MAX_PASS_LENGTH + 1], *fndpass; rc = -1; db = NULL; if (uuid_is_null(args->uuid) || !args->dbfile) { fprintf(stderr, "missing arguments for retrieve\n"); goto out; } if (get_pass(PASS_PROMPT, pass, MAX_PASS_LENGTH + 1, stdin)) { fprintf(stderr, "%s\n", GET_PASS_FAIL); goto out; } if (!(db = pwsdb_open(pass, args->dbfile))) { fprintf(stderr, "couldn't open db\n"); goto out; } if (!(fndpass = pwsdb_get_pass(db, args->uuid))) { fprintf(stderr, "couldn't find pass\n"); goto out; } pb_write(fndpass); rc = 0; out: destroy_db(db); free(db); return rc; }
bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) { /* First calculate the message size using a non-writing substream. */ pb_ostream_t substream = {0,0,0,0}; size_t size; bool status; if (!pb_encode(&substream, fields, src_struct)) return false; size = substream.bytes_written; if (!pb_encode_varint(stream, (uint64_t)size)) return false; if (stream->callback == NULL) return pb_write(stream, NULL, size); /* Just sizing */ if (stream->bytes_written + size > stream->max_size) return false; /* Use a substream to verify that a callback doesn't write more than * what it did the first time. */ substream.callback = stream->callback; substream.state = stream->state; substream.max_size = size; substream.bytes_written = 0; status = pb_encode(&substream, fields, src_struct); stream->bytes_written += substream.bytes_written; stream->state = substream.state; if (substream.bytes_written != size) return false; return status; }
static uint32_t sacd_net_input_total_sectors(sacd_input_t dev) { if (!dev) { return 0; } else { ServerRequest request; ServerResponse response; pb_istream_t input = pb_istream_from_socket(&dev->fd); pb_ostream_t output = pb_ostream_from_socket(&dev->fd); uint8_t zero = 0; request.type = ServerRequest_Type_DISC_SIZE; if (!pb_encode(&output, ServerRequest_fields, &request)) { return 0; } /* We signal the end of request with a 0 tag. */ pb_write(&output, &zero, 1); if (!pb_decode(&input, ServerResponse_fields, &response)) { return 0; } if (response.type != ServerResponse_Type_DISC_SIZE) { return 0; } return (uint32_t) response.result; } }
/* ** PB_PUT -- buffered put on pipe ** ** This routine puts the named data out onto the pipe ** determined by ppb->pb_proc. ** ** Parameters: ** dp -- a pointer to the data to write. ** len -- the length of the data to write. ** ppb -- a pointer to the pipe block. ** ** Returns: ** none ** ** Side Effects: ** none ** ** Trace Flags: ** 18.8 - 18.15 */ void pb_put(register char *dp, register int len, register pb_t *ppb) { register int i; #ifdef xCTR2 if (tTf(18, 9)) lprintf("pb_put: len %d\n", len); #endif /* ** Top loop. ** Loop until we have run out of things to write. */ while (len > 0) { /* compute the length to move */ i = min(ppb->pb_nleft, len); #ifdef xCM_DEBUG if (i <= 0) syserr("pb_put: zero"); #endif /* move data into buffer and adjust ptrs & counts */ bmove(dp, ppb->pb_xptr, i); dp += i; len -= i; ppb->pb_xptr += i; ppb->pb_nleft -= i; ppb->pb_nused += i; /* flush block if full */ if (ppb->pb_nleft <= 0) pb_write(ppb); } }
/* Callbacks don't need this function because they usually know the data type * without examining the field structure. * Therefore it is static for now. */ static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, const void *pData, size_t count, pb_encoder_t func) { size_t i; const void *p; size_t size; if (count == 0) return true; if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) { if (!pb_encode_tag(stream, PB_WT_STRING, field->tag)) return false; /* Determine the total size of packed array. */ if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32) { size = 4 * count; } else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64) { size = 8 * count; } else { pb_ostream_t sizestream = {0,0,0,0}; p = pData; for (i = 0; i < count; i++) { if (!func(&sizestream, field, p)) return false; p = (const char*)p + field->data_size; } size = sizestream.bytes_written; } if (!pb_encode_varint(stream, (uint64_t)size)) return false; if (stream->callback == NULL) return pb_write(stream, NULL, size); /* Just sizing.. */ /* Write the data */ p = pData; for (i = 0; i < count; i++) { if (!func(stream, field, p)) return false; p = (const char*)p + field->data_size; } } else { p = pData; for (i = 0; i < count; i++) { if (!pb_encode_tag_for_field(stream, field)) return false; if (!func(stream, field, p)) return false; p = (const char*)p + field->data_size; } } return true; }
static void client_thread(void *userdata) { p_socket client = (p_socket) userdata; ServerRequest request; ServerResponse response; uint8_t zero = 0; uint8_t *output_buf = (uint8_t *) malloc(MAX_PROCESSING_BLOCK_SIZE * SACD_LSN_SIZE + 1024); pb_istream_t input = pb_istream_from_socket(client); pb_ostream_t output; sacd_reader_t *sacd_reader = 0; scarletbook_handle_t *handle = 0; int non_encrypted_disc = 0; int checked_for_non_encrypted_disc = 0; uint32_t encrypted_start_1 = 0; uint32_t encrypted_start_2 = 0; uint32_t encrypted_end_1 = 0; uint32_t encrypted_end_2 = 0; uint32_t block_size = 0; uint32_t end_lsn = 0; client_connected = 1; response.data.bytes = (uint8_t *) malloc(MAX_PROCESSING_BLOCK_SIZE * SACD_LSN_SIZE); for (;;) { if (!pb_decode(&input, ServerRequest_fields, &request)) { break; } response.has_data = false; response.data.size = 0; response.result = -1; switch(request.type) { case ServerRequest_Type_DISC_READ: { response.type = ServerResponse_Type_DISC_READ; if (handle && sacd_reader) { int encrypted = 0; end_lsn = request.sector_offset + request.sector_count; // check what block ranges are encrypted.. if (request.sector_offset < encrypted_start_1) { block_size = min(encrypted_start_1 - request.sector_offset, MAX_PROCESSING_BLOCK_SIZE); encrypted = 0; } else if (request.sector_offset >= encrypted_start_1 && request.sector_offset <= encrypted_end_1) { block_size = min(encrypted_end_1 + 1 - request.sector_offset, MAX_PROCESSING_BLOCK_SIZE); encrypted = 1; } else if (request.sector_offset > encrypted_end_1 && request.sector_offset < encrypted_start_2) { block_size = min(encrypted_start_2 - request.sector_offset, MAX_PROCESSING_BLOCK_SIZE); encrypted = 0; } else if (request.sector_offset >= encrypted_start_2 && request.sector_offset <= encrypted_end_2) { block_size = min(encrypted_end_2 + 1 - request.sector_offset, MAX_PROCESSING_BLOCK_SIZE); encrypted = 1; } block_size = min(end_lsn - request.sector_offset, block_size); response.result = sacd_read_block_raw(sacd_reader, request.sector_offset, block_size, response.data.bytes); response.has_data = response.result > 0; response.data.size = response.result * SACD_LSN_SIZE; // the ATAPI call which returns the flag if the disc is encrypted or not is unknown at this point. // user reports tell me that the only non-encrypted discs out there are DSD 3 14/16 discs. // this is a quick hack/fix for these discs. if (encrypted && checked_for_non_encrypted_disc == 0) { switch (handle->area[0].area_toc->frame_format) { case FRAME_FORMAT_DSD_3_IN_14: case FRAME_FORMAT_DSD_3_IN_16: non_encrypted_disc = *(uint64_t *)(response.data.bytes + 16) == 0; break; } checked_for_non_encrypted_disc = 1; } // encrypted blocks need to be decrypted first if (encrypted && non_encrypted_disc == 0) { sacd_decrypt(sacd_reader, response.data.bytes, block_size); } } } break; case ServerRequest_Type_DISC_OPEN: response.type = ServerResponse_Type_DISC_OPENED; sacd_reader = sacd_open("/dev_bdvd"); if (sacd_reader) { handle = scarletbook_open(sacd_reader, 0); checked_for_non_encrypted_disc = 0; non_encrypted_disc = 0; if (handle) { // set the encryption range if (handle->area[0].area_toc != 0) { encrypted_start_1 = handle->area[0].area_toc->track_start; encrypted_end_1 = handle->area[0].area_toc->track_end; } if (handle->area[1].area_toc != 0) { encrypted_start_2 = handle->area[1].area_toc->track_start; encrypted_end_2 = handle->area[1].area_toc->track_end; } response.result = sacd_authenticate(sacd_reader); } } break; case ServerRequest_Type_DISC_CLOSE: { response.type = ServerResponse_Type_DISC_CLOSED; if (handle) { scarletbook_close(handle); handle = 0; } if (sacd_reader) { sacd_close(sacd_reader); sacd_reader = 0; } response.result = 0; } break; case ServerRequest_Type_DISC_SIZE: response.type = ServerResponse_Type_DISC_SIZE; if (sacd_reader) { response.result = sacd_get_total_sectors(sacd_reader); } break; } // reset output stream output = pb_ostream_from_buffer(output_buf, MAX_PROCESSING_BLOCK_SIZE * SACD_LSN_SIZE + 1024); if (!pb_encode(&output, ServerResponse_fields, &response)) { break; } /* We signal the end of a request with a 0 tag. */ pb_write(&output, &zero, 1); // write the output buffer to the opened socket { bool ret; size_t written; ret = (socket_send(client, (char *) output_buf, output.bytes_written, &written, 0, 0) == IO_DONE && written == output.bytes_written); if (!ret) break; } if (request.type == ServerRequest_Type_DISC_CLOSE) { break; } } if (handle) scarletbook_close(handle); if (sacd_reader) sacd_close(sacd_reader); free(response.data.bytes); free(output_buf); closesocket((int) *client); client_connected = 0; sysThreadExit(0); }
static ssize_t sacd_net_input_read(sacd_input_t dev, int pos, int blocks, void *buffer) { if (!dev) { return 0; } else { uint8_t output_buf[16]; ServerRequest request; ServerResponse response; pb_ostream_t output = pb_ostream_from_buffer(output_buf, sizeof(output_buf)); pb_istream_t input = pb_istream_from_socket(&dev->fd); uint8_t zero = 0; request.type = ServerRequest_Type_DISC_READ; request.sector_offset = pos; request.sector_count = blocks; if (!pb_encode(&output, ServerRequest_fields, &request)) { return 0; } /* We signal the end of request with a 0 tag. */ pb_write(&output, &zero, 1); // write the output buffer to the opened socket { bool ret; size_t written; ret = (socket_send(&dev->fd, (char *) output_buf, output.bytes_written, &written, 0, 0) == IO_DONE && written == output.bytes_written); if (!ret) return 0; } #if 0 response.data.bytes = buffer; { size_t got; uint8_t *buf_ptr = dev->input_buffer; size_t buf_left = blocks * SACD_LSN_SIZE + 16; input = pb_istream_from_buffer(dev->input_buffer, MAX_PROCESSING_BLOCK_SIZE * SACD_LSN_SIZE + 1024); if (socket_recv(&dev->fd, (char *) buf_ptr, buf_left, &got, MSG_PARTIAL, 0) != IO_DONE) return 0; while(got > 0 && !pb_decode(&input, ServerResponse_fields, &response)) { buf_ptr += got; buf_left -= got; if (socket_recv(&dev->fd, (char *) buf_ptr, buf_left, &got, MSG_PARTIAL, 0) != IO_DONE) return 0; input = pb_istream_from_buffer(dev->input_buffer, MAX_PROCESSING_BLOCK_SIZE * SACD_LSN_SIZE + 1024); } } #else response.data.bytes = buffer; if (!pb_decode(&input, ServerResponse_fields, &response)) { return 0; } #endif if (response.type != ServerResponse_Type_DISC_READ) { return 0; } if (response.has_data) { return response.result; } } return 0; }
/* Encode a static array. Handles the size calculations and possible packing. */ static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, const void *pData, size_t count, pb_encoder_t func) { size_t i; const void *p; size_t size; if (count == 0) return true; if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size) PB_RETURN_ERROR(stream, "array max size exceeded"); /* We always pack arrays if the datatype allows it. */ if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) { if (!pb_encode_tag(stream, PB_WT_STRING, field->tag)) return false; /* Determine the total size of packed array. */ if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32) { size = 4 * count; } else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64) { size = 8 * count; } else { pb_ostream_t sizestream = PB_OSTREAM_SIZING; p = pData; for (i = 0; i < count; i++) { if (!func(&sizestream, field, p)) return false; p = (const char*)p + field->data_size; } size = sizestream.bytes_written; } if (!pb_encode_varint(stream, (uint64_t)size)) return false; if (stream->callback == NULL) return pb_write(stream, NULL, size); /* Just sizing.. */ /* Write the data */ p = pData; for (i = 0; i < count; i++) { if (!func(stream, field, p)) return false; p = (const char*)p + field->data_size; } } else { p = pData; for (i = 0; i < count; i++) { if (!pb_encode_tag_for_field(stream, field)) return false; /* Normally the data is stored directly in the array entries, but * for pointer-type string and bytes fields, the array entries are * actually pointers themselves also. So we have to dereference once * more to get to the actual data. */ if (PB_ATYPE(field->type) == PB_ATYPE_POINTER && (PB_LTYPE(field->type) == PB_LTYPE_STRING || PB_LTYPE(field->type) == PB_LTYPE_BYTES)) { if (!func(stream, field, *(const void* const*)p)) return false; } else { if (!func(stream, field, p)) return false; } p = (const char*)p + field->data_size; } } return true; }
/** * initialize and open a SACD device or file. */ static sacd_input_t sacd_net_input_open(const char *target) { ServerRequest request; ServerResponse response; sacd_input_t dev = 0; const char *err = 0; t_timeout tm; pb_istream_t input; pb_ostream_t output; uint8_t zero = 0; /* Allocate the library structure */ dev = (sacd_input_t) calloc(sizeof(*dev), 1); if (dev == NULL) { fprintf(stderr, "libsacdread: Could not allocate memory.\n"); return NULL; } dev->input_buffer = (uint8_t *) malloc(MAX_PROCESSING_BLOCK_SIZE * SACD_LSN_SIZE + 1024); if (dev->input_buffer == NULL) { fprintf(stderr, "libsacdread: Could not allocate memory.\n"); goto error; } socket_open(); socket_create(&dev->fd, AF_INET, SOCK_STREAM, 0); socket_setblocking(&dev->fd); timeout_markstart(&tm); err = inet_tryconnect(&dev->fd, substr(target, 0, strchr(target, ':') - target), atoi(strchr(target, ':') + 1), &tm); if (err) { fprintf(stderr, "Failed to connect\n"); goto error; } socket_setblocking(&dev->fd); input = pb_istream_from_socket(&dev->fd); output = pb_ostream_from_socket(&dev->fd); request.type = ServerRequest_Type_DISC_OPEN; if (!pb_encode(&output, ServerRequest_fields, &request)) { fprintf(stderr, "Failed to encode request\n"); goto error; } /* We signal the end of request with a 0 tag. */ pb_write(&output, &zero, 1); if (!pb_decode(&input, ServerResponse_fields, &response)) { fprintf(stderr, "Failed to decode response\n"); goto error; } if (response.result != 0 || response.type != ServerResponse_Type_DISC_OPENED) { fprintf(stderr, "Response result non-zero or disc opened\n"); goto error; } return dev; error: sacd_input_close(dev); return 0; }