Implement binkp/1.1 and Turn on FREQ at binkp.

master
Sergey Babitch 17 years ago
parent a148609494
commit fd35c10c4e

@ -49,4 +49,6 @@
+ Changed version for compliance with *BSD ports
+ Added possibility to run external program for each override and
hidden. See bforce.subst.sample for examples and
docs/readme.txt for details
docs/readme.txt for details.
+ Implement binkp/1.1 (Multiple Batch Mode and Non-reliable Mode).
+ Turn on FREQ at binkp sessions.

@ -12,6 +12,9 @@
#
# To use BinkP protocol, write:
# Override 1:2/3 Ipaddr f3.n2.z1.fidonet.net Flags CM,BINKP
# Override 1:2/4 Ipaddr f4.n2.z1.fidonet.net Flags CM,BINKP,NR
#
# NR - for binkp NR mode request (Not Reliable Links).
#
# If you want never call to certain node, write:
# Override 1:2/3 Phone Unpublished

@ -83,6 +83,9 @@ void binkp_process_NUL(s_binkp_sysinfo *remote_data, char *buffer)
&remote_data->majorver,
&remote_data->minorver);
}
if ((remote_data->majorver * 100 +
remote_data->minorver)> 100)
remote_data->options |= BINKP_OPT_MB;
}
else
strnxcpy(remote_data->progname, buffer+4, sizeof(remote_data->progname));
@ -210,12 +213,9 @@ int binkp_outgoing(s_binkp_sysinfo *local_data, s_binkp_sysinfo *remote_data)
break;
case BPMSG_NUL:
if( binkp_state == BPO_WaitNUL || binkp_state == BPO_WaitADR )
{
binkp_process_NUL(remote_data, bpi.ibuf+1);
if( binkp_state == BPO_WaitNUL )
binkp_state = BPO_SendPWD;
}
binkp_process_NUL(remote_data, bpi.ibuf+1);
if( binkp_state == BPO_WaitNUL )
binkp_state = BPO_SendPWD;
break;
case BPMSG_ADR:
@ -347,14 +347,28 @@ int binkp_incoming(s_binkp_sysinfo *local_data, s_binkp_sysinfo *remote_data)
break;
case BPMSG_NUL:
if( binkp_state == BPI_WaitADR )
binkp_process_NUL(remote_data, bpi.ibuf+1);
binkp_process_NUL(remote_data, bpi.ibuf+1);
break;
case BPMSG_ADR:
if( binkp_state == BPI_WaitADR )
{
int i;
char *szOpt = xstrcpy (" MB");
s_override ovr;
binkp_process_ADR(remote_data, bpi.ibuf+1);
for(i = 0; i < remote_data->anum; i++)
{
ovr.sFlags = "";
override_get (&ovr, remote_data->addrs[i].addr, 0);
if (!nodelist_checkflag (ovr.sFlags, "NR"))
{
szOpt = xstrcat (szOpt, " NR");
break;
}
}
binkp_queuemsg(&bpi,BPMSG_NUL,"OPT",szOpt);
free (szOpt);
binkp_state = BPI_WaitPWD;
}
break;
@ -387,17 +401,13 @@ Abort:
return rc;
}
int binkp_transfer(s_protinfo *pi)
{
int binkp_transfer(s_protinfo *pi) {
int i, n, rc = PRC_NOERROR;
bool recv_ready = FALSE;
bool send_ready = FALSE;
bool sent_EOB = FALSE;
bool rcvd_EOB = FALSE;
bool send_file = FALSE;
bool recv_file = FALSE;
bool wait_got = FALSE;
bool nofiles = FALSE;
int recv_rc = 0;
int send_rc = 0;
char *fname = NULL;
@ -405,52 +415,71 @@ int binkp_transfer(s_protinfo *pi)
time_t ftime = 0;
size_t foffs = 0;
s_bpinfo bpi;
binkp_init_bpinfo(&bpi);
while( !sent_EOB || !rcvd_EOB )
{
if( !send_file && !sent_EOB && bpi.opos == 0 && bpi.n_msgs == 0 )
{
if( !p_tx_fopen(pi) )
{
send_file = TRUE;
binkp_queuemsgf(&bpi, BPMSG_FILE, "%s %ld %ld 0",
pi->send->net_name, (long)pi->send->bytes_total,
(long)pi->send->mod_time);
}
else
/* No more files */
nofiles = TRUE;
}
if( send_file && bpi.opos == 0 && bpi.n_msgs == 0 )
{
if( (n = p_tx_readfile(bpi.obuf + BINKP_BLK_HDRSIZE,
4096, pi)) < 0 )
{
p_tx_fclose(pi);
send_file = FALSE;
}
else
{
binkp_puthdr(bpi.obuf, (unsigned)(n & 0x7fff));
bpi.opos = n + BINKP_BLK_HDRSIZE;
pi->send->bytes_sent += n;
if( pi->send->eofseen )
{
wait_got = TRUE; send_file = FALSE;
pi->send->status = FSTAT_WAITACK;
}
}
}
if( nofiles && !wait_got && !sent_EOB )
{
sent_EOB = TRUE;
binkp_queuemsg(&bpi, BPMSG_EOB, NULL, NULL);
}
s_binkp_sysinfo *remote;
enum {
BPT_Start_Send_File,
BPT_Wait_M_GET,
BPT_Send_File,
BPT_Wait_M_GOT,
BPT_No_Files,
BPT_EOB
} binkp_send_state = BPT_Start_Send_File;
remote = (s_binkp_sysinfo *) state.handshake->remote_data;
binkp_init_bpinfo(&bpi);
while (1) {
if (binkp_send_state == BPT_Start_Send_File) {
if (p_tx_fopen (pi)) {
binkp_send_state = BPT_No_Files;
} else {
char *name = pi->send->net_name;
long total = (long) pi->send->bytes_total;
long time = (long) pi->send->mod_time;
if (remote->options & BINKP_OPT_NR) {
binkp_queuemsgf(&bpi,BPMSG_FILE,"%s %ld %ld -1",name,total,time);
binkp_send_state = BPT_Wait_M_GET;
} else {
binkp_queuemsgf(&bpi,BPMSG_FILE,"%s %ld %ld 0", name,total,time);
binkp_send_state = BPT_Send_File;
}
}
}
if (binkp_send_state == BPT_Send_File) {
if (bpi.opos == 0 && bpi.n_msgs == 0) {
if((n = p_tx_readfile (bpi.obuf+BINKP_BLK_HDRSIZE,4096,pi))<0) {
p_tx_fclose (pi);
binkp_send_state = BPT_Start_Send_File;
} else {
binkp_puthdr (bpi.obuf, (unsigned) (n & 0x7fff));
bpi.opos = n + BINKP_BLK_HDRSIZE;
pi->send->bytes_sent += n;
if (pi->send->eofseen) {
pi->send->status = FSTAT_WAITACK;
if (remote->options & BINKP_OPT_NR)
binkp_send_state = BPT_Wait_M_GOT;
else binkp_send_state = BPT_Start_Send_File;
}
}
}
}
if (binkp_send_state == BPT_No_Files) {
for (i = 0; i < pi->n_sentfiles; i++) {
if (pi->sentfiles[i].status == FSTAT_WAITACK) break;
}
if (i == pi->n_sentfiles) {
binkp_queuemsg (&bpi, BPMSG_EOB, NULL, NULL);
binkp_send_state = BPT_EOB;
}
}
/* End of the current batch (start the next batch if need). */
if (binkp_send_state == BPT_EOB && rcvd_EOB) {
if (remote->options & BINKP_OPT_MB && bpi.msgs_in_batch > 2) {
bpi.msgs_in_batch = 0;
binkp_send_state = BPT_Start_Send_File;
rcvd_EOB = FALSE;
continue;
}
break;
}
recv_ready = send_ready = FALSE;
if( tty_select(&recv_ready, (bpi.opos || bpi.n_msgs) ?
&send_ready : NULL, bpi.timeout) < 0 )
@ -464,8 +493,8 @@ int binkp_transfer(s_protinfo *pi)
if( send_ready && (send_rc = binkp_send(&bpi)) < 0 )
gotoexit(PRC_ERROR);
switch(recv_rc) {
case BPMSG_NONE:
switch(recv_rc) {
case BPMSG_NONE:
break;
case BPMSG_DATA: /* Got new data block */
if( recv_file )
@ -533,26 +562,29 @@ int binkp_transfer(s_protinfo *pi)
break;
case BPMSG_FILE:
if( recv_file )
{ p_rx_fclose(pi); recv_file = FALSE; }
if( binkp_parsfinfo(bpi.ibuf+1, &fname,
&fsize, &ftime, &foffs) )
{
log ("BinkP error: M_FILE: %s", bpi.ibuf + 1);
binkp_queuemsg(&bpi, BPMSG_ERR, "FILE: ", "unparsable arguments");
goto FinishSession;
}
if( pi->recv && !p_compfinfo(pi->recv, fname, fsize, ftime)
&& pi->recv->bytes_skipped == foffs )
&& pi->recv->bytes_skipped == foffs && pi->recv->fp )
{
recv_file = TRUE;
break;
}
if (recv_file) {
p_rx_fclose (pi);
recv_file = FALSE;
}
switch(p_rx_fopen(pi, fname, fsize, ftime, 0)) {
case 0:
if( pi->recv->bytes_skipped == 0 )
if (pi->recv->bytes_skipped == foffs)
{
recv_file = TRUE;
break;
@ -588,58 +620,43 @@ int binkp_transfer(s_protinfo *pi)
rcvd_EOB = TRUE;
break;
case BPMSG_GOT:
case BPMSG_SKIP:
if( binkp_parsfinfo(bpi.ibuf+1, &fname, &fsize, &ftime, NULL) == 0 )
{
if( send_file && !p_compfinfo(pi->send, fname, fsize, ftime) )
{
/* We got GOT/SKIP for current file! */
if( recv_rc == BPMSG_GOT )
pi->send->status = FSTAT_SKIPPED;
else
pi->send->status = FSTAT_REFUSED;
p_tx_fclose(pi);
send_file = FALSE;
break;
}
wait_got = FALSE;
for( i = 0; i < pi->n_sentfiles; i++ )
{
if( pi->sentfiles[i].status == FSTAT_WAITACK
&& !p_compfinfo(&pi->sentfiles[i], fname, fsize, ftime) )
{
s_finfo *tmp = pi->send;
pi->send = &pi->sentfiles[i];
if( recv_rc == BPMSG_GOT )
pi->send->status = FSTAT_SUCCESS;
else
pi->send->status = FSTAT_REFUSED;
p_tx_fclose(pi);
pi->send = tmp;
break;
}
else if( pi->sentfiles[i].status == FSTAT_WAITACK )
wait_got = TRUE;
}
case BPMSG_GOT:
case BPMSG_SKIP:
if (binkp_parsfinfo (bpi.ibuf+1,&fname,&fsize,&ftime,NULL)) {
char *m = recv_rc == BPMSG_GOT ? "M_GOT" : "M_SKIP";
binkp_queuemsgf (&bpi, BPMSG_ERR, "%s: %s", m, bpi.ibuf + 1);
log ("BinkP error: %s: %s", m, bpi.ibuf + 1);
binkp_send_state = BPT_No_Files;
rc = PRC_ERROR;
break;
}
for(i = 0; i < pi->n_sentfiles; i++ ) {
if (!p_compfinfo (&pi->sentfiles[i], fname, fsize, ftime)) {
s_finfo *tmp = pi->send;
pi->send = &pi->sentfiles[i];
if (recv_rc == BPMSG_SKIP) {
pi->send->status = FSTAT_REFUSED;
} else {
if (pi->send->status == FSTAT_WAITACK) {
pi->send->status = FSTAT_SUCCESS;
} else {
pi->send->status = FSTAT_SKIPPED;
}
}
p_tx_fclose(pi);
pi->send = tmp;
break;
}
}
if (!strcmp (pi->send->net_name, fname)) {
if (binkp_send_state == BPT_Send_File ||
binkp_send_state == BPT_Wait_M_GET ||
binkp_send_state == BPT_Wait_M_GOT) {
binkp_send_state = BPT_Start_Send_File;
}
}
break;
/*
* Check, maybe there are files still
* waiting for the GOT/SKIP acknwoledge
*/
while( i < pi->n_sentfiles && !wait_got )
{
if( pi->sentfiles[i].status == FSTAT_WAITACK )
wait_got = TRUE;
++i;
}
}
break;
case BPMSG_ERR:
log("remote report error: \"%s\"", bpi.ibuf+1);
gotoexit(PRC_ERROR);
@ -653,13 +670,13 @@ int binkp_transfer(s_protinfo *pi)
case BPMSG_GET:
if( binkp_parsfinfo(bpi.ibuf+1, &fname, &fsize, &ftime, &foffs) == 0 )
{
if( send_file && !p_compfinfo(pi->send, fname, fsize, ftime) )
if(!p_compfinfo(pi->send,fname,fsize,ftime))
{
if( fseek(pi->send->fp, foffs, SEEK_SET) == -1 )
{
log("cannot send file from requested offset %ld", (long)foffs);
p_tx_fclose(pi);
send_file = FALSE;
binkp_send_state = BPT_Start_Send_File;
}
else
{
@ -670,6 +687,7 @@ int binkp_transfer(s_protinfo *pi)
binkp_queuemsgf(&bpi, BPMSG_FILE, "%s %ld %ld %ld",
pi->send->net_name, (long)pi->send->bytes_total,
(long)pi->send->mod_time, (long)foffs);
binkp_send_state = BPT_Send_File;
}
}
}

@ -117,6 +117,7 @@ int binkp_incoming2(s_handshake_protocol *THIS)
{
session_remote_lookup(remote_data->addrs, remote_data->anum);
session_remote_log_status();
binkp_log_options(remote_data);
}
if( rc == HRC_OK )
@ -128,6 +129,7 @@ int binkp_incoming2(s_handshake_protocol *THIS)
remote_data->anum);
session_set_send_options();
session_set_inbound();
session_set_freqs_status();
}
return rc;
@ -145,6 +147,8 @@ int binkp_outgoing2(s_handshake_protocol *THIS)
remote_data = (s_binkp_sysinfo *)THIS->remote_data;
local_data = (s_binkp_sysinfo *)THIS->local_data;
session_set_freqs_status();
binkp_set_sysinfo(local_data, &state.node.addr, TRUE);
@ -155,6 +159,7 @@ int binkp_outgoing2(s_handshake_protocol *THIS)
{
session_remote_lookup(remote_data->addrs, remote_data->anum);
session_remote_log_status();
binkp_log_options(remote_data);
}
if( rc == HRC_OK )

@ -177,6 +177,7 @@ void binkp_queuemsg(s_bpinfo *bpi, e_bpmsg msg, const char *s1, const char *s2)
(char*)bpi->msgqueue[bpi->n_msgs].data+3));
++bpi->n_msgs;
++bpi->msgs_in_batch;
}
/*****************************************************************************
@ -220,20 +221,24 @@ void binkp_queuemsgf(s_bpinfo *bpi, e_bpmsg msg, const char *fmt, ...)
* Return value:
* non-zero value on error, zero on success
*/
int binkp_parsfinfo(char *s, char **fn, size_t *sz, time_t *tm, size_t *offs)
{
int binkp_parsfinfo(char *str,char **fn,size_t *sz,time_t *tm,size_t *offs){
char *n;
char *p_fname = NULL;
char *p_size = NULL;
char *p_time = NULL;
char *p_offs = NULL;
static char *s = NULL;
/* Attention, offs may be NULL! */
ASSERT(s != NULL && fn != NULL && sz != NULL && tm != NULL);
ASSERT(str != NULL && fn != NULL && sz != NULL && tm != NULL);
DEB((D_PROT, "binkp_parsemsg: want parse \"%s\"", s));
if (s) free (s);
s = xstrcpy (str);
p_fname = string_token(s, &n, NULL, 0);
p_size = string_token(NULL, &n, NULL, 0);
p_time = string_token(NULL, &n, NULL, 0);
@ -241,7 +246,8 @@ int binkp_parsfinfo(char *s, char **fn, size_t *sz, time_t *tm, size_t *offs)
if( p_fname && p_size && p_time && (!offs || p_offs) )
{
if( ISDEC(p_size) && ISDEC(p_time) && (!offs || ISDEC(p_offs)) )
if( ISDEC(p_size) && ISDEC(p_time) &&
(!offs || ISDEC(p_offs) || !strcmp (p_offs, "-1")) )
{
(*fn) = p_fname;
(*sz) = atol(p_size);
@ -454,6 +460,7 @@ int binkp_recv(s_bpinfo *bpi)
bpi->imsgtype = binkp_getmsgtype(bpi->ibuf[0]);
DEB((D_PROT, "binkp_recv: got message #%d, %ld byte(s), \"%s\"",
(int)bpi->imsgtype, bpi->isize, bpi->ibuf+1));
++bpi->msgs_in_batch;
if( bpi->imsgtype < 0 )
{
bpi->isize = -1;
@ -528,6 +535,32 @@ void binkp_queue_sysinfo(s_bpinfo *bpi, s_binkp_sysinfo *binkp)
binkp_queuemsg(bpi, BPMSG_ADR, NULL, astr);
free(astr);
}
if (state.caller)
{
char *szOpt = xstrcpy (" MB");
if (!nodelist_checkflag (state.node.flags, "NR"))
szOpt = xstrcat (szOpt, " NR");
if (!nodelist_checkflag (state.node.flags, "ND"))
szOpt = xstrcat (szOpt, " ND");
if (*szOpt)
binkp_queuemsg(bpi, BPMSG_NUL, "OPT", szOpt);
free (szOpt);
}
}
/*****************************************************************************
* Write options to the log
*
* Arguments:
* binkp structure with the system information
*
* Return value:
* None
*/
void binkp_log_options(s_binkp_sysinfo *remote)
{
if (remote->options & BINKP_OPT_MB) log ("We are in MB mode.");
if (remote->options & BINKP_OPT_NR) log ("We are in NR mode.");
}
/*****************************************************************************

@ -387,7 +387,16 @@ int p_tx_readfile(char *buffer, size_t buflen, s_protinfo *pi)
{
int n;
struct stat st;
long ftell_pos = ftell(pi->send->fp);
long ftell_pos;
/*
* Sanity check: read from closed file.
*/
if (pi->send->fp == NULL) {
log ("Error: Read from closed file \"%s\".", pi->send->fname);
return -1;
}
ftell_pos = ftell(pi->send->fp);
pi->send->eofseen = FALSE; /* clear EOF flag */

@ -26,7 +26,7 @@
#define BINKP_NAME "binkp"
#define BINKP_MAJOR 1
#define BINKP_MINOR 0
#define BINKP_MINOR 1
#define BINKP_PORT 24554
#define BINKP_TIMEOUT (5*60)
#define BINKP_MIN_BLKSIZE 128
@ -124,6 +124,7 @@ typedef struct {
int junkcount;
s_bpmsg *msgqueue; /* Outgoing messages queue */
int n_msgs; /* Number of messages in queue */
int msgs_in_batch; /* Number of messages in batch */
int timeout;
} s_bpinfo;
@ -149,6 +150,7 @@ int binkp_send(s_bpinfo *bpi);
int binkp_flush_queue(s_bpinfo *bpi, int timeout);
int binkp_recv(s_bpinfo *bpi);
void binkp_update_sysinfo(s_binkp_sysinfo *binkp);
void binkp_log_options(s_binkp_sysinfo *remote);
void binkp_log_sysinfo(s_binkp_sysinfo *binkp);
void binkp_queue_sysinfo(s_bpinfo *bpi, s_binkp_sysinfo *binkp);
void binkp_set_sysinfo(s_binkp_sysinfo *binkp, s_faddr *remote_addr, bool caller);

Loading…
Cancel
Save