/* fast send routine */ static int file_send (client_t *client) { int loop = 6, bytes, written = 0; fh_node *fh = client->shared_data; worker_t *worker = client->worker; time_t now; if (fserve_change_worker (client)) // allow for balancing return 1; client->schedule_ms = worker->time_ms; now = worker->current_time.tv_sec; /* slowdown if max bandwidth is exceeded, but allow for short-lived connections to avoid * this, eg admin requests */ if (throttle_sends > 1 && now - client->connection.con_time > 1) { client->schedule_ms += 300; loop = 1; } while (loop && written < 30000) { loop--; if (fserve_running == 0 || client->connection.error) return -1; if (client->connection.discon_time && now >= client->connection.discon_time) return -1; if (format_file_read (client, fh->format, fh->f) < 0) return -1; bytes = client->check_buffer (client); if (bytes < 0) { client->schedule_ms += (written ? 120 : 250); break; } written += bytes; client->schedule_ms += 3; } 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; }