diff --git a/CHANGES.ugenk b/CHANGES.ugenk index 4ea9c9e..2a3e408 100644 --- a/CHANGES.ugenk +++ b/CHANGES.ugenk @@ -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 \ No newline at end of file + docs/readme.txt for details. + + Implement binkp/1.1 (Multiple Batch Mode and Non-reliable Mode). + + Turn on FREQ at binkp sessions. diff --git a/examples/bforce.subst b/examples/bforce.subst index 187b25f..fb57008 100644 --- a/examples/bforce.subst +++ b/examples/bforce.subst @@ -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 diff --git a/source/bforce/prot_binkp.c b/source/bforce/prot_binkp.c index 03d6d90..ec71d3c 100644 --- a/source/bforce/prot_binkp.c +++ b/source/bforce/prot_binkp.c @@ -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; } } } diff --git a/source/bforce/prot_binkp_api.c b/source/bforce/prot_binkp_api.c index 93c8bdf..761679e 100644 --- a/source/bforce/prot_binkp_api.c +++ b/source/bforce/prot_binkp_api.c @@ -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 ) diff --git a/source/bforce/prot_binkp_misc.c b/source/bforce/prot_binkp_misc.c index f3f9242..b84bf63 100644 --- a/source/bforce/prot_binkp_misc.c +++ b/source/bforce/prot_binkp_misc.c @@ -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."); } /***************************************************************************** diff --git a/source/bforce/prot_common.c b/source/bforce/prot_common.c index cf7f3ca..f47ba56 100644 --- a/source/bforce/prot_common.c +++ b/source/bforce/prot_common.c @@ -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 */ diff --git a/source/include/prot_binkp.h b/source/include/prot_binkp.h index 241efb7..15dc44b 100644 --- a/source/include/prot_binkp.h +++ b/source/include/prot_binkp.h @@ -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);