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; }
/* send routine for files sent at a target bitrate, eg fallback files. */ static int throttled_file_send (client_t *client) { int bytes; fh_node *fh = client->shared_data; time_t now; worker_t *worker = client->worker; unsigned long secs; unsigned int rate = 0; unsigned int limit = fh->finfo.limit; if (fserve_running == 0 || client->connection.error) return -1; now = worker->current_time.tv_sec; secs = now - client->timer_start; client->schedule_ms = worker->time_ms; if (fh->finfo.fallback) return fserve_move_listener (client); if (fserve_change_worker (client)) // allow for balancing return 1; if (client->flags & CLIENT_WANTS_FLV) /* increase limit for flv clients as wrapping takes more space */ limit = (unsigned long)(limit * 1.01); rate = secs ? (client->counter+1400)/secs : limit * 2; // DEBUG3 ("counter %lld, duration %ld, limit %u", client->counter, secs, rate); if (rate > limit) { if (limit >= 1400) client->schedule_ms += 1000/(limit/1400); else client->schedule_ms += 50; // should not happen but guard against it rate_add (fh->out_bitrate, 0, worker->time_ms); global_add_bitrates (global.out_bitrate, 0, worker->time_ms); if (client->counter > 8192) return 0; // allow an initial amount without throttling } switch (format_file_read (client, fh->format, fh->f)) { case -1: // DEBUG0 ("loop of file triggered"); client->intro_offset = 0; client->schedule_ms += client->throttle ? client->throttle : 150; return 0; case -2: // DEBUG0 ("major failure on read, better leave"); return -1; default: //DEBUG1 ("reading from offset %ld", client->intro_offset); break; } bytes = client->check_buffer (client); if (bytes < 0) bytes = 0; //DEBUG3 ("bytes %d, counter %ld, %ld", bytes, client->counter, client->worker->time_ms - (client->timer_start*1000)); rate_add (fh->out_bitrate, bytes, worker->time_ms); global_add_bitrates (global.out_bitrate, bytes, worker->time_ms); if (limit > 2800) client->schedule_ms += (1000/(limit/1400*2)); else client->schedule_ms += 50; /* progessive slowdown if max bandwidth is exceeded. */ if (throttle_sends > 1) client->schedule_ms += 300; return 0; }