[ttssh2-commit] [10964] SCP受信時、受信したデータが随時書き込まれない場合があるので修正

Back to archive index
scmno****@osdn***** scmno****@osdn*****
2023年 10月 8日 (日) 15:24:45 JST


Revision: 10964
          https://osdn.net/projects/ttssh2/scm/svn/commits/10964
Author:   zmatsuo
Date:     2023-10-08 15:24:45 +0900 (Sun, 08 Oct 2023)
Log Message:
-----------
SCP受信時、受信したデータが随時書き込まれない場合があるので修正

- SCP 受信したデータが随時書き込まれない (GitHub #15)

Ticket #34056
MFT r10959, r10960, r10962 相当

Revision Links:
--------------
    https://osdn.net/projects/ttssh2/scm/svn/commits/10959
    https://osdn.net/projects/ttssh2/scm/svn/commits/10960
    https://osdn.net/projects/ttssh2/scm/svn/commits/10962

Ticket Links:
------------
    https://osdn.net/projects/ttssh2/tracker/detail/15
    https://osdn.net/projects/ttssh2/tracker/detail/34056

Modified Paths:
--------------
    branches/4-stable/doc/en/html/about/history.html
    branches/4-stable/doc/ja/html/about/history.html
    branches/4-stable/ttssh2/ttxssh/ssh.c
    branches/4-stable/ttssh2/ttxssh/ssh.h
    branches/4-stable/ttssh2/ttxssh/ttxssh.h

-------------- next part --------------
Modified: branches/4-stable/doc/en/html/about/history.html
===================================================================
--- branches/4-stable/doc/en/html/about/history.html	2023-10-08 06:24:34 UTC (rev 10963)
+++ branches/4-stable/doc/en/html/about/history.html	2023-10-08 06:24:45 UTC (rev 10964)
@@ -3352,6 +3352,7 @@
     <ul>
       <li>when SSH2 dynamic port forwarding is used, an application fault occurs.</li>
       <li>when <a href="../menu/setup-sshauth.html">Authentication Setup dialog</a> is opened, username setting value is "Use default username" (DefaultUserType=1), nevertheless "Do not enter username" is selected.</li>
+      <li>When receiving SCP, received data is not written and memory usage increases, or no response.</li>
     </ul>
   </li>
 

Modified: branches/4-stable/doc/ja/html/about/history.html
===================================================================
--- branches/4-stable/doc/ja/html/about/history.html	2023-10-08 06:24:34 UTC (rev 10963)
+++ branches/4-stable/doc/ja/html/about/history.html	2023-10-08 06:24:45 UTC (rev 10964)
@@ -3358,6 +3358,7 @@
     <ul>
       <li>SSH2\x83_\x83C\x83i\x83~\x83b\x83N\x83|\x81[\x83g\x83t\x83H\x83\x8F\x81[\x83f\x83B\x83\x93\x83O\x82\xF0\x8Eg\x97p\x82\xB7\x82\xE9\x82ƈُ\xED\x8FI\x97\xB9\x82\xB7\x82\xE9\x96\xE2\x91\xE8\x82\xF0\x8FC\x90\xB3\x82\xB5\x82\xBD\x81B</li>
       <li><a href="../menu/setup-sshauth.html">Authentication Setup \x83_\x83C\x83A\x83\x8D\x83O</a>\x82\xF0\x8AJ\x82\xA2\x82\xBD\x82Ƃ\xAB\x82ɁASSH \x94F\x8F؂Ɏg\x97p\x82\xB7\x82郆\x81[\x83U\x96\xBC\x90ݒ肪 "Use default username" (DefaultUserType=1) \x82Ȃ̂\xC9 "Do not enter username" \x82\xAA\x91I\x91\xF0\x82\xB3\x82\xEA\x82\xE9\x96\xE2\x91\xE8\x82\xF0\x8FC\x90\xB3\x82\xB5\x82\xBD\x81B</li>
+      <li>SCP\x8E\xF3\x90M\x8E\x9E\x81A\x8E\xF3\x90M\x83f\x81[\x83^\x82\xAA\x90\x8F\x8E\x9E\x8F\x91\x82\xAB\x8D\x9E\x82܂ꂸ\x83\x81\x83\x82\x83\x8A\x8Eg\x97p\x97ʂ\xAA\x91\x9D\x89\xC1\x82\xB7\x82\xE9\x81A\x89\x9E\x93\x9A\x82Ȃ\xB5\x82ɂȂ\xE9\x95s\x8B\x82\xF0\x8FC\x90\xB3\x82\xB5\x82\xBD\x81B</li>
     </ul>
   </li>
 

Modified: branches/4-stable/ttssh2/ttxssh/ssh.c
===================================================================
--- branches/4-stable/ttssh2/ttxssh/ssh.c	2023-10-08 06:24:34 UTC (rev 10963)
+++ branches/4-stable/ttssh2/ttxssh/ssh.c	2023-10-08 06:24:45 UTC (rev 10964)
@@ -140,8 +140,8 @@
 static void start_ssh_heartbeat_thread(PTInstVar pvar);
 void ssh2_channel_send_close(PTInstVar pvar, Channel_t *c);
 static BOOL SSH_agent_response(PTInstVar pvar, Channel_t *c, int local_channel_num, unsigned char *data, unsigned int buflen);
-static void ssh2_scp_get_packetlist(Channel_t *c, unsigned char **buf, unsigned int *buflen);
-static void ssh2_scp_free_packetlist(Channel_t *c);
+static void ssh2_scp_get_packetlist(PTInstVar pvar, Channel_t *c, unsigned char **buf, unsigned int *buflen);
+static void ssh2_scp_free_packetlist(PTInstVar pvar, Channel_t *c);
 static void get_window_pixel_size(PTInstVar pvar, int *x, int *y);
 static void do_SSH2_dispatch_setup_for_transfer(PTInstVar pvar);
 static void ssh2_prep_userauth(PTInstVar pvar);
@@ -360,8 +360,10 @@
 
 		// SCP\x8E\xF3\x90M\x82̏ꍇ\x82̂݁ASCP\x97p\x83\x8A\x83X\x83g\x82̊J\x95\xFA\x82\xF0\x8Ds\x82\xA4\x81B
 		// Windows9x\x82ŗ\x8E\x82\xBF\x82\xE9\x96\xE2\x91\xE8\x82\xF0\x8FC\x90\xB3\x82\xB5\x82\xBD\x81B
-		if (c->scp.dir == FROMREMOTE)
-			ssh2_scp_free_packetlist(c);
+		if (c->scp.dir == FROMREMOTE) {
+			PTInstVar pvar = c->scp.pvar;
+			ssh2_scp_free_packetlist(pvar, c);
+		}
 
 		g_scp_sending = FALSE;
 	}
@@ -8292,7 +8294,7 @@
 		if (is_canceled_window(hWnd))
 			goto cancel_abort;
 
-		ssh2_scp_get_packetlist(c, &data, &buflen);
+		ssh2_scp_get_packetlist(pvar, c, &data, &buflen);
 		if (data && buflen) {
 			msg.message = WM_RECEIVING_FILE;
 
@@ -8363,7 +8365,6 @@
 	c->scp.state = SCP_CLOSING;
 	ShowWindow(c->scp.progress_window, SW_HIDE);
 
-cancel_abort:
 	// \x83`\x83\x83\x83l\x83\x8B\x82̃N\x83\x8D\x81[\x83Y\x82\xF0\x8Ds\x82\xA2\x82\xBD\x82\xA2\x82\xAA\x81A\x92\xBC\x90\xDA ssh2_channel_send_close() \x82\xF0\x8CĂяo\x82\xB7\x82ƁA
 	// \x93\x96\x8AY\x8A֐\x94\x82\xAA\x83X\x83\x8C\x83b\x83h\x83Z\x81[\x83t\x82ł͂Ȃ\xA2\x82\xBD\x82߁ASCP\x8F\x88\x97\x9D\x82\xAA\x90\xB3\x8F\xED\x82ɏI\x97\xB9\x82\xB5\x82Ȃ\xA2\x8Fꍇ\x82\xAA\x82\xA0\x82\xE9\x81B
 	// (2011.6.1 yutaka)
@@ -8370,12 +8371,43 @@
 	parm.c = c;
 	parm.pvar = pvar;
 	SendMessage(hWnd, WM_CHANNEL_CLOSE, (WPARAM)&parm, 0);
+	return 0;
 
+cancel_abort:
+	pvar->recv.close_request = TRUE;
 	return 0;
 }
 
-static void ssh2_scp_add_packetlist(Channel_t *c, unsigned char *buf, unsigned int buflen)
+// do_SSH2_adjust_window_size() \x82\xF0\x82\xA0\x82\xE9\x92\xF6\x93x\x8E\x9E\x8AԂ\xAA\x8Co\x89߂\xB5\x82Ă\xA9\x82\xE7\x83R\x81[\x83\x8B\x82\xB7\x82\xE9
+// \x83t\x83\x8D\x81[\x90\xA7\x8C\xE4\x81A\x8E\xF3\x90M\x8F\x88\x97\x9D\x82\xF0\x8DĊJ
+static void CALLBACK do_SSH2_adjust_window_size_timer(
+	HWND hWnd, UINT uMsg, UINT_PTR nIDEvent, DWORD dwTime)
 {
+	(void)hWnd;
+	(void)uMsg;
+	(void)dwTime;
+	Channel_t *c = (Channel_t *)nIDEvent;
+	PTInstVar pvar = c->scp.pvar;
+
+	if (pvar->recv.data_finished) {
+		// \x91\x97\x90M\x8FI\x97\xB9\x82\xB5\x82\xBD\x82̂Ƀ\x81\x83b\x83Z\x81[\x83W\x82\xAA\x8Ec\x82\xC1\x82Ă\xA2\x82\xBD\x8E\x9E\x91΍\xF4
+		return;
+	}
+	if (pvar->recv.timer_id != 0) {
+		// SetTimer() \x82̓C\x83\x93\x83^\x81[\x83o\x83\x8B\x82ɔ\xAD\x90\xB6\x82\xB7\x82\xE9\x82̂ō폜\x82\xB7\x82\xE9
+		KillTimer(pvar->cv->HWin, pvar->recv.timer_id);
+		pvar->recv.timer_id = 0;
+	}
+
+	logprintf(LOG_LEVEL_NOTICE, "%s: SCP receive, send SSH_MSG_CHANNEL_WINDOW_ADJUST", __FUNCTION__);
+	pvar->recv.suspended = FALSE;
+	do_SSH2_adjust_window_size(pvar, c);
+}
+
+// SSH\x83T\x81[\x83o\x82\xA9\x82瑗\x82\xE7\x82\xEA\x82Ă\xAB\x82\xBD\x83t\x83@\x83C\x83\x8B\x82̃f\x81[\x83^\x82\xF0\x83\x8A\x83X\x83g\x82ɂ‚Ȃ\xAE\x81B
+// \x83\x8A\x83X\x83g\x82̎\xE6\x82\xE8\x8Fo\x82\xB5\x82\xCD ssh_scp_receive_thread \x83X\x83\x8C\x83b\x83h\x82ōs\x82\xA4\x81B
+static void ssh2_scp_add_packetlist(PTInstVar pvar, Channel_t *c, unsigned char *buf, unsigned int buflen)
+{
 	PacketList_t *p, *old;
 
 	EnterCriticalSection(&g_ssh_scp_lock);
@@ -8398,11 +8430,30 @@
 		c->scp.pktlist_tail = p;
 	}
 
+	// \x83L\x83\x85\x81[\x82ɋl\x82񂾃f\x81[\x83^\x82̑\x8D\x83T\x83C\x83Y\x82\xF0\x89\xC1\x8EZ\x82\xB7\x82\xE9\x81B
+	c->scp.pktlist_cursize += buflen;
+
+	// \x83L\x83\x85\x81[\x82ɋl\x82񂾃f\x81[\x83^\x82̑\x8D\x83T\x83C\x83Y\x82\xAA\x8F\xE3\x8C\xC0臒l\x82𒴂\xA6\x82\xBD\x8Fꍇ\x81A
+	// SSH\x83T\x81[\x83o\x82\xCCwindows size\x82̍X\x90V\x82\xF0\x92\xE2\x8E~\x82\xB7\x82\xE9
+	// \x82\xB1\x82\xEA\x82ɂ\xE6\x82胊\x83X\x83g\x83G\x83\x93\x83g\x83\x8A\x82\xAA\x91\x9D\x82\xA6\x91\xB1\x82\xAF\x81A\x8F\xC1\x94\x83\x82\x83\x8A\x82̔\xEC\x91剻\x82\xF0
+	// \x89\xF1\x94\xF0\x82ł\xAB\x82\xE9\x81B
+	if (c->scp.pktlist_cursize >= SCPRCV_HIGH_WATER_MARK) {
+		logprintf(LOG_LEVEL_NOTICE,
+			"%s: enter suspend", __FUNCTION__);
+		pvar->recv.suspended = TRUE;
+	}
+
+	logprintf(LOG_LEVEL_NOTICE,
+		"%s: channel=#%d SCP recv %lu(bytes) and enqueued.%s",
+		__FUNCTION__, c->local_num, c->scp.pktlist_cursize,
+		pvar->recv.suspended ? "(suspended)" : ""
+		);
+
 error:;
 	LeaveCriticalSection(&g_ssh_scp_lock);
 }
 
-static void ssh2_scp_get_packetlist(Channel_t *c, unsigned char **buf, unsigned int *buflen)
+static void ssh2_scp_get_packetlist(PTInstVar pvar, Channel_t *c, unsigned char **buf, unsigned int *buflen)
 {
 	PacketList_t *p;
 
@@ -8425,18 +8476,47 @@
 
 	free(p);
 
+	// \x83L\x83\x85\x81[\x82ɋl\x82񂾃f\x81[\x83^\x82̑\x8D\x83T\x83C\x83Y\x82\xF0\x8C\xB8\x8EZ\x82\xB7\x82\xE9\x81B
+	c->scp.pktlist_cursize -= *buflen;
+
+	// \x83L\x83\x85\x81[\x82ɋl\x82񂾃f\x81[\x83^\x82̑\x8D\x83T\x83C\x83Y\x82\xAA\x89\xBA\x8C\xC0臒l\x82\xF0\x89\xBA\x89\xF1\x82\xC1\x82\xBD\x8Fꍇ\x81A
+	// SSH\x83T\x81[\x83o\x82\xD6window size\x82̍X\x90V\x82\xF0\x8DĊJ\x82\xB7\x82\xE9
+	if (c->scp.pktlist_cursize <= SCPRCV_LOW_WATER_MARK) {
+		logprintf(LOG_LEVEL_NOTICE, "%s: SCP receive resumed", __FUNCTION__);
+		// \x83u\x83\x8D\x83b\x83N\x82\xB5\x82Ă\xA2\x82\xE9\x8Fꍇ
+		if (pvar->recv.suspended) {
+			// SCP\x8E\xF3\x90M\x82̃u\x83\x8D\x83b\x83N\x82\xF0\x89\xF0\x8F\x9C\x82\xB7\x82\xE9\x81B
+			pvar->recv.suspended = FALSE;
+			if (c->scp.filercvsize < c->scp.filetotalsize) {
+				// \x91\xB1\x82\xAB\x82\xF0\x8E\xF3\x90M
+				pvar->recv.timer_id =
+					SetTimer(pvar->cv->HWin, (UINT_PTR)c, USER_TIMER_MINIMUM, do_SSH2_adjust_window_size_timer);
+			}
+		}
+	}
+
+	logprintf(LOG_LEVEL_NOTICE,
+		"%s: channel=#%d SCP recv %lu(bytes) and dequeued.%s",
+		__FUNCTION__, c->local_num, c->scp.pktlist_cursize,
+		pvar->recv.suspended ? "(suspended)" : ""
+	);
+
 end:;
 	LeaveCriticalSection(&g_ssh_scp_lock);
 }
 
-static void ssh2_scp_alloc_packetlist(Channel_t *c)
+static void ssh2_scp_alloc_packetlist(PTInstVar pvar, Channel_t *c)
 {
 	c->scp.pktlist_head = NULL;
 	c->scp.pktlist_tail = NULL;
 	InitializeCriticalSection(&g_ssh_scp_lock);
+	c->scp.pktlist_cursize = 0;
+	pvar->recv.suspended = FALSE;
+	pvar->recv.timer_id = 0;
+	pvar->recv.close_request = FALSE;
 }
 
-static void ssh2_scp_free_packetlist(Channel_t *c)
+static void ssh2_scp_free_packetlist(PTInstVar pvar, Channel_t *c)
 {
 	PacketList_t *p, *old;
 
@@ -8452,18 +8532,13 @@
 	c->scp.pktlist_head = NULL;
 	c->scp.pktlist_tail = NULL;
 	DeleteCriticalSection(&g_ssh_scp_lock);
+	c->scp.pktlist_cursize = 0;
+	pvar->recv.suspended = FALSE;
+	pvar->recv.data_finished = FALSE;
 }
 
 static BOOL SSH2_scp_fromremote(PTInstVar pvar, Channel_t *c, unsigned char *data, unsigned int buflen)
 {
-	int permission;
-	long long size;
-	char filename[MAX_PATH];
-	char ch;
-	HWND hDlgWnd;
-	char msg[256];
-	int copylen;
-
 	if (buflen == 0)
 		return FALSE;
 
@@ -8485,14 +8560,22 @@
 			goto reply;
 
 		} else if (data[0] == 'C') {  // C0666 size file
+			HWND hDlgWnd;
 			HANDLE thread;
 			unsigned int tid;
+			int permission;
+			long long size;
+			char filename[MAX_PATH];
 
 			sscanf_s(data, "C%o %lld %s", &permission, &size, filename, (unsigned int)sizeof(filename));
+			logprintf(LOG_LEVEL_NOTICE, "%s: SCP '%s', size=%lld, perm=0x%08x",
+					  __FUNCTION__,
+					  filename, size, permission);
 
 			// Windows\x82Ȃ̂Ńp\x81[\x83~\x83b\x83V\x83\x87\x83\x93\x82͖\xB3\x8E\x8B\x81B\x83T\x83C\x83Y\x82̂݋L\x98^\x81B
 			c->scp.filetotalsize = size;
 			c->scp.filercvsize = 0;
+			c->scp.recv.received_size = 0;
 
 			c->scp.state = SCP_DATA;
 
@@ -8514,7 +8597,7 @@
 				ShowWindow(hDlgWnd, SW_SHOW);
 			}
 
-			ssh2_scp_alloc_packetlist(c);
+			ssh2_scp_alloc_packetlist(pvar, c);
 			thread = (HANDLE)_beginthreadex(NULL, 0, ssh_scp_receive_thread, c, 0, &tid);
 			if (thread == 0) {
 				// TODO:
@@ -8528,6 +8611,9 @@
 		} else {
 			// \x83T\x81[\x83o\x82\xA9\x82\xE7\x82̃f\x81[\x83^\x82\xAA\x95s\x92\xE8\x82̏ꍇ\x82́A\x83G\x83\x89\x81[\x95\\x8E\xA6\x82\xF0\x8Ds\x82\xA4\x81B
 			// (2014.7.13 yutaka)
+			char msg[256];
+			int copylen;
+
 			copylen = min(buflen, sizeof(msg));
 			memcpy(msg, data, copylen);
 			msg[copylen - 1] = 0;
@@ -8538,16 +8624,60 @@
 		}
 
 	} else if (c->scp.state == SCP_DATA) {  // payload\x82̎\xF3\x90M
-		unsigned char *newdata = malloc(buflen);
-		if (newdata != NULL) {
-			memcpy(newdata, data, buflen);
+		logprintf(LOG_LEVEL_VERBOSE, "%s: SCP_DATA size=%lld",
+				  __FUNCTION__,
+				  buflen);
+		if (pvar->recv.close_request) {
+			// \x83L\x83\x83\x83\x93\x83Z\x83\x8B\x83{\x83^\x83\x93\x82\xF0\x89\x9F\x82\xB3\x82ꂽ
+			ssh2_channel_send_close(pvar, c);
+		}
+		else {
+			unsigned char *newdata = malloc(buflen);
+			if (newdata != NULL) {
+				memcpy(newdata, data, buflen);
 
-			// SCP\x8E\xF3\x90M\x8F\x88\x97\x9D\x82̃X\x83s\x81[\x83h\x82\xAA\x91\xAC\x82\xA2\x8Fꍇ\x81A\x83X\x83\x8C\x83b\x83h\x82̃\x81\x83b\x83Z\x81[\x83W\x83L\x83\x85\x81[\x82\xAA\x83t\x83\x8B(10000\x8C\xC2)\x82\xC9
-			// \x82Ȃ\xE8\x81A\x82\xA9\x82ƒX\x83\x8C\x83b\x83h\x8F\xE3\x82ł\xCC SendMessage \x82\xAA\x83u\x83\x8D\x83b\x83N\x82\xB7\x82邱\x82Ƃɂ\xE6\x82\xE8\x81ATera Term(TTSSH)
-			// \x8E\xA9\x91̂\xAA\x83X\x83g\x81[\x83\x8B\x82\xB5\x82Ă\xB5\x82܂\xA4\x81B\x82\xB1\x82̖\xE2\x91\xE8\x82\xF0\x89\xF1\x94\xF0\x82\xB7\x82邽\x82߁A\x83X\x83\x8C\x83b\x83h\x82̃\x81\x83b\x83Z\x81[\x83W\x83L\x83\x85\x81[\x82\xF0
-			// \x8Eg\x82\xA4\x82̂\xF0\x82\xE2\x82߂āA\x83\x8A\x83\x93\x83N\x83h\x83\x8A\x83X\x83g\x95\xFB\x8E\xAE\x82ɐ؂\xE8\x91ւ\xA6\x82\xE9\x81B
-			// (2016.11.3 yutaka)
-			ssh2_scp_add_packetlist(c, newdata, buflen);
+				// \x82\xB1\x82̒\x86\x82\xC5 suspended \x82\xAA TRUE \x82ɂȂ邱\x82Ƃ\xAA\x82\xA0\x82\xE9
+				ssh2_scp_add_packetlist(pvar, c, newdata, buflen);
+			}
+
+			c->scp.recv.received_size += buflen;
+
+			if (c->scp.recv.received_size >= c->scp.filetotalsize) {
+				// \x8E\xF3\x90M\x8FI\x97\xB9
+				assert (pvar->recv.timer_id == 0);
+				PTInstVar pvar = c->scp.pvar;
+				pvar->recv.data_finished = TRUE;
+				if (pvar->recv.timer_id != 0) {
+					pvar->recv.timer_id = 0;
+					KillTimer(pvar->cv->HWin, pvar->recv.timer_id);
+				}
+			}
+			else if (pvar->recv.suspended) {
+				// \x83t\x83\x8D\x81[\x90\xA7\x8C䒆
+				logprintf(LOG_LEVEL_NOTICE, "%s: scp receive suspended", __FUNCTION__);
+			}
+			else {
+				// \x83\x8D\x81[\x83J\x83\x8B\x82\xCCwindow size\x82\xF0\x83`\x83F\x83b\x83N
+				//	\x82\xB1\x82܂߂ɂ\xE2\x82炸\x82ɁA\x82\xA0\x82\xE9\x92\xF6\x93x\x82܂Ƃ߂Ē\xB2\x90\xAE\x82\xF0\x8Ds\x82\xA4
+				if (c->local_window < c->local_window_max/2) {
+					// window\x83T\x83C\x83Y\x82𒲐\xAE\x82\xB7\x82\xE9
+#if 0
+					// \x82\xB7\x82\xAE\x82ɒ\xB2\x90\xAE\x82\xB7\x82\xE9
+					//		\x82\xB7\x82\xAE\x82ɃT\x81[\x83o\x81[\x82\xA9\x82\xE7\x83f\x81[\x83^\x82\xAA\x8E\xF3\x90M\x82ł\xAB\x82\xE9\x8A‹\xAB\x82̏ꍇ\x81A
+					// 		FD_READ\x82\xAA\x97D\x90悳\x82\xEA\x82ă\x81\x83b\x83Z\x81[\x83W\x83L\x83\x85\x81[\x82ɐς܂\xEA\x82\xC4
+					// 		\x91\xBC\x82\xCCwindows\x82̃\x81\x83b\x83Z\x81[\x83W\x8F\x88\x97\x9D(\x83L\x83\x83\x83\x93\x83Z\x83\x8B\x83{\x83^\x83\x93\x89\x9F\x89\xBA\x82Ȃ\xC7)\x82\xAA
+					//		\x82ł\xAB\x82Ȃ\xAD\x82Ȃ邽\x82ߎg\x97p\x82\xB5\x82Ȃ\xA2
+					do_ssh2_adjust_window_size(pvar, c);
+#else
+					// \x8F\xAD\x82\xB5\x8E\x9E\x8AԂ\xF0\x92u\x82\xA2\x82Ă\xA9\x82璲\x90\xAE
+					//		\x83^\x83C\x83}\x81[\x82\xF0\x8Eg\x82\xC1\x82\xC4GUI\x83X\x83\x8C\x83b\x83h\x82Ŋ֐\x94\x82\xF0\x83R\x81[\x83\x8B\x82\xB7\x82\xE9
+					if (pvar->recv.timer_id == 0) {
+						pvar->recv.timer_id =
+							SetTimer(pvar->cv->HWin, (UINT_PTR)c, USER_TIMER_MINIMUM, do_SSH2_adjust_window_size_timer);
+					}
+#endif
+				}
+			}
 		}
 
 	} else if (c->scp.state == SCP_CLOSING) {  // EOF\x82̎\xF3\x90M
@@ -8558,8 +8688,11 @@
 	return TRUE;
 
 reply:
-	ch = '\0';
-	SSH2_send_channel_data(pvar, c, &ch, 1, 0);
+	{
+		char ch;
+		ch = '\0';
+		SSH2_send_channel_data(pvar, c, &ch, 1, 0);
+	}
 	return TRUE;
 }
 
@@ -8682,6 +8815,9 @@
 
 	} else if (c->type == TYPE_SCP) {  // SCP
 		SSH2_scp_response(pvar, c, data, str_len);
+		// \x83E\x83B\x83\x93\x83h\x83E\x83T\x83C\x83Y\x82̒\xB2\x90\xAE
+		c->local_window -= str_len;
+		return TRUE;
 
 	} else if (c->type == TYPE_SFTP) {  // SFTP
 		sftp_response(pvar, c, data, str_len);
@@ -8781,7 +8917,12 @@
 	// \x83E\x83B\x83\x93\x83h\x83E\x83T\x83C\x83Y\x82̒\xB2\x90\xAE
 	c->local_window -= strlen;
 
-	do_SSH2_adjust_window_size(pvar, c);
+	if (c->type == TYPE_SCP && pvar->recv.suspended) {
+		logprintf(LOG_LEVEL_NOTICE, "%s: SCP suspended", __FUNCTION__);
+	}
+	else {
+		do_SSH2_adjust_window_size(pvar, c);
+	}
 
 	return TRUE;
 }
@@ -9034,6 +9175,10 @@
 		ssh2_channel_delete(c);
 
 	} else if (c->type == TYPE_SCP) {
+		// \x8E\xF3\x90M\x8FI\x97\xB9
+		PTInstVar pvar = c->scp.pvar;
+		pvar->recv.data_finished = TRUE;
+
 		ssh2_channel_delete(c);
 
 	} else if (c->type == TYPE_AGENT) {

Modified: branches/4-stable/ttssh2/ttxssh/ssh.h
===================================================================
--- branches/4-stable/ttssh2/ttxssh/ssh.h	2023-10-08 06:24:34 UTC (rev 10963)
+++ branches/4-stable/ttssh2/ttxssh/ssh.h	2023-10-08 06:24:45 UTC (rev 10964)
@@ -534,6 +534,11 @@
 	struct PacketList *next;
 } PacketList_t;
 
+// SCP\x8E\xF3\x90M\x8F\x88\x97\x9D\x82ɂ\xA8\x82\xAF\x82\xE9\x83t\x83\x8D\x81[\x90\xA7\x8C\xE4\x82\xCC臒l
+// \x93K\x97p\x90\xE6 scp_t.filercvsize
+#define SCPRCV_HIGH_WATER_MARK (1 * 1024 * 1024)  // 1MB
+#define SCPRCV_LOW_WATER_MARK (0)  // 0MB
+
 typedef struct scp {
 	enum scp_dir dir;              // transfer direction
 	enum scp_state state;          // SCP state 
@@ -553,6 +558,10 @@
 	DWORD fileatime;
 	PacketList_t *pktlist_head;
 	PacketList_t *pktlist_tail;
+	unsigned long pktlist_cursize;
+	struct {
+		uint64_t received_size;
+	} recv;
 } scp_t;
 
 enum sftp_state {

Modified: branches/4-stable/ttssh2/ttxssh/ttxssh.h
===================================================================
--- branches/4-stable/ttssh2/ttxssh/ttxssh.h	2023-10-08 06:24:34 UTC (rev 10963)
+++ branches/4-stable/ttssh2/ttxssh/ttxssh.h	2023-10-08 06:24:45 UTC (rev 10964)
@@ -352,6 +352,14 @@
 	// dialog resource
 	HFONT hFontFixed;		// hosts.c\x93\xE0\x82̃_\x83C\x83A\x83\x8D\x83O\x97p
 
+	struct {
+		BOOL suspended;  // SCP\x8E\xF3\x90M\x82̃t\x83\x8D\x81[\x90\xA7\x8C\xE4\x97p,TRUE\x82̂Ƃ\xAB\x89\x9E\x93\x9A\x82\xF0\x95Ԃ\xB3\x82Ȃ\xA2\x8F\xF3\x91\xD4
+		//BOOL timer_triggerd;
+		UINT_PTR timer_id;
+		BOOL data_finished;	// TRUE\x82̂Ƃ\xAB,\x83f\x81[\x83^\x82̎\xF3\x90M\x82͊\xAE\x97\xB9\x82\xB5\x82\xBD
+		BOOL close_request;
+	} recv;
+
 	char *server_sig_algs;
 
 } TInstVar;


ttssh2-commit メーリングリストの案内
Back to archive index