int format_file_read (client_t *client, format_plugin_t *plugin, icefile_handle f) { refbuf_t *refbuf = client->refbuf; ssize_t bytes = -1; int unprocessed = 0; do { if (refbuf == NULL) { if (file_in_use (f) == 0) return -2; refbuf = client->refbuf = refbuf_new (8192); client->flags |= CLIENT_HAS_INTRO_CONTENT; client->pos = refbuf->len; client->queue_pos = 0; } if (client->pos < refbuf->len) break; if (refbuf->next) { //DEBUG1 ("next intro block is %d", refbuf->next->len); client->refbuf = refbuf->next; refbuf->next = NULL; refbuf_release (refbuf); client->pos = 0; return 0; } if (file_in_use (f) == 0) return -2; bytes = pread (f, refbuf->data, 8192, client->intro_offset); if (bytes <= 0) return bytes < 0 ? -2 : -1; refbuf->len = bytes; client->pos = 0; if (plugin && plugin->align_buffer) { /* here the buffer may require truncating to keep the buffers aligned on * certain boundaries */ unprocessed = plugin->align_buffer (client, plugin); if (unprocessed == bytes) return -1; if (unprocessed < 0 || unprocessed > bytes) { unprocessed = 0; client->connection.error = 1; } } client->intro_offset += (bytes - unprocessed); } while (1); return refbuf->len - client->pos; }
static int prefile_send (client_t *client) { int loop = 8, bytes, written = 0; worker_t *worker = client->worker; while (loop) { refbuf_t *refbuf = client->refbuf; fh_node *fh = client->shared_data; loop--; if (fserve_running == 0 || client->connection.error) return -1; if (refbuf == NULL || client->pos == refbuf->len) { if (fh->finfo.fallback) return fserve_move_listener (client); if (refbuf == NULL || refbuf->next == NULL) { if (file_in_use (fh->f)) // is there a file to read from { if (fh->finfo.limit) client->ops = &throttled_file_content_ops; else client->ops = &file_content_ops; refbuf_release (client->refbuf); client->refbuf = NULL; client->pos = 0; return client->ops->process (client); } if (client->respcode) return -1; return client_send_404 (client, NULL); } else { refbuf_t *to_go = client->refbuf; refbuf = client->refbuf = to_go->next; to_go->next = NULL; refbuf_release (to_go); } client->pos = 0; } if (refbuf->flags & WRITE_BLOCK_GENERIC) bytes = format_generic_write_to_client (client); else bytes = client->check_buffer (client); if (bytes < 0) { client->schedule_ms = worker->time_ms + (written ? 150 : 300); return 0; } written += bytes; global_add_bitrates (global.out_bitrate, bytes, worker->time_ms); if (written > 30000) break; } return 0; }
int format_file_read (client_t *client, format_plugin_t *plugin, icefile_handle f) { refbuf_t *refbuf = client->refbuf; ssize_t bytes = -1; int unprocessed = 0; do { if (refbuf == NULL) { if (file_in_use (f) == 0) return -2; refbuf = client->refbuf = refbuf_new (8192); client->flags |= CLIENT_HAS_INTRO_CONTENT; client->pos = refbuf->len; client->queue_pos = 0; refbuf->flags |= BUFFER_LOCAL_USE; } if (client->pos < refbuf->len) break; if (refbuf->next) { //DEBUG1 ("next intro block is %d", refbuf->next->len); client->refbuf = refbuf->next; refbuf->next = NULL; refbuf_release (refbuf); client->pos = 0; return 0; } if ((refbuf->flags & BUFFER_LOCAL_USE) == 0) { client_set_queue (client, NULL); refbuf = NULL; continue; } if (file_in_use (f) == 0) return -2; bytes = pread (f, refbuf->data, 8192, client->intro_offset); if (bytes <= 0) return bytes < 0 ? -2 : -1; if (client->connection.sent_bytes > 0 && client->intro_offset == 0 && bytes >= 10 && memcmp (refbuf->data, "ID3", 3) == 0) { // special case of filtering ID3 from fallback files unsigned char *p = (unsigned char*)refbuf->data; if (p[3] < 0xFF && p[4] < 0xFF && (p[5] & 0xF) == 0) { int ver = p[3], rev = p[4]; size_t size = (p[6] & 0x7f); size = (size << 7) + (p[7] & 0x7f); size = (size << 7) + (p[8] & 0x7f); size = (size << 7) + (p[9] & 0x7f); client->intro_offset = size + 10; DEBUG3 ("Detected ID3v2 (%d.%d) in file, tag size %" PRIu64, ver, rev, (uint64_t)size); continue; } } refbuf->len = bytes; client->pos = 0; if (plugin && plugin->align_buffer) { /* here the buffer may require truncating to keep the buffers aligned on * certain boundaries */ unprocessed = plugin->align_buffer (client, plugin); if (unprocessed == bytes) return -1; if (unprocessed < 0 || unprocessed > bytes) { unprocessed = 0; client->connection.error = 1; } } client->intro_offset += (bytes - unprocessed); } while (1); return refbuf->len - client->pos; }