/* * Reconnect to server after a timeout, reissue last command to * get us back into the pre-timeout state */ static int reconnect( int retry) { char buf[NNTP_STRLEN]; /* * Tear down current connection */ NNTP_HARD_CLOSE; if (!tinrc.auto_reconnect) ring_bell(); DEBUG_IO((stderr, _("\nServer timed out, trying reconnect # %d\n"), retry)); /* * Exit tin if the user says no to reconnect. The exit code stops tin from trying * to disconnect again - the connection is already dead */ if (!tinrc.auto_reconnect && prompt_yn(cLINES, _(txt_reconnect_to_news_server), TRUE) != 1) tin_done(NNTP_ERROR_EXIT); /* user said no to reconnect */ clear_message(); strcpy(buf, last_put); /* Keep copy here, it will be clobbered a lot otherwise */ if (!nntp_open()) { /* * Re-establish our current group and resend last command */ if (curr_group != NULL) { DEBUG_IO((stderr, _("Rejoin current group\n"))); sprintf(last_put, "GROUP %s", curr_group->name); put_server(last_put); s_gets(last_put, NNTP_STRLEN, nntp_rd_fp); # ifdef DEBUG debug_nntp("<<<", last_put); # endif /* DEBUG */ DEBUG_IO((stderr, _("Read (%s)\n"), last_put)); } DEBUG_IO((stderr, _("Resend last command (%s)\n"), buf)); put_server(buf); return 0; } if (--retry == 0) /* No more tries? */ tin_done(NNTP_ERROR_EXIT); return retry; }
static unsigned buffer_write(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, unsigned bit_count) { DEBUG_IO("%d bits", bit_count); assert(ctx->write_count + DIV_ROUND_UP(bit_count, 8) <= ctx->write_size); bit_copy(ctx->write_buffer + ctx->write_count, 0, out, out_offset, bit_count); ctx->write_count += DIV_ROUND_UP(bit_count, 8); return bit_count; }
static unsigned buffer_add_read(struct mpsse_ctx *ctx, uint8_t *in, unsigned in_offset, unsigned bit_count, unsigned offset) { DEBUG_IO("%d bits, offset %d", bit_count, offset); assert(ctx->read_count + DIV_ROUND_UP(bit_count, 8) <= ctx->read_size); bit_copy_queued(&ctx->read_queue, in, in_offset, ctx->read_buffer + ctx->read_count, offset, bit_count); ctx->read_count += DIV_ROUND_UP(bit_count, 8); return bit_count; }
/* * Send 'string' to the NNTP server, terminating it with CR and LF, as per * ARPA standard. * * Returns: Nothing. * * Side effects: Talks to the server. * Closes connection if things are not right. * * Note: This routine flushes the buffer each time it is called. For large * transmissions (i.e., posting news) don't use it. Instead, do the * fprintf's yourself, and then a final fflush. * Only cache commands, don't cache data transmissions. * */ void put_server( const char *string) { if (*string && strlen(string)) { DEBUG_IO((stderr, "put_server(%s)\n", string)); s_puts(string, nntp_wr_fp); s_puts("\r\n", nntp_wr_fp); # ifdef DEBUG debug_nntp(">>>", string); # endif /* DEBUG */ /* * remember the last command we wrote to be able to resend it after a * reconnect. reconnection is handled by get_server() */ strcpy(last_put, string); } (void) s_flush(nntp_wr_fp); }
void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in, unsigned in_offset, unsigned length, uint8_t mode) { /* TODO: Fix MSB first modes */ DEBUG_IO("%s%s %d bits", in ? "in" : "", out ? "out" : "", length); if (ctx->retval != ERROR_OK) { DEBUG_IO("Ignoring command due to previous error"); return; } /* TODO: On H chips, use command 0x8E/0x8F if in and out are both 0 */ if (out || (!out && !in)) mode |= 0x10; if (in) mode |= 0x20; while (length > 0) { /* Guarantee buffer space enough for a minimum size transfer */ if (buffer_write_space(ctx) + (length < 8) < (out || (!out && !in) ? 4 : 3) || (in && buffer_read_space(ctx) < 1)) ctx->retval = mpsse_flush(ctx); if (length < 8) { /* Transfer remaining bits in bit mode */ buffer_write_byte(ctx, 0x02 | mode); buffer_write_byte(ctx, length - 1); if (out) out_offset += buffer_write(ctx, out, out_offset, length); if (in) in_offset += buffer_add_read(ctx, in, in_offset, length, 8 - length); if (!out && !in) buffer_write_byte(ctx, 0x00); length = 0; } else { /* Byte transfer */ unsigned this_bytes = length / 8; /* MPSSE command limit */ if (this_bytes > 65536) this_bytes = 65536; /* Buffer space limit. We already made sure there's space for the minimum * transfer. */ if ((out || (!out && !in)) && this_bytes + 3 > buffer_write_space(ctx)) this_bytes = buffer_write_space(ctx) - 3; if (in && this_bytes > buffer_read_space(ctx)) this_bytes = buffer_read_space(ctx); if (this_bytes > 0) { buffer_write_byte(ctx, mode); buffer_write_byte(ctx, (this_bytes - 1) & 0xff); buffer_write_byte(ctx, (this_bytes - 1) >> 8); if (out) out_offset += buffer_write(ctx, out, out_offset, this_bytes * 8); if (in) in_offset += buffer_add_read(ctx, in, in_offset, this_bytes * 8, 0); if (!out && !in) for (unsigned n = 0; n < this_bytes; n++) buffer_write_byte(ctx, 0x00); length -= this_bytes * 8; } } }
static void buffer_write_byte(struct mpsse_ctx *ctx, uint8_t data) { DEBUG_IO("%02x", data); assert(ctx->write_count < ctx->write_size); ctx->write_buffer[ctx->write_count++] = data; }