/* call to check the buffer contents for file reading. move the client * to right place in the queue at end of file else repeat file if queue * is not ready yet. */ int format_check_file_buffer (source_t *source, client_t *client) { refbuf_t *refbuf = client->refbuf; if (refbuf == NULL) { /* client refers to no data, must be from a move */ if (source->client->con) { find_client_start (source, client); return -1; } /* source -> file fallback, need a refbuf for data */ refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE); client->refbuf = refbuf; client->pos = refbuf->len; client->intro_offset = 0; } if (client->pos == refbuf->len) { if (get_file_data (source->intro_file, client)) { client->pos = 0; client->intro_offset += refbuf->len; } else { if (source->stream_data_tail) { /* better find the right place in queue for this client */ client_set_queue (client, NULL); find_client_start (source, client); } else client->intro_offset = 0; /* replay intro file */ return -1; } } return 0; }
/* general send routine per listener. The deletion_expected tells us whether * the last in the queue is about to disappear, so if this client is still * referring to it after writing then drop the client as it's fallen too far * behind */ static void send_to_listener (source_t *source, client_t *client, int deletion_expected) { int bytes; int loop = 10; /* max number of iterations in one go */ int total_written = 0; /* new users need somewhere to start from */ if (client->refbuf == NULL) { find_client_start (source, client); if (client->refbuf == NULL) return; } while (1) { /* jump out if client connection has died */ if (client->con->error) break; /* lets not send too much to one client in one go, but don't sleep for too long if more data can be sent */ if (total_written > 20000 || loop == 0) { source->short_delay = 1; break; } loop--; bytes = source->format->write_buf_to_client (source->format, client); if (bytes <= 0) break; /* can't write any more */ total_written += bytes; } /* the refbuf referenced at head (last in queue) may be marked for deletion * if so, check to see if this client is still referring to it */ if (deletion_expected && client->refbuf == source->stream_data) { DEBUG0("Client has fallen too far behind, removing"); client->con->error = 1; } }