static int play_cmd(void) { struct player *other; natid cnum; struct natstr *natp; char **ap; char buf[128]; ap = player->argp; if (*++ap) { strncpy(player->userid, *ap, sizeof(player->userid) - 1); player->userid[sizeof(player->userid) - 1] = '\0'; player->authenticated = 0; } if (*++ap) { if (natbyname(*ap, &cnum) < 0) { pr_id(player, C_CMDERR, "country %s does not exist\n", *ap); return RET_FAIL; } } if (*++ap) { if (!natpass(cnum, *ap)) { pr_id(player, C_CMDERR, "password bad, logging entry\n"); logerror("%s tried country #%d with %s", praddr(player), cnum, *ap); return RET_FAIL; } player->cnum = cnum; player->authenticated = 1; } if (!may_play()) return RET_FAIL; other = getplayer(player->cnum); if (other) { natp = getnatp(player->cnum); if (natp->nat_stat != STAT_VIS) { pr_id(player, C_EXIT, "country in use by %s\n", praddr(other)); } else { pr_id(player, C_EXIT, "country in use\n"); } return RET_FAIL; } snprintf(buf, sizeof(buf), "Play#%d", player->cnum); logerror("%s logged in as country #%d", praddr(player), player->cnum); journal_login(); empth_set_name(empth_self(), buf); pr_id(player, C_INIT, "%d\n", CLIENTPROTO); empth_rwlock_rdlock(shutdown_lock); player->state = PS_PLAYING; player_main(player); journal_logout(); logerror("%s logged out, country #%d", praddr(player), player->cnum); if (!io_eof(player->iop) && !io_error(player->iop)) io_set_eof(player->iop); return RET_OK; }
static int count_time (struct spx_data *data) { unsigned long last_granulepos = 0; /* Seek to somewhere neer the last page */ if (io_file_size(data->stream) > 10000) { debug ("Seeking near the end"); if (io_seek(data->stream, -10000, SEEK_END) == -1) logit ("Seeking failed, scaning whole file"); ogg_sync_reset (&data->oy); } /* Read granulepos from the last packet */ while (!io_eof(data->stream)) { /* Sync to page and read it */ while (!io_eof(data->stream)) { char *buf; int nb_read; if (ogg_sync_pageout(&data->oy, &data->og) == 1) { debug ("Sync"); break; } else if (!io_eof(data->stream)) { debug ("Need more data"); buf = ogg_sync_buffer (&data->oy, 200); nb_read = io_read (data->stream, buf, 200); ogg_sync_wrote (&data->oy, nb_read); } } /* We have last packet */ if (io_eof(data->stream)) break; last_granulepos = ogg_page_granulepos (&data->og); } return last_granulepos / data->rate; }
static int count_time (struct spx_data *data) { ogg_int64_t last_granulepos = 0; /* Seek to somewhere near the last page */ if (io_file_size(data->stream) > 10000) { debug ("Seeking near the end"); if (io_seek(data->stream, -10000, SEEK_END) == -1) logit ("Seeking failed, scanning whole file"); ogg_sync_reset (&data->oy); } /* Read granulepos from the last packet */ while (!io_eof(data->stream)) { /* Sync to page and read it */ while (!io_eof(data->stream)) { if (ogg_sync_pageout(&data->oy, &data->og) == 1) { debug ("Sync"); break; } if (!io_eof(data->stream)) { debug ("Need more data"); get_more_data (data); } } /* We have last packet */ if (io_eof(data->stream)) break; last_granulepos = ogg_page_granulepos (&data->og); } return last_granulepos / data->rate; }
/* * Receive a line of input from the current player. * If the player's aborted flag is set, return -1 without receiving * input. * Else receive one line and store it in CMD[SIZE]. * This may block for input, yielding the processor. Flush buffered * output when blocking, to make sure player sees the prompt. * If the player's connection has the I/O error or EOF indicator set, * or the line is "aborted", set the player's aborted flag and return * -1. * If we block and time out, set the EOF indicator on the player's * connection, set the player's aborted flag, and return -1. * If the line is "ctld", set the player's eof and aborted flag and * return -1. * Else return the length of the line. * Design bug: there is no way to indicate truncation of a long line. */ int recvclient(char *cmd, int size) { int count, res; time_t deadline; count = -1; while (!player->aborted) { /* Try to get a line of input */ count = io_gets(player->iop, cmd, size); if (count >= 0) { /* got it */ if (strcmp(cmd, "ctld") == 0) player->aborted = player->got_ctld = 1; if (strcmp(cmd, "aborted") == 0) player->aborted = 1; journal_input(cmd); break; } /* * Flush all queued output before potentially sleeping in * io_input(), to make sure player sees the prompt. */ deadline = player_io_deadline(player, 0); while (io_output(player->iop, deadline) > 0) ; /* * Try to receive some input. Need to recompute deadline; * command abortion during io_output() might have changed it. */ deadline = player_io_deadline(player, 0); res = io_input(player->iop, deadline); if (res > 0) ; else if (res < 0) player->aborted = 1; else if (io_eof(player->iop)) player->aborted = 1; else if (!player->aborted) { pr_flash(player, "idle connection terminated\n"); io_set_eof(player->iop); player->aborted = 1; } } if (player->aborted) { player->recvfail++; if (player->recvfail > 255) { /* * Looks like the thread is stuck in a loop that fails to * check errors; oops once, then slow it down drastically. */ CANT_HAPPEN(player->recvfail == 256); empth_sleep(time(NULL) + 60); } return -1; } player->recvfail = 0; return count; }
/* * Execute command named by player->argp[0]. * BUF is the raw UTF-8 command line. It should have been passed to * parse() to set up player->argp. * If REDIR is not null, it's the command's redirection, in UTF-8. * Return -1 if the command is not unique or doesn't exist, else 0. */ int dispatch(char *buf, char *redir) { struct natstr *np; struct cmndstr *command; int cmd; cmd = comtch(player->argp[0], player_coms, player->nstat); if (cmd < 0) { if (cmd == M_NOTUNIQUE) pr("Command \"%s\" is ambiguous -- ", player->argp[0]); else if (cmd == M_IGNORE) return 0; else pr("\"%s\" is not a legal command\n", player->argp[0]); return -1; } command = &player_coms[cmd]; np = getnatp(player->cnum); if (np->nat_btu < command->c_cost && command->c_cost > 0) { if (player->god || opt_BLITZ) np->nat_btu = max_btus; else { pr("You don't have the BTU's, bozo\n"); return 0; } } if (!command->c_addr) { pr("Command not implemented\n"); return 0; } player->may_sleep = command->c_flags & C_MOD ? PLAYER_SLEEP_ON_INPUT : PLAYER_SLEEP_FREELY; player->command = command; empth_rwlock_rdlock(update_lock); if (redir) { prredir(redir); uprnf(buf); pr("\n"); } journal_command(command->c_form); switch (command->c_addr()) { case RET_OK: player->btused += command->c_cost; break; case RET_FAIL: pr("command failed\n"); player->btused += command->c_cost; break; case RET_SYN: pr("Usage: %s\n", command->c_form); break; default: CANT_REACH(); break; } empth_rwlock_unlock(update_lock); player->command = NULL; if (player->may_sleep != PLAYER_SLEEP_NEVER || !io_eof(player->iop)) player->may_sleep = PLAYER_SLEEP_FREELY; /* else we're being kicked out */ return 0; }
static bool io_get_line(struct io *io, struct buffer *buf, int c, size_t *lineno, bool can_read) { char *eol; ssize_t readsize; while (TRUE) { if (io->bufsize > 0) { eol = memchr(io->bufpos, c, io->bufsize); while (io->span && io->bufpos < eol && eol[-1] == '\\') { if (lineno) (*lineno)++; eol[-1] = eol[0] = ' '; eol = memchr(io->bufpos, c, io->bufsize); } if (eol) { buf->data = io->bufpos; buf->size = eol - buf->data; *eol = 0; io->bufpos = eol + 1; io->bufsize -= io->bufpos - buf->data; if (lineno) (*lineno)++; return TRUE; } } if (io_eof(io)) { if (io->bufsize) { buf->data = io->bufpos; buf->size = io->bufsize; io->bufpos[io->bufsize] = 0; io->bufpos += io->bufsize; io->bufsize = 0; if (lineno) (*lineno)++; return TRUE; } return FALSE; } if (!can_read) return FALSE; if (io->bufsize > 0 && io->bufpos > io->buf) memmove(io->buf, io->bufpos, io->bufsize); if (io->bufalloc == io->bufsize) { if (!io_realloc_buf(&io->buf, io->bufalloc, BUFSIZ)) return FALSE; io->bufalloc += BUFSIZ; } io->bufpos = io->buf; readsize = io_read(io, io->buf + io->bufsize, io->bufalloc - io->bufsize); if (io_error(io)) return NULL; io->bufsize += readsize; } }
static bool unclosable_eof(void* _self) { UnclosableInput* self = _self; return io_eof(self->wrap); }
static bool limited_eof(void* _self) { LimitedInput* self = _self; return (self->read == self->limit) || io_eof(self->in); }
static int spx_decode (void *prv_data, char *sound_buf, int nbytes, struct sound_params *sound_params) { struct spx_data *data = (struct spx_data *)prv_data; int bytes_requested = nbytes; int16_t *out = (int16_t *)sound_buf; sound_params->channels = data->nchannels; sound_params->rate = data->rate; sound_params->fmt = SFMT_S16 | SFMT_NE; while (nbytes) { int j; /* First see if there is anything left in the output buffer and * empty it out */ if (data->output_left > 0) { int to_copy = nbytes / sizeof(int16_t); to_copy = MIN(data->output_left, to_copy); memcpy (out, data->output + data->output_start, to_copy * sizeof(int16_t)); out += to_copy; data->output_start += to_copy; data->output_left -= to_copy; nbytes -= to_copy * sizeof(int16_t); } else if (ogg_stream_packetout (&data->os, &data->op) == 1) { int16_t *temp_output = data->output; /* Decode some more samples */ /* Copy Ogg packet to Speex bitstream */ speex_bits_read_from (&data->bits, (char*)data->op.packet, data->op.bytes); for (j = 0; j < data->frames_per_packet; j++) { /* Decode frame */ speex_decode_int (data->st, &data->bits, temp_output); if (data->nchannels == 2) speex_decode_stereo_int (temp_output, data->frame_size, &data->stereo); speex_decoder_ctl (data->st, SPEEX_GET_BITRATE, &data->bitrate); /*data->samples_decoded += data->frame_size;*/ temp_output += data->frame_size * data->nchannels; } /*logit ("Read %d bytes from page", data->frame_size * data->nchannels * data->frames_per_packet);*/ data->output_start = 0; data->output_left = data->frame_size * data->nchannels * data->frames_per_packet; } else if (ogg_sync_pageout(&data->oy, &data->og) == 1) { /* Read in another ogg page */ ogg_stream_pagein (&data->os, &data->og); debug ("Granulepos: %"PRId64, ogg_page_granulepos(&data->og)); } else if (!io_eof(data->stream)) { /* Finally, pull in some more data and try again on the next pass */ get_more_data (data); } else break; } return bytes_requested - nbytes; }
static int spx_seek (void *prv_data, int sec) { struct spx_data *data = (struct spx_data *)prv_data; off_t begin = 0, end, old_pos; assert (sec >= 0); end = io_file_size (data->stream); if (end == -1) return -1; old_pos = io_tell (data->stream); debug ("Seek request to %ds", sec); while (1) { off_t middle = (end + begin) / 2; ogg_int64_t granule_pos; int position_seconds; debug ("Seek to %"PRId64, middle); if (io_seek(data->stream, middle, SEEK_SET) == -1) { io_seek (data->stream, old_pos, SEEK_SET); ogg_stream_reset (&data->os); ogg_sync_reset (&data->oy); return -1; } debug ("Syncing..."); /* Sync to page and read it */ ogg_sync_reset (&data->oy); while (!io_eof(data->stream)) { if (ogg_sync_pageout(&data->oy, &data->og) == 1) { debug ("Sync"); break; } if (!io_eof(data->stream)) { debug ("Need more data"); get_more_data (data); } } if (io_eof(data->stream)) { debug ("EOF when syncing"); return -1; } granule_pos = ogg_page_granulepos(&data->og); position_seconds = granule_pos / data->rate; debug ("We are at %ds", position_seconds); if (position_seconds == sec) { ogg_stream_pagein (&data->os, &data->og); debug ("We have it at granulepos %"PRId64, granule_pos); break; } else if (sec < position_seconds) { end = middle; debug ("going back"); } else { begin = middle; debug ("going forward"); } debug ("begin - end %"PRId64" - %"PRId64, begin, end); if (end - begin <= 200) { /* Can't find the exact position. */ sec = position_seconds; break; } } ogg_sync_reset (&data->oy); ogg_stream_reset (&data->os); return sec; }