Develop and Download Open Source Software

Browse Subversion Repository

Diff of /branches/ssh_chacha20poly1305/ttssh2/ttxssh/ssh.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 3074 by yutakapon, Mon Dec 24 14:42:50 2007 UTC revision 3075 by yutakapon, Tue Dec 25 14:49:01 2007 UTC
# Line 29  SOFTWARE, EVEN IF ADVISED OF THE POSSIBI Line 29  SOFTWARE, EVEN IF ADVISED OF THE POSSIBI
29    
30  #include "ttxssh.h"  #include "ttxssh.h"
31  #include "util.h"  #include "util.h"
32    #include "resource.h"
33    
34  #include <openssl/bn.h>  #include <openssl/bn.h>
35  #include <openssl/evp.h>  #include <openssl/evp.h>
# Line 51  SOFTWARE, EVEN IF ADVISED OF THE POSSIBI Line 52  SOFTWARE, EVEN IF ADVISED OF THE POSSIBI
52  #include <sys/stat.h>  #include <sys/stat.h>
53  #include <assert.h>  #include <assert.h>
54    
55    
56  // SSH2 macro  // SSH2 macro
57  #ifdef _DEBUG  #ifdef _DEBUG
58  #define SSH2_DEBUG  #define SSH2_DEBUG
# Line 86  typedef struct scp { Line 88  typedef struct scp {
88          char sendfilefull[MAX_PATH];   // sending filename fullpath          char sendfilefull[MAX_PATH];   // sending filename fullpath
89          FILE *sendfp;                  // file pointer          FILE *sendfp;                  // file pointer
90          struct _stat filestat;         // file status information          struct _stat filestat;         // file status information
91          HANDLE thread;                 // sending thread handle          HWND progress;
92  } scp_t;  } scp_t;
93    
94  typedef struct channel {  typedef struct channel {
# Line 181  static Channel_t *ssh2_channel_new(unsig Line 183  static Channel_t *ssh2_channel_new(unsig
183          c->bufchain = NULL;          c->bufchain = NULL;
184          if (type == TYPE_SCP) {          if (type == TYPE_SCP) {
185                  c->scp.state = SCP_INIT;                  c->scp.state = SCP_INIT;
186                  c->scp.thread = (HANDLE)-1L;                  c->scp.progress = NULL;
187          }          }
188    
189          return (c);          return (c);
# Line 255  static void ssh2_channel_delete(Channel_ Line 257  static void ssh2_channel_delete(Channel_
257    
258          if (c->type == TYPE_SCP) {          if (c->type == TYPE_SCP) {
259                  c->scp.state = SCP_CLOSING;                  c->scp.state = SCP_CLOSING;
260                  // SCPスレッドが動いていたら終わるまで待つ                  if (c->scp.progress != NULL) {
261                  if (c->scp.thread != (HANDLE)-1L) {                          //SendMessage(c->scp.progress, WM_CLOSE, 0, 0);
262                          WaitForSingleObject(c->scp.thread, INFINITE);                          DestroyWindow(c->scp.progress);
263                          CloseHandle(c->scp.thread);                          c->scp.progress = NULL;
                         c->scp.thread = (HANDLE)-1L;  
264                  }                  }
265                    fclose(c->scp.sendfp);
266          }          }
267    
268          memset(c, 0, sizeof(Channel_t));          memset(c, 0, sizeof(Channel_t));
# Line 332  void ssh_heartbeat_lock_finalize(void) Line 334  void ssh_heartbeat_lock_finalize(void)
334    
335  void ssh_heartbeat_lock(void)  void ssh_heartbeat_lock(void)
336  {  {
337          EnterCriticalSection(&g_ssh_heartbeat_lock);          //EnterCriticalSection(&g_ssh_heartbeat_lock);
338  }  }
339    
340  void ssh_heartbeat_unlock(void)  void ssh_heartbeat_unlock(void)
341  {  {
342          LeaveCriticalSection(&g_ssh_heartbeat_lock);          //LeaveCriticalSection(&g_ssh_heartbeat_lock);
343  }  }
344    
345  static void ssh_blocking_send_lock(void)  static void ssh_blocking_send_lock(void)
346  {  {
347          EnterCriticalSection(&g_ssh_blocking_send_lock);          //EnterCriticalSection(&g_ssh_blocking_send_lock);
348  }  }
349    
350  static void ssh_blocking_send_unlock(void)  static void ssh_blocking_send_unlock(void)
351  {  {
352          LeaveCriticalSection(&g_ssh_blocking_send_lock);          //LeaveCriticalSection(&g_ssh_blocking_send_lock);
353  }  }
354    
355    
# Line 6412  static unsigned __stdcall ssh_heartbeat_ Line 6414  static unsigned __stdcall ssh_heartbeat_
6414    
6415  static void start_ssh_heartbeat_thread(PTInstVar pvar)  static void start_ssh_heartbeat_thread(PTInstVar pvar)
6416  {  {
6417          HANDLE thread;          HANDLE thread = (HANDLE)-1;
6418          unsigned tid;          //unsigned tid;
6419    
6420            // TTSSHは thread-safe ではないのでスレッドは禁止 (yutaka)
6421    #if 0
6422          thread = (HANDLE)_beginthreadex(NULL, 0, ssh_heartbeat_thread, pvar, 0, &tid);          thread = (HANDLE)_beginthreadex(NULL, 0, ssh_heartbeat_thread, pvar, 0, &tid);
6423    #endif
6424          if (thread == (HANDLE)-1) {          if (thread == (HANDLE)-1) {
6425                  // TODO:                  // TODO:
6426          }          }
# Line 7018  static void do_SSH2_adjust_window_size(P Line 7023  static void do_SSH2_adjust_window_size(P
7023  }  }
7024    
7025    
7026    void ssh2_channel_remote_close(PTInstVar pvar, Channel_t *c)
7027    {
7028            if (SSHv2(pvar)) {
7029                    buffer_t *msg;
7030                    unsigned char *outmsg;
7031                    int len;
7032    
7033                    // SSH2 serverにchannel closeを伝える
7034                    msg = buffer_init();
7035                    if (msg == NULL) {
7036                            // TODO: error check
7037                            return;
7038                    }
7039                    buffer_put_int(msg, c->remote_id);
7040    
7041                    len = buffer_len(msg);
7042                    outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_CLOSE, len);
7043                    memcpy(outmsg, buffer_ptr(msg), len);
7044                    finish_send_packet(pvar);
7045                    buffer_free(msg);
7046            }
7047    }
7048    
7049    #define WM_START_SENDING_FILE (WM_USER + 1)
7050    
7051  typedef struct scp_thread_parm {  typedef struct scp_thread_parm {
7052          PTInstVar pvar;          PTInstVar pvar;
7053          Channel_t *c;          Channel_t *c;
7054  } scp_thread_parm_t;  } scp_thread_parm_t;
7055    
7056  static unsigned __stdcall ssh_scp_thread(void FAR * p)  static LRESULT CALLBACK ssh_scp_dlg_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
7057  {  {
7058          scp_thread_parm_t *parm = (scp_thread_parm_t *)p;          const int RWIN_TIMEOUT = 100;  // 100 msec
7059          PTInstVar pvar = parm->pvar;          const int SEND_TIMEOUT = 1;    // 1 msec
7060          Channel_t *c = parm->c;          const int IDC_TIMER = 1;
7061            static int instance = 0;
7062            static PTInstVar pvar = NULL;
7063            static Channel_t *c = NULL;
7064            static long long total_size = 0;
7065          char buf[8192];          char buf[8192];
7066          size_t ret;          size_t ret;
7067          long long total_size = 0;          scp_thread_parm_t *parm;
7068    
7069          do {          switch (msg) {
7070                  // ファイルから読み込んだデータはかならずサーバへ送信する。                  case WM_INITDIALOG:
7071                  ret = fread(buf, 1, sizeof(buf), c->scp.sendfp);                          if (instance > 0) {
7072                  if (ret == 0)                                  EndDialog(hWnd, 0);
7073                          break;                          } else {
7074                                    instance++;
7075                            }
7076                            return FALSE;
7077    
7078                    case WM_TIMER:
7079                            {
7080                            char s[80];
7081    
                 do {  
7082                          // socket or channelがクローズされたらスレッドを終わる                          // socket or channelがクローズされたらスレッドを終わる
7083                          if (pvar->socket == INVALID_SOCKET || c->scp.state == SCP_CLOSING || c->used == 0)                          if (pvar->socket == INVALID_SOCKET || c->scp.state == SCP_CLOSING || c->used == 0)
7084                                  goto done;                                  goto end;
7085    
7086                          // サーバのウィンドウに余裕がない場合は、送信しない。SSH2_send_channel_data()で遅延送信処理が                          if (sizeof(buf) > c->remote_window) {
7087                          // あるが、SCPスレッドとメインスレッドは別コンテキストであるため、SCPスレッドから遅延送信処理を                                  SetTimer(hWnd, 1, RWIN_TIMEOUT, 0);
7088                          // 行おうとしてもうまく動かない。                                  return TRUE;
                         if (ret > c->remote_window) {  
                                 Sleep(100); // yield  
7089                          }                          }
                 } while (ret > c->remote_window);  
7090    
7091                  // 別コンテキストで、SSHのシーケンスへ割り込まないようにロックを取る。                          // ファイルから読み込んだデータはかならずサーバへ送信する。
7092                  ssh_heartbeat_lock();                          ret = fread(buf, 1, sizeof(buf), c->scp.sendfp);
7093                  SSH2_send_channel_data(pvar, c, buf, ret);                          if (ret == 0)
7094                  ssh_heartbeat_unlock();                                  goto eof;
7095                            SSH2_send_channel_data(pvar, c, buf, ret);
7096                            total_size += ret;
7097    
7098                            _snprintf_s(s, sizeof(s), _TRUNCATE, "%lld / %lld (%d%%)", total_size, (long long)c->scp.filestat.st_size,
7099                                    (100 * total_size / c->scp.filestat.st_size)%100 );
7100                            SendMessage(GetDlgItem(hWnd, IDC_PROGRESS), WM_SETTEXT, 0, (LPARAM)s);
7101                            goto retry;
7102    
7103    eof:
7104                            SSH2_send_channel_data(pvar, c, "\0", 1);
7105                            c->scp.state = SCP_DATA;
7106                            assert(total_size == c->scp.filestat.st_size);
7107    end:
7108                            c->scp.state = SCP_DATA;
7109                            PostMessage(hWnd, WM_CLOSE, 0, 0);
7110                            return TRUE;
7111    
7112                  total_size += ret;  retry:
7113                            SetTimer(hWnd, IDC_TIMER, SEND_TIMEOUT, 0);
7114                            }
7115                            return TRUE;
7116                            break;
7117    
7118          } while (ret >= sizeof(buf));                  case WM_START_SENDING_FILE:
7119                            {
7120                            parm = (scp_thread_parm_t *)wp;
7121                            pvar = parm->pvar;
7122                            c = parm->c;
7123                            free(parm);   // free!
7124                            total_size = 0;
7125    
7126          // EOF                          SendMessage(GetDlgItem(hWnd, IDC_FILENAME), WM_SETTEXT, 0, (LPARAM)c->scp.sendfile);
         SSH2_send_channel_data(pvar, c, "\0", 1);  
         c->scp.state = SCP_DATA;  
7127    
7128          assert(total_size == c->scp.filestat.st_size);                          SetTimer(hWnd, 1, 100, 0);
7129                            }
7130                            return TRUE;
7131                            break;
7132    
7133  done:                  case WM_COMMAND:
7134          free(p);                          switch (wp) {
7135                            }
7136    
7137          return 0;                          switch (LOWORD(wp)) {
7138                                    case IDOK:
7139                                            {
7140                                            return TRUE;
7141                                            }
7142    
7143                                    case IDCANCEL:
7144                                            ssh2_channel_remote_close(pvar, c);
7145                                            PostMessage(hWnd, WM_CLOSE, 0, 0);
7146                                            //EndDialog(hWnd, 0);
7147                                            return TRUE;
7148                                    default:
7149                                            return FALSE;
7150                            }
7151                            break;
7152    
7153                    case WM_CLOSE:
7154                            KillTimer(hWnd, IDC_TIMER);
7155                            EndDialog(hWnd, 0);
7156                            return TRUE;
7157    
7158                    case WM_DESTROY:
7159                            instance--;
7160                            return TRUE;
7161    
7162                    default:
7163                            return FALSE;
7164            }
7165            return TRUE;
7166  }  }
7167    
7168    
# Line 7143  static BOOL handle_SSH2_channel_data(PTI Line 7236  static BOOL handle_SSH2_channel_data(PTI
7236                                  SSH2_send_channel_data(pvar, c, buf, strlen(buf));                                  SSH2_send_channel_data(pvar, c, buf, strlen(buf));
7237    
7238                          } else if (c->scp.state == SCP_FILEINFO) {                          } else if (c->scp.state == SCP_FILEINFO) {
                                 HANDLE thread;  
                                 unsigned tid;  
7239                                  scp_thread_parm_t *parm = malloc(sizeof(scp_thread_parm_t));                                  scp_thread_parm_t *parm = malloc(sizeof(scp_thread_parm_t));
7240                                    HWND hDlgWnd;
7241    
7242                                  if (parm == NULL) {                                  if (parm == NULL) {
7243                                          // TODO:                                          // TODO:
# Line 7153  static BOOL handle_SSH2_channel_data(PTI Line 7245  static BOOL handle_SSH2_channel_data(PTI
7245                                  parm->pvar = pvar;                                  parm->pvar = pvar;
7246                                  parm->c = c;                                  parm->c = c;
7247    
7248                                  thread = (HANDLE)_beginthreadex(NULL, 0, ssh_scp_thread, parm, 0, &tid);                                  hDlgWnd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_SSHSCP_PROGRESS),
7249                                  if (thread == (HANDLE)-1) {                                 pvar->cv->HWin, (DLGPROC)ssh_scp_dlg_proc);
7250                                          // TODO:                                  if (hDlgWnd != NULL) {
7251                                            c->scp.progress = hDlgWnd;
7252                                            ShowWindow(hDlgWnd, SW_SHOW);
7253                                            SendMessage(hDlgWnd, WM_START_SENDING_FILE, (WPARAM)parm, 0);
7254                                  }                                  }
                                 c->scp.thread = thread;  
7255    
7256                          } else if (c->scp.state == SCP_DATA) {                          } else if (c->scp.state == SCP_DATA) {
7257                                  // 送信完了                                  // 送信完了
7258                                  ssh2_channel_delete(c);  // free channel                                  ssh2_channel_delete(c);  // free channel
7259    
7260                                  MessageBox(NULL, "SCP sending done.", "TTSSH", MB_OK);                                  //MessageBox(NULL, "SCP sending done.", "TTSSH", MB_OK);
7261                          }                          }
7262    
7263                  } else {  // error                  } else {  // error
7264                          char msg[2048];                          char msg[2048];
7265                          unsigned int i;                          unsigned int i, max;
7266    
7267                          for (i = 0 ; i < str_len ; i++) {                          if (str_len > sizeof(msg))
7268                                    max = sizeof(msg);
7269                            else
7270                                    max = str_len;
7271                            for (i = 0 ; i < max ; i++) {
7272                                  msg[i] = data[i];                                  msg[i] = data[i];
7273                          }                          }
7274                          msg[i] = '\0';                          msg[i] = '\0';
7275    
7276                            ssh2_channel_remote_close(pvar, c);
7277                          ssh2_channel_delete(c);  // free channel                          ssh2_channel_delete(c);  // free channel
7278    
7279                          MessageBox(NULL, msg, "TTSSH: SCP error", MB_OK | MB_ICONEXCLAMATION);                          MessageBox(NULL, msg, "TTSSH: SCP error", MB_OK | MB_ICONEXCLAMATION);

Legend:
Removed from v.3074  
changed lines
  Added in v.3075

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26