jcs
/subtext
/amendments
/541
binkp: Abort idle connections, respect binkp_delete_done for sending
Keep track of the time we last received a frame from the server and
if nothing happens in a while, kill the connection.
Use the binkp_delete_done setting to move processed outbound packets
into the processed folder for debugging.
Also send the actual mtime of the packet we're sending instead of
1, since it can be helpful for the binkp server operator.
jcs made amendment 541 about 1 year ago
--- binkp.c Tue Nov 14 08:59:06 2023
+++ binkp.c Tue Nov 14 17:20:46 2023
@@ -229,6 +229,7 @@ binkp_connect(void)
goto error;
}
+ binkpc->last_frame_at = Time;
return true;
error:
@@ -329,11 +330,18 @@ binkp_send_frame(short command, char *data, size_t dat
error = _TCPSend(&binkpc->tcp_send_iopb, binkpc->tcp_stream,
binkpc->tcp_wds, nil, nil, false);
if (error) {
- logger_printf("[binkp] TCPSend of %d failed: %d",
- binkpc->tcp_wds[0].length, error);
+ if (BINKP_CONNECTION_ALIVE(binkpc)) {
+ logger_printf("[binkp] TCPSend of %d failed (%d), aborting",
+ binkpc->tcp_wds[0].length, error);
+ } else {
+ logger_printf("[binkp] Connection lost (%d) while sending frame",
+ binkpc->tcp_status_pb.connectionState);
+ }
+ binkpc->error = true;
return 0;
}
+ binkpc->last_frame_at = Time;
uthread_yield();
return binkpc->tcp_wds[0].length;
@@ -380,7 +388,8 @@ binkp_read_frame(void)
logger_printf("[binkp] Received bogus frame, no data_size");
return false;
}
-
+
+ binkpc->last_frame_at = Time;
binkpc->cur_frame.type =
(binkpc->cur_frame.data_size & (1 << 15)) == 0 ? BINKP_TYPE_DATA :
BINKP_TYPE_COMMAND;
@@ -432,6 +441,7 @@ binkp_read_frame(void)
if (error)
goto failed_read;
+ binkpc->last_frame_at = Time;
frame_data_read += rlen;
if (binkpc->cur_frame.type == BINKP_TYPE_DATA) {
@@ -648,6 +658,13 @@ binkp_login(void)
while (binkpc && !binkpc->error) {
if (!binkp_read_frame()) {
uthread_yield();
+
+ if (Time - binkpc->last_frame_at > 30) {
+ logger_printf("[binkp] No frame received in %ld seconds, "
+ "aborting", (Time - binkpc->last_frame_at));
+ binkpc->error = true;
+ break;
+ }
continue;
}
@@ -928,12 +945,12 @@ binkp_buffer_file(Str255 path, char **data)
void
binkp_deliver_outbox(void)
{
+ Str255 file_name_c, path, done_path;
char command[50];
CInfoPBRec cipbr = { 0 };
HFileInfo *fpb = (HFileInfo *)&cipbr;
DirInfo *dpb = (DirInfo *)&cipbr;
CMovePBRec cmpbr = { 0 };
- Str255 file_name_c, path;
struct stat sb;
unsigned long started = Time, elapsed;
size_t len, data_size, fsize_left;
@@ -986,9 +1003,8 @@ binkp_deliver_outbox(void)
logger_printf("[binkp] Sending file %s size %lu", file_name_c,
sb.st_size);
- /* just send 1 as unix mtime */
- len = snprintf(command, sizeof(command), "%s %lu 1 0", file_name_c,
- sb.st_size);
+ len = snprintf(command, sizeof(command), "%s %lu %lu 0", file_name_c,
+ sb.st_size, MAC_TO_UNIX_TIME(sb.st_mtime));
if (!binkp_send_frame(BINKP_COMMAND_M_FILE, command, len))
goto done;
@@ -1020,6 +1036,12 @@ binkp_deliver_outbox(void)
/* wait for frame */
while (binkpc != NULL && !binkp_read_frame() && !binkpc->error) {
+ if (Time - binkpc->last_frame_at > 30) {
+ logger_printf("[binkp] No frame received in %ld seconds, "
+ "aborting", (Time - binkpc->last_frame_at));
+ binkpc->error = true;
+ goto done;
+ }
uthread_yield();
continue;
}
@@ -1037,12 +1059,37 @@ binkp_deliver_outbox(void)
}
logger_printf("[binkp] Successfully sent file %s", file_name_c);
-
- error = FSDelete(path, 0);
- if (error)
- /* this must be fatal so we don't keep trying this file */
- panic("[binkp] Failed deleting outbox file %s: %d",
- PtoCstr(path), error);
+
+ if (db->config.binkp_delete_done) {
+ if ((error = FSDelete(path, 0)))
+ /* this must be fatal so we don't keep trying this file */
+ panic("[binkp] Failed deleting outbox file %s: %d",
+ PtoCstr(path), error);
+ } else {
+ PtoCstr(binkp_done_dir);
+ snprintf((char *)done_path, sizeof(done_path),
+ "%s:%s", binkp_done_dir, file_name_c);
+ CtoPstr(done_path);
+ CtoPstr(binkp_done_dir);
+
+try_rename:
+ cmpbr.ioNamePtr = path;
+ cmpbr.ioNewName = binkp_done_dir;
+ cmpbr.ioDirID = 0;
+ cmpbr.ioNewDirID = 0;
+ cmpbr.ioVRefNum = 0;
+ error = PBCatMove(&cmpbr, false);
+ if (error == dupFNErr) {
+ error = FSDelete(done_path, 0);
+ if (error)
+ panic("[binkp] Failed deleting %s: %d",
+ PtoCstr(done_path), error);
+ goto try_rename;
+ } else if (error) {
+ panic("[binkp] Failed moving %s to %s: %d",
+ PtoCstr(path), PtoCstr(done_path), error);
+ }
+ }
}
if (!binkp_send_frame(BINKP_COMMAND_M_EOB, "", 0))
--- binkp.h Fri Nov 10 16:46:53 2023
+++ binkp.h Tue Nov 14 10:55:41 2023
@@ -64,6 +64,7 @@ struct binkp_connection {
size_t buf_size;
struct binkp_frame cur_frame;
struct binkp_file cur_incoming_file;
+ time_t last_frame_at;
bool done_receiving;
bool done_sending;
bool error;