|
|
@ -614,26 +614,26 @@ case 4:
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define PROTO_ERROR(msg) log("error: %s", msg); bstate->extracmd[0] = BPMSG_ERR; strcpy(bstate->extracmd+1, msg); bstate->extraislast = true; return -1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int binkp_doreceiveblock(s_binkp_state *bstate, char *buf, int block_type, unsigned short block_length)
|
|
|
|
int binkp_doreceiveblock(s_binkp_state *bstate, char *buf, int block_type, unsigned short block_length)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
switch (block_type) {
|
|
|
|
switch (block_type) {
|
|
|
|
case BINKP_BLK_CMD:
|
|
|
|
case BINKP_BLK_CMD:
|
|
|
|
if (block_length<1) {
|
|
|
|
if (block_length<1) {
|
|
|
|
log("zero length command received");
|
|
|
|
PROTO_ERROR("Zero length command received")
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
buf[block_length] = 0; // fencing for easy processing
|
|
|
|
buf[block_length] = 0; // fencing for easy processing
|
|
|
|
switch (buf[0]) {
|
|
|
|
switch (buf[0]) {
|
|
|
|
case BPMSG_NUL: /* Site information, just logging */
|
|
|
|
case BPMSG_NUL: /* Site information, just logging */
|
|
|
|
log("M_NUL");
|
|
|
|
log("received M_NUL len=%d", block_length);
|
|
|
|
binkp_process_NUL(bstate->remote_data, buf+1);
|
|
|
|
binkp_process_NUL(bstate->remote_data, buf+1);
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
case BPMSG_ADR: /* List of addresses */
|
|
|
|
case BPMSG_ADR: /* List of addresses */
|
|
|
|
log("M_ADR");
|
|
|
|
log("received M_ADR len=%d", block_length);
|
|
|
|
if (bstate->address_established) {
|
|
|
|
if (bstate->address_established) {
|
|
|
|
log("remote tries to change address");
|
|
|
|
PROTO_ERROR("remote tries to change address");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( bstate->extracmd[0] !=-1 ) return 0; // suspend !!!
|
|
|
|
if( bstate->extracmd[0] !=-1 ) return 0; // suspend !!!
|
|
|
|
binkp_process_ADR(buf+1);
|
|
|
|
binkp_process_ADR(buf+1);
|
|
|
@ -692,14 +692,12 @@ case BPMSG_ADR: /* List of addresses */
|
|
|
|
bstate->address_established = true;
|
|
|
|
bstate->address_established = true;
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
case BPMSG_PWD: /* Session password */
|
|
|
|
case BPMSG_PWD: /* Session password */
|
|
|
|
log("M_PWD received");
|
|
|
|
log("received M_PWD len=%d", block_length);
|
|
|
|
if (bstate->mode != bmode_incoming_handshake) {
|
|
|
|
if (bstate->mode != bmode_incoming_handshake) {
|
|
|
|
log("unexpected M_PWD");
|
|
|
|
PROTO_ERROR("unexpected M_PWD");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!bstate->address_established) {
|
|
|
|
if (!bstate->address_established) {
|
|
|
|
log("M_PWD before M_ADR");
|
|
|
|
PROTO_ERROR("M_PWD before M_ADR");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
strnxcpy(bstate->remote_data->passwd, buf+1, block_length);
|
|
|
|
strnxcpy(bstate->remote_data->passwd, buf+1, block_length);
|
|
|
@ -732,20 +730,18 @@ case BPMSG_PWD: /* Session password */
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case BPMSG_FILE: /* File information */
|
|
|
|
case BPMSG_FILE: /* File information */
|
|
|
|
log("M_FILE");
|
|
|
|
log("received M_FILE len=%d", block_length);
|
|
|
|
if (bstate->mode != bmode_transfer) {
|
|
|
|
if (bstate->mode != bmode_transfer) {
|
|
|
|
log("unexpected M_FILE");
|
|
|
|
PROTO_ERROR("unexpected M_FILE");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
s_bpfinfo recvfi;
|
|
|
|
s_bpfinfo recvfi;
|
|
|
|
if( binkp_parsfinfo(buf+1, &recvfi, true) ) {
|
|
|
|
if( binkp_parsfinfo(buf+1, &recvfi, true) ) {
|
|
|
|
log ("M_FILE parse error: %s", buf + 1);
|
|
|
|
log ("M_FILE parse error: %s", buf + 1);
|
|
|
|
return -1;
|
|
|
|
PROTO_ERROR("invalid M_FILE");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bstate->batch_recv_count += 1;
|
|
|
|
bstate->batch_recv_count += 1;
|
|
|
|
if (bstate->frs == frs_data) {
|
|
|
|
if (bstate->frs == frs_data) {
|
|
|
|
log("overlapping M_FILE received");
|
|
|
|
PROTO_ERROR("overlapping M_FILE received");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (bstate->frs == frs_didget) {
|
|
|
|
if (bstate->frs == frs_didget) {
|
|
|
@ -766,7 +762,7 @@ case BPMSG_FILE: /* File information */
|
|
|
|
|
|
|
|
|
|
|
|
if (bstate->frs!=frs_nothing && bstate->frs!=frs_skipping) {
|
|
|
|
if (bstate->frs!=frs_nothing && bstate->frs!=frs_skipping) {
|
|
|
|
log("strange receiving mode %d", bstate->frs);
|
|
|
|
log("strange receiving mode %d", bstate->frs);
|
|
|
|
return -1;
|
|
|
|
PROTO_ERROR("invalid mode for M_FILE");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if( bstate->extracmd[0] != -1 ) return 0;
|
|
|
|
if( bstate->extracmd[0] != -1 ) return 0;
|
|
|
@ -804,17 +800,14 @@ case 2:
|
|
|
|
bstate->frs = frs_skipping;
|
|
|
|
bstate->frs = frs_skipping;
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
log("p_rx_fopen_error");
|
|
|
|
PROTO_ERROR("p_rx_fopen_error");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
log("never get here");
|
|
|
|
PROTO_ERROR("never should get here");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case BPMSG_OK: /* Password was acknowleged (data ignored) */
|
|
|
|
case BPMSG_OK: /* Password was acknowleged (data ignored) */
|
|
|
|
log("M_OK received");
|
|
|
|
log("received M_OK len=%d", block_length);
|
|
|
|
if (bstate->mode != bmode_outgoing_handshake) {
|
|
|
|
if (bstate->mode != bmode_outgoing_handshake) {
|
|
|
|
log("unexpected M_OK");
|
|
|
|
PROTO_ERROR("unexpected M_OK");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (session_addrs_lock(state.remoteaddrs, state.n_remoteaddr)) {
|
|
|
|
if (session_addrs_lock(state.remoteaddrs, state.n_remoteaddr)) {
|
|
|
|
log("error: unable to lock");
|
|
|
|
log("error: unable to lock");
|
|
|
@ -829,33 +822,29 @@ case BPMSG_OK: /* Password was acknowleged (data ignored) */
|
|
|
|
return 2;
|
|
|
|
return 2;
|
|
|
|
|
|
|
|
|
|
|
|
case BPMSG_EOB: /* End Of Batch (data ignored) */
|
|
|
|
case BPMSG_EOB: /* End Of Batch (data ignored) */
|
|
|
|
log("M_EOB received");
|
|
|
|
log("received M_EOB len=%d", block_length);
|
|
|
|
if (bstate->mode != bmode_transfer) {
|
|
|
|
if (bstate->mode != bmode_transfer) {
|
|
|
|
log("unexpected M_EOB");
|
|
|
|
PROTO_ERROR("unexpected M_EOB");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bstate->batchreceivecomplete += 1;
|
|
|
|
bstate->batchreceivecomplete += 1;
|
|
|
|
return 1; // continue receiving as M_GOT may and would arrive
|
|
|
|
return 1; // continue receiving as M_GOT may and would arrive
|
|
|
|
|
|
|
|
|
|
|
|
case BPMSG_GOT: /* File received */
|
|
|
|
case BPMSG_GOT: /* File received */
|
|
|
|
case BPMSG_SKIP:
|
|
|
|
case BPMSG_SKIP:
|
|
|
|
log("received GOT/SKIP");
|
|
|
|
log("received GOT/SKIP len=%d", block_length);
|
|
|
|
if (bstate->mode != bmode_transfer) {
|
|
|
|
if (bstate->mode != bmode_transfer) {
|
|
|
|
log("unexpected M_GOT/M_SKIP");
|
|
|
|
PROTO_ERROR("unexpected M_GOT/M_SKIP");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
s_bpfinfo fi;
|
|
|
|
s_bpfinfo fi;
|
|
|
|
int i;
|
|
|
|
int i;
|
|
|
|
if (binkp_parsfinfo (buf+1, &fi, false)) {
|
|
|
|
if (binkp_parsfinfo (buf+1, &fi, false)) {
|
|
|
|
log("error parsing");
|
|
|
|
PROTO_ERROR("error parsing M_GOT/M_SKIP");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (strcmp (bstate->pi->send->net_name, fi.fn) == 0 && bstate->pi->send->status != FSTAT_WAITACK) {
|
|
|
|
if (strcmp (bstate->pi->send->net_name, fi.fn) == 0 && bstate->pi->send->status != FSTAT_WAITACK) {
|
|
|
|
log("aborting current file");
|
|
|
|
log("aborting current file");
|
|
|
|
if (bstate->pi->send->netspool) {
|
|
|
|
if (bstate->pi->send->netspool) {
|
|
|
|
log("cannot abort netspool in progress");
|
|
|
|
PROTO_ERROR("cannot SKIP or REFUSE netspool");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p_tx_fclose(bstate->pi);
|
|
|
|
p_tx_fclose(bstate->pi);
|
|
|
|
bstate->phase = 0;
|
|
|
|
bstate->phase = 0;
|
|
|
@ -867,8 +856,7 @@ case BPMSG_SKIP:
|
|
|
|
bstate->pi->send = &bstate->pi->sentfiles[i];
|
|
|
|
bstate->pi->send = &bstate->pi->sentfiles[i];
|
|
|
|
if (buf[0] == BPMSG_SKIP) {
|
|
|
|
if (buf[0] == BPMSG_SKIP) {
|
|
|
|
if (bstate->pi->send->netspool) {
|
|
|
|
if (bstate->pi->send->netspool) {
|
|
|
|
log("cannot skip netspool");
|
|
|
|
PROTO_ERROR("cannot skip netspool");
|
|
|
|
return -1; // no reason to continue sending
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
log("skipped %s", fi.fn);
|
|
|
|
log("skipped %s", fi.fn);
|
|
|
|
bstate->pi->send->status = FSTAT_REFUSED;
|
|
|
|
bstate->pi->send->status = FSTAT_REFUSED;
|
|
|
@ -879,8 +867,7 @@ case BPMSG_SKIP:
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
log("confirmed not sent file - skipped %s", fi.fn);
|
|
|
|
log("confirmed not sent file - skipped %s", fi.fn);
|
|
|
|
if (bstate->pi->send->netspool) {
|
|
|
|
if (bstate->pi->send->netspool) {
|
|
|
|
log("cannot skip netspool");
|
|
|
|
PROTO_ERROR("cannot skip netspool");
|
|
|
|
return -1; // no reason to continue sending
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bstate->pi->send->status = FSTAT_SKIPPED;
|
|
|
|
bstate->pi->send->status = FSTAT_SKIPPED;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -891,8 +878,7 @@ case BPMSG_SKIP:
|
|
|
|
goto check_that_all_files_are_confirmed;
|
|
|
|
goto check_that_all_files_are_confirmed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
log("unmatched file name");
|
|
|
|
PROTO_ERROR("unmatched file name in M_GOT/M_SKIP");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
check_that_all_files_are_confirmed:
|
|
|
|
check_that_all_files_are_confirmed:
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -917,15 +903,14 @@ case BPMSG_BSY: /* All AKAs are busy */
|
|
|
|
return 3;
|
|
|
|
return 3;
|
|
|
|
|
|
|
|
|
|
|
|
case BPMSG_GET: /* Get a file from offset */
|
|
|
|
case BPMSG_GET: /* Get a file from offset */
|
|
|
|
log("received M_GET: cancel transmitting current file and send requested file if it is in outbound");
|
|
|
|
log("received M_GET len=%d", block_length);
|
|
|
|
if (bstate->mode != bmode_transfer) {
|
|
|
|
if (bstate->mode != bmode_transfer) {
|
|
|
|
log("unexpected M_GET");
|
|
|
|
PROTO_ERROR("unexpected M_GET");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
s_bpfinfo getfi;
|
|
|
|
s_bpfinfo getfi;
|
|
|
|
if (binkp_parsfinfo(buf+1, &getfi, true) != 0) {
|
|
|
|
if (binkp_parsfinfo(buf+1, &getfi, true) != 0) {
|
|
|
|
log("error parsing M_GET %s", buf+1);
|
|
|
|
log("error parsing M_GET %s", buf+1);
|
|
|
|
return -1;
|
|
|
|
PROTO_ERROR("invalid M_GET");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
log("M_GET file %s size %d time %d offset %d", getfi.fn, getfi.sz, getfi.tm, getfi.offs);
|
|
|
|
log("M_GET file %s size %d time %d offset %d", getfi.fn, getfi.sz, getfi.tm, getfi.offs);
|
|
|
|
|
|
|
|
|
|
|
@ -959,7 +944,7 @@ case BPMSG_GET: /* Get a file from offset */
|
|
|
|
if( p_tx_rewind(bstate->pi, getfi.offs) != 0 ) {
|
|
|
|
if( p_tx_rewind(bstate->pi, getfi.offs) != 0 ) {
|
|
|
|
log("failed to rewind");
|
|
|
|
log("failed to rewind");
|
|
|
|
p_tx_fclose(bstate->pi);
|
|
|
|
p_tx_fclose(bstate->pi);
|
|
|
|
return -1;
|
|
|
|
PROTO_ERROR("seek error")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bstate->pi->send->bytes_skipped = getfi.offs;
|
|
|
|
bstate->pi->send->bytes_skipped = getfi.offs;
|
|
|
|
bstate->pi->send->bytes_sent = getfi.offs;
|
|
|
|
bstate->pi->send->bytes_sent = getfi.offs;
|
|
|
@ -982,13 +967,12 @@ case BPMSG_GET: /* Get a file from offset */
|
|
|
|
hint.sz = getfi.sz;
|
|
|
|
hint.sz = getfi.sz;
|
|
|
|
hint.tm = getfi.tm;
|
|
|
|
hint.tm = getfi.tm;
|
|
|
|
if( p_tx_fopen(bstate->pi, &hint) != 0 ) {
|
|
|
|
if( p_tx_fopen(bstate->pi, &hint) != 0 ) {
|
|
|
|
log("could not satisfy M_GET");
|
|
|
|
PROTO_ERROR("could not satisfy M_GET");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( p_tx_rewind(bstate->pi, getfi.offs) != 0 ) {
|
|
|
|
if( p_tx_rewind(bstate->pi, getfi.offs) != 0 ) {
|
|
|
|
log("failed to rewind");
|
|
|
|
log("failed to rewind");
|
|
|
|
p_tx_fclose(bstate->pi);
|
|
|
|
p_tx_fclose(bstate->pi);
|
|
|
|
return -1;
|
|
|
|
PROTO_ERROR("seek error 2");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bstate->waiting_got = true;
|
|
|
|
bstate->waiting_got = true;
|
|
|
|
log("sending \"%s\" from %ld offset", bstate->pi->send->net_name, (long)getfi.offs);
|
|
|
|
log("sending \"%s\" from %ld offset", bstate->pi->send->net_name, (long)getfi.offs);
|
|
|
@ -1003,7 +987,7 @@ case BPMSG_GET: /* Get a file from offset */
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
log("unknown command %d received", buf[0]);
|
|
|
|
log("unknown command %d received", buf[0]);
|
|
|
|
return -1;
|
|
|
|
PROTO_ERROR("invalid command")
|
|
|
|
|
|
|
|
|
|
|
|
case BINKP_BLK_DATA:
|
|
|
|
case BINKP_BLK_DATA:
|
|
|
|
//if there is file in progress
|
|
|
|
//if there is file in progress
|
|
|
@ -1013,8 +997,7 @@ case BINKP_BLK_DATA:
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (bstate->frs == frs_nothing) {
|
|
|
|
if (bstate->frs == frs_nothing) {
|
|
|
|
log("unexpected data block");
|
|
|
|
PROTO_ERROR("unexpected data block");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (bstate->frs == frs_didget || bstate->frs == frs_skipping) {
|
|
|
|
if (bstate->frs == frs_didget || bstate->frs == frs_skipping) {
|
|
|
|
log("did M_GET or M_GOT or M_SKIP, skipping data");
|
|
|
|
log("did M_GET or M_GOT or M_SKIP, skipping data");
|
|
|
@ -1027,7 +1010,7 @@ case BINKP_BLK_DATA:
|
|
|
|
n = p_rx_writefile(buf, block_length, bstate->pi);
|
|
|
|
n = p_rx_writefile(buf, block_length, bstate->pi);
|
|
|
|
|
|
|
|
|
|
|
|
if( n < 0 ) {
|
|
|
|
if( n < 0 ) {
|
|
|
|
log("error writing file");
|
|
|
|
log("error writing local file");
|
|
|
|
if( n == -2 ) {
|
|
|
|
if( n == -2 ) {
|
|
|
|
bstate->extracmd[0] = BPMSG_GOT;
|
|
|
|
bstate->extracmd[0] = BPMSG_GOT;
|
|
|
|
sprintf(bstate->extracmd+1, "%s %ld %ld", bstate->pi->recv->net_name, (long)bstate->pi->recv->bytes_total,
|
|
|
|
sprintf(bstate->extracmd+1, "%s %ld %ld", bstate->pi->recv->net_name, (long)bstate->pi->recv->bytes_total,
|
|
|
@ -1055,7 +1038,7 @@ case BINKP_BLK_DATA:
|
|
|
|
bstate->frs = frs_skipping;
|
|
|
|
bstate->frs = frs_skipping;
|
|
|
|
bstate->pi->recv->status = FSTAT_REFUSED;
|
|
|
|
bstate->pi->recv->status = FSTAT_REFUSED;
|
|
|
|
p_rx_fclose(bstate->pi);
|
|
|
|
p_rx_fclose(bstate->pi);
|
|
|
|
return -1;
|
|
|
|
PROTO_ERROR("extra data for file")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( bstate->pi->recv->bytes_received == bstate->pi->recv->bytes_total ) {
|
|
|
|
else if( bstate->pi->recv->bytes_received == bstate->pi->recv->bytes_total ) {
|
|
|
|
log("receive completed");
|
|
|
|
log("receive completed");
|
|
|
@ -1083,11 +1066,9 @@ case BINKP_BLK_DATA:
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
log("never should be here");
|
|
|
|
PROTO_ERROR("never should be here");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
log("impossible block_type");
|
|
|
|
PROTO_ERROR("impossible block_type");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|