TransferSocket.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968
  1. //---------------------------------------------------------------------------
  2. #include "FileZillaPCH.h"
  3. #include "TransferSocket.h"
  4. #include "MainThread.h"
  5. #include "AsyncProxySocketLayer.h"
  6. #ifndef MPEXT_NO_GSS
  7. #include "AsyncGssSocketLayer.h"
  8. #endif
  9. #define BUFSIZE 16384
  10. #define STATE_WAITING 0
  11. #define STATE_STARTING 1
  12. #define STATE_STARTED 2
  13. /////////////////////////////////////////////////////////////////////////////
  14. // CTransferSocket
  15. CTransferSocket::CTransferSocket(CFtpControlSocket *pOwner, int nMode)
  16. {
  17. DebugAssert(pOwner);
  18. InitIntern(pOwner->GetIntern());
  19. m_pOwner = pOwner;
  20. m_nMode = nMode;
  21. m_nTransferState = STATE_WAITING;
  22. m_bCheckTimeout = FALSE;
  23. m_pBuffer = 0;
  24. m_bufferpos = 0;
  25. m_pFile = 0;
  26. m_OnTransferOut = NULL;
  27. m_OnTransferIn = NULL;
  28. m_bListening = FALSE;
  29. m_bSentClose = FALSE;
  30. m_nInternalMessageID = 0;
  31. m_transferdata.transfersize = 0;
  32. m_transferdata.transferleft = 0;
  33. m_uploaded = 0;
  34. m_nNotifyWaiting = 0;
  35. m_bActivationPending = false;
  36. m_LastSendBufferUpdate = 0;
  37. UpdateStatusBar(true);
  38. m_pProxyLayer = NULL;
  39. m_pSslLayer = NULL;
  40. #ifndef MPEXT_NO_GSS
  41. m_pGssLayer = NULL;
  42. #endif
  43. if (m_nMode & CSMODE_LIST)
  44. {
  45. const bool mlst = false;
  46. m_pListResult = m_pOwner->CreateListResult(mlst);
  47. }
  48. else
  49. m_pListResult = 0;
  50. m_LastUpdateTime.QuadPart = 0;
  51. }
  52. CTransferSocket::~CTransferSocket()
  53. {
  54. delete [] m_pBuffer;
  55. GetIntern()->PostMessage(FZ_MSG_MAKEMSG(FZ_MSG_TRANSFERSTATUS, 0), 0);
  56. Close();
  57. RemoveAllLayers();
  58. delete m_pProxyLayer;
  59. delete m_pSslLayer;
  60. #ifndef MPEXT_NO_GSS
  61. delete m_pGssLayer;
  62. #endif
  63. m_pOwner->RemoveActiveTransfer();
  64. delete m_pListResult;
  65. }
  66. _int64 CTransferSocket::GetTransferSize(CFtpControlSocket::transferDirection direction, bool & beenWaiting)
  67. {
  68. if (GetState() != closed)
  69. return m_pOwner->GetAbleToTransferSize(direction, beenWaiting);
  70. else
  71. return BUFSIZE;
  72. }
  73. /////////////////////////////////////////////////////////////////////////////
  74. // Member-Funktion CTransferSocket
  75. void CTransferSocket::OnReceive(int nErrorCode)
  76. {
  77. if (GetState() != connected && GetState() != attached && GetState() != closed)
  78. return;
  79. if (m_nTransferState == STATE_WAITING)
  80. {
  81. m_nNotifyWaiting |= FD_READ;
  82. return;
  83. }
  84. if (m_bSentClose)
  85. return;
  86. if (m_bListening)
  87. return;
  88. if (m_nMode&CSMODE_LIST)
  89. {
  90. if (m_nTransferState == STATE_STARTING)
  91. OnConnect(0);
  92. std::vector<char> Buffer(BUFSIZE);
  93. int numread = CAsyncSocketEx::Receive(&Buffer[0], Buffer.size());
  94. if (numread != SOCKET_ERROR && numread)
  95. {
  96. m_LastActiveTime = CTime::CreateForCurrentTime();
  97. m_pListResult->AddData(&Buffer[0], numread);
  98. m_transferdata.transfersize += numread;
  99. t_ffam_transferstatus *status = new t_ffam_transferstatus;
  100. status->bFileTransfer = FALSE;
  101. status->transfersize = -1;
  102. status->bytes = m_transferdata.transfersize;
  103. GetIntern()->PostMessage(FZ_MSG_MAKEMSG(FZ_MSG_TRANSFERSTATUS, 0), (LPARAM)status);
  104. }
  105. if (!numread)
  106. {
  107. CloseAndEnsureSendClose(0);
  108. }
  109. if (numread == SOCKET_ERROR)
  110. {
  111. int nError = GetLastError();
  112. if (nError == WSAENOTCONN)
  113. {
  114. //Not yet connected
  115. return;
  116. }
  117. else if (m_pSslLayer && nError == WSAESHUTDOWN)
  118. {
  119. // Do nothing, wait for shutdown complete notification.
  120. return;
  121. }
  122. else if (nError != WSAEWOULDBLOCK)
  123. {
  124. LogError(nError);
  125. CloseAndEnsureSendClose(CSMODE_TRANSFERERROR);
  126. }
  127. }
  128. }
  129. else if (m_nMode & CSMODE_DOWNLOAD)
  130. {
  131. if (m_nTransferState == STATE_STARTING)
  132. OnConnect(0);
  133. bool beenWaiting = false;
  134. _int64 ableToRead = GetTransferSize(CFtpControlSocket::download, beenWaiting);
  135. if (!beenWaiting)
  136. DebugAssert(ableToRead);
  137. else if (!ableToRead)
  138. {
  139. TriggerEvent(FD_READ);
  140. return;
  141. }
  142. if (!m_pBuffer)
  143. m_pBuffer = new char[BUFSIZE];
  144. int numread = CAsyncSocketEx::Receive(m_pBuffer, static_cast<int>(ableToRead));
  145. if (numread!=SOCKET_ERROR)
  146. {
  147. m_pOwner->SpeedLimitAddTransferredBytes(CFtpControlSocket::download, numread);
  148. }
  149. if (!numread)
  150. {
  151. CloseAndEnsureSendClose(0);
  152. return;
  153. }
  154. if (numread == SOCKET_ERROR)
  155. {
  156. int nError = GetLastError();
  157. if (nError == WSAENOTCONN)
  158. {
  159. //Not yet connected
  160. return;
  161. }
  162. else if (m_pSslLayer && nError == WSAESHUTDOWN)
  163. {
  164. // Do nothing, wait for shutdown complete notification.
  165. return;
  166. }
  167. else if (nError != WSAEWOULDBLOCK)
  168. {
  169. LogError(nError);
  170. CloseAndEnsureSendClose(CSMODE_TRANSFERERROR);
  171. }
  172. UpdateStatusBar(true);
  173. return;
  174. }
  175. int written = 0;
  176. m_LastActiveTime = CTime::CreateForCurrentTime();
  177. try
  178. {
  179. WriteData(m_pBuffer, numread);
  180. written = numread;
  181. }
  182. catch (CFileException * e)
  183. {
  184. LPTSTR msg = new TCHAR[BUFSIZE];
  185. if (e->GetErrorMessage(msg, BUFSIZE))
  186. m_pOwner->ShowStatus(msg, FZ_LOG_ERROR);
  187. delete [] msg;
  188. CloseAndEnsureSendClose(CSMODE_TRANSFERERROR);
  189. return;
  190. }
  191. m_transferdata.transferleft -= written;
  192. UpdateStatusBar(false);
  193. }
  194. }
  195. void CTransferSocket::SetBuffers()
  196. {
  197. /* Set internal socket send buffer
  198. * this should fix the speed problems some users have reported
  199. */
  200. m_SendBuf = GetOptionVal(OPTION_MPEXT_SNDBUF);
  201. if (m_SendBuf > 0)
  202. {
  203. DWORD value;
  204. int len = sizeof(value);
  205. GetSockOpt(SO_SNDBUF, &value, &len);
  206. if (value < m_SendBuf)
  207. {
  208. SetSockOpt(SO_SNDBUF, &m_SendBuf, sizeof(m_SendBuf));
  209. }
  210. // For now we increase receive buffer, whenever send buffer is set.
  211. // The size is not configurable. The constant taken from FZ.
  212. value = 0;
  213. len = sizeof(value);
  214. GetSockOpt(SO_RCVBUF, &value, &len);
  215. int rcvbuf = 4 * 1024 * 1024;
  216. if (value < rcvbuf)
  217. {
  218. value = rcvbuf;
  219. SetSockOpt(SO_RCVBUF, &value, sizeof(value));
  220. }
  221. }
  222. }
  223. void CTransferSocket::OnAccept(int nErrorCode)
  224. {
  225. m_bListening=FALSE;
  226. CAsyncSocketEx tmp;
  227. Accept(tmp);
  228. SOCKET socket=tmp.Detach();
  229. CAsyncSocketEx::Close();
  230. Attach(socket);
  231. SetBuffers();
  232. if (m_nTransferState == STATE_STARTING)
  233. {
  234. Start();
  235. }
  236. }
  237. void CTransferSocket::ConfigureSocket()
  238. {
  239. // Note that FileZilla re-enables Nagle's alg during TLS negotiation.
  240. // Following post claims that TCP_NODELAY
  241. // has to be set before connect()
  242. // https://stackoverflow.com/q/22583941/850848#25871250
  243. int nodelay = GetOptionVal(OPTION_MPEXT_NODELAY);
  244. if (nodelay != 0)
  245. {
  246. BOOL bvalue = TRUE;
  247. SetSockOpt(TCP_NODELAY, &bvalue, sizeof(bvalue), IPPROTO_TCP);
  248. }
  249. CAsyncSocketEx::ConfigureSocket();
  250. }
  251. void CTransferSocket::OnConnect(int nErrorCode)
  252. {
  253. if (nErrorCode)
  254. {
  255. TCHAR buffer[1000];
  256. memset(buffer, 0, sizeof(buffer));
  257. FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, nErrorCode, 0, buffer, 999, 0);
  258. CString str;
  259. str.Format(IDS_ERRORMSG_CANTOPENTRANSFERCHANNEL,buffer);
  260. str.Replace( L"\n", L"\0" );
  261. str.Replace( L"\r", L"\0" );
  262. m_pOwner->ShowStatus(str, FZ_LOG_ERROR);
  263. CloseAndEnsureSendClose(CSMODE_TRANSFERERROR);
  264. }
  265. else
  266. {
  267. SetBuffers();
  268. m_pOwner->ShowStatus(L"Data connection opened", FZ_LOG_INFO);
  269. }
  270. if (m_nTransferState == STATE_WAITING)
  271. {
  272. // OnReceive (invoked by m_nNotifyWaiting including FD_READ)
  273. // will call back to OnConnected (as we won't be connected yet).
  274. // This is needed for file transfers only, where SetActive is
  275. // called only after 1xx response to RETR (and similar) arrives.
  276. // But we get FD_CONNECT earlier, hence we get to this branch.
  277. // With directory listing, SetActive is called before Connect,
  278. // so we are already STATE_STARTING on FD_CONNECT.
  279. // It should probably behave the same in both scenarios.
  280. m_nNotifyWaiting |= FD_READ;
  281. }
  282. else if (m_nTransferState == STATE_STARTING)
  283. {
  284. Start();
  285. }
  286. }
  287. void CTransferSocket::Start()
  288. {
  289. m_nTransferState = STATE_STARTED;
  290. m_LastActiveTime=CTime::CreateForCurrentTime();
  291. if (m_pSslLayer)
  292. {
  293. AddLayer(m_pSslLayer);
  294. int res = m_pSslLayer->InitSSLConnection(true, m_pOwner->m_pSslLayer,
  295. GetOptionVal(OPTION_MPEXT_SSLSESSIONREUSE), CString(),
  296. m_pOwner->m_pTools);
  297. if (res == SSL_FAILURE_INITSSL)
  298. {
  299. m_pOwner->ShowStatus(IDS_ERRORMSG_CANTINITSSL, FZ_LOG_ERROR);
  300. }
  301. if (res)
  302. {
  303. CloseAndEnsureSendClose(CSMODE_TRANSFERERROR);
  304. return;
  305. }
  306. }
  307. #ifndef MPEXT_NO_GSS
  308. if (m_pGssLayer)
  309. {
  310. AddLayer(m_pGssLayer);
  311. }
  312. #endif
  313. }
  314. void CTransferSocket::OnClose(int nErrorCode)
  315. {
  316. if (m_nTransferState == STATE_WAITING)
  317. {
  318. m_nNotifyWaiting |= FD_CLOSE;
  319. return;
  320. }
  321. m_pOwner->ShowStatus(L"Data connection closed", FZ_LOG_PROGRESS);
  322. OnReceive(0);
  323. CloseAndEnsureSendClose(0);
  324. // Report pending transfer
  325. // (particularly during ascii downloads, when the transferred data might be larger than expected,
  326. // though possibly also when downloading a growing file)
  327. if (FLAGSET(m_nMode, CSMODE_DOWNLOAD))
  328. {
  329. UpdateStatusBar(true);
  330. }
  331. }
  332. int CTransferSocket::CheckForTimeout(int delay)
  333. {
  334. UpdateStatusBar(false);
  335. if (!m_bCheckTimeout)
  336. {
  337. // we are closed, so make sure the FTP control socket is itself checking for
  338. // timeout as we are not
  339. return 0;
  340. }
  341. CTimeSpan span = CTime::CreateForCurrentTime()-m_LastActiveTime;
  342. if (span.GetTotalSeconds()>=delay)
  343. {
  344. m_pOwner->ShowTimeoutError(IDS_DATA_CONNECTION);
  345. CloseAndEnsureSendClose(CSMODE_TRANSFERTIMEOUT);
  346. return 2;
  347. }
  348. return 1;
  349. }
  350. void CTransferSocket::SetState(int nState)
  351. {
  352. CAsyncSocketEx::SetState(nState);
  353. if (m_bActivationPending && Activate())
  354. {
  355. m_bActivationPending = false;
  356. }
  357. }
  358. bool CTransferSocket::Activate()
  359. {
  360. // Activation (OnSend => OnConnect) indirectly causes adding
  361. // of TLS layer, which needs connected underlying layers.
  362. // The code should be generic, but we particularly need it for this (TLS over proxy)
  363. // scenario only. So for a safety, we use it for the scenario only.
  364. bool Result =
  365. (GetState() == connected) || (GetState() == attached) ||
  366. (m_pSslLayer == NULL) || (m_pProxyLayer == NULL);
  367. if (Result)
  368. {
  369. if (m_nTransferState == STATE_WAITING)
  370. m_nTransferState = STATE_STARTING;
  371. m_bCheckTimeout = TRUE;
  372. m_LastActiveTime = CTime::CreateForCurrentTime();
  373. if (m_nNotifyWaiting & FD_READ)
  374. OnReceive(0);
  375. if (m_nNotifyWaiting & FD_WRITE)
  376. OnSend(0);
  377. if (m_nNotifyWaiting & FD_CLOSE)
  378. OnClose(0);
  379. }
  380. return Result;
  381. }
  382. void CTransferSocket::SetActive()
  383. {
  384. if (!Activate())
  385. {
  386. m_bActivationPending = true;
  387. }
  388. }
  389. void CTransferSocket::OnSend(int nErrorCode)
  390. {
  391. if (m_nTransferState == STATE_WAITING)
  392. {
  393. m_nNotifyWaiting |= FD_WRITE;
  394. return;
  395. }
  396. if (m_bSentClose)
  397. {
  398. return;
  399. }
  400. if (m_bListening)
  401. {
  402. return;
  403. }
  404. if (!(m_nMode&CSMODE_UPLOAD))
  405. {
  406. return;
  407. }
  408. if (m_nTransferState == STATE_STARTING)
  409. {
  410. OnConnect(0);
  411. }
  412. if (m_SendBuf > 0)
  413. {
  414. unsigned int Ticks = GetTickCount();
  415. if (Ticks - m_LastSendBufferUpdate >= 1000)
  416. {
  417. DWORD BufferLen = 0;
  418. DWORD OutLen = 0;
  419. if (WSAIoctl(m_SocketData.hSocket, SIO_IDEAL_SEND_BACKLOG_QUERY, NULL, 0, &BufferLen, sizeof(BufferLen), &OutLen, 0, 0) == 0)
  420. {
  421. DebugAssert(OutLen == sizeof(BufferLen));
  422. if (m_SendBuf < BufferLen)
  423. {
  424. LogMessage(FZ_LOG_PROGRESS, L"Increasing send buffer from %d to %d", m_SendBuf, BufferLen);
  425. m_SendBuf = BufferLen;
  426. SetSockOpt(SO_SNDBUF, &m_SendBuf, sizeof(m_SendBuf));
  427. }
  428. }
  429. m_LastSendBufferUpdate = Ticks;
  430. }
  431. }
  432. if (!m_pFile && (m_OnTransferIn == NULL))
  433. {
  434. return;
  435. }
  436. if (!m_pBuffer)
  437. m_pBuffer = new char[BUFSIZE];
  438. bool firstPass = true;
  439. while (TRUE)
  440. {
  441. bool beenWaiting = false;
  442. _int64 currentBufferSize = GetTransferSize(CFtpControlSocket::upload, beenWaiting);
  443. int numread;
  444. if ((currentBufferSize == 0) && (m_bufferpos == 0))
  445. {
  446. // Not allowed to send yet, try later
  447. TriggerEvent(FD_WRITE);
  448. return;
  449. }
  450. int readwanted = static_cast<int>(currentBufferSize - m_bufferpos);
  451. if (m_bufferpos < currentBufferSize)
  452. {
  453. numread = ReadDataFromFile(m_pBuffer + m_bufferpos, readwanted);
  454. if (numread < 0 )
  455. {
  456. return;
  457. }
  458. else if ((numread == 0) && (m_bufferpos == 0))
  459. {
  460. CloseOnShutDownOrError(0);
  461. return;
  462. }
  463. }
  464. else
  465. {
  466. numread = 0;
  467. }
  468. DebugAssert(numread>=0);
  469. DebugAssert(m_bufferpos>=0);
  470. int bufferlen = (numread + m_bufferpos);
  471. // Just to make the change noop, but the test should probably be done everytime
  472. if (firstPass)
  473. {
  474. DebugAssert(bufferlen <= BUFSIZE);
  475. if (bufferlen <= 0)
  476. {
  477. CloseOnShutDownOrError(0);
  478. return;
  479. }
  480. firstPass = false;
  481. }
  482. int numsent = Send(m_pBuffer, bufferlen);
  483. if (numsent != SOCKET_ERROR)
  484. {
  485. m_pOwner->SpeedLimitAddTransferredBytes(CFtpControlSocket::upload, numsent);
  486. m_LastActiveTime = CTime::CreateForCurrentTime();
  487. m_transferdata.transferleft -= numsent;
  488. m_uploaded += numsent;
  489. }
  490. if (numsent==SOCKET_ERROR || !numsent)
  491. {
  492. int nError = GetLastError();
  493. if (nError == WSAENOTCONN)
  494. {
  495. //Not yet connected
  496. m_bufferpos += numread;
  497. return;
  498. }
  499. else if (nError == WSAEWOULDBLOCK)
  500. {
  501. m_bufferpos += numread;
  502. }
  503. else if (m_pSslLayer && nError == WSAESHUTDOWN)
  504. {
  505. m_bufferpos += numread;
  506. // Do nothing, wait for shutdown complete notification.
  507. return;
  508. }
  509. else
  510. {
  511. LogError(nError);
  512. CloseOnShutDownOrError(CSMODE_TRANSFERERROR);
  513. }
  514. UpdateStatusBar(true);
  515. return;
  516. }
  517. else
  518. {
  519. int pos = bufferlen - numsent;
  520. if (pos < 0 || (numsent + pos) > BUFSIZE)
  521. {
  522. LogMessage(FZ_LOG_WARNING, L"Index out of range");
  523. CloseOnShutDownOrError(CSMODE_TRANSFERERROR);
  524. return;
  525. }
  526. else if ((pos == 0) && // all data in buffer were sent
  527. // was read less then wanted (eof reached?)
  528. // (should be safe to always just do (numread <= 0), but limiting the impact of the change for now)
  529. (numread < ((m_OnTransferIn != NULL) ? 1 : readwanted)) &&
  530. (m_bufferpos != currentBufferSize)) // and it's not because the buffer is full?
  531. {
  532. // With TLS 1.3 we can get back
  533. m_bufferpos = 0;
  534. CloseOnShutDownOrError(0);
  535. return;
  536. }
  537. else if (!pos)
  538. {
  539. m_bufferpos = 0;
  540. }
  541. else
  542. {
  543. memmove(m_pBuffer, m_pBuffer+numsent, pos);
  544. m_bufferpos=pos;
  545. }
  546. }
  547. //Check if there are other commands in the command queue.
  548. MSG msg;
  549. if (PeekMessage(&msg, 0, m_nInternalMessageID, m_nInternalMessageID, PM_NOREMOVE))
  550. {
  551. //Send resume message
  552. LogMessage(FZ_LOG_DEBUG, L"Message waiting in queue, resuming later");
  553. TriggerEvent(FD_WRITE);
  554. UpdateStatusBar(false);
  555. return;
  556. }
  557. UpdateStatusBar(false);
  558. }
  559. }
  560. void CTransferSocket::UpdateStatusBar(bool forceUpdate)
  561. {
  562. if (m_nTransferState != STATE_STARTED)
  563. return;
  564. if (!forceUpdate)
  565. {
  566. //Don't flood the main window with messages
  567. //Else performance would be really low
  568. LARGE_INTEGER curtime;
  569. LARGE_INTEGER freq;
  570. QueryPerformanceFrequency(&freq);
  571. QueryPerformanceCounter(&curtime);
  572. if (((curtime.QuadPart-m_LastUpdateTime.QuadPart) < (freq.QuadPart/15) ) )
  573. return;
  574. m_LastUpdateTime = curtime;
  575. }
  576. //Update the statusbar
  577. t_ffam_transferstatus *status=new t_ffam_transferstatus;
  578. status->bFileTransfer = m_nMode & (CSMODE_DOWNLOAD | CSMODE_UPLOAD);
  579. status->transfersize = m_transferdata.transfersize;
  580. status->bytes=m_transferdata.transfersize-m_transferdata.transferleft;
  581. GetIntern()->PostMessage(FZ_MSG_MAKEMSG(FZ_MSG_TRANSFERSTATUS, 0), (LPARAM)status);
  582. }
  583. BOOL CTransferSocket::Create(BOOL bUseSsl)
  584. {
  585. if (bUseSsl)
  586. {
  587. m_pSslLayer = new CAsyncSslSocketLayer;
  588. m_pSslLayer->SetClientCertificate(m_pOwner->m_CurrentServer.Certificate, m_pOwner->m_CurrentServer.PrivateKey);
  589. }
  590. int nProxyType = GetOptionVal(OPTION_PROXYTYPE);
  591. if (nProxyType != PROXYTYPE_NOPROXY)
  592. {
  593. USES_CONVERSION;
  594. m_pProxyLayer = new CAsyncProxySocketLayer;
  595. m_pProxyLayer->SetProxy(
  596. nProxyType, T2CA(GetOption(OPTION_PROXYHOST)), GetOptionVal(OPTION_PROXYPORT),
  597. GetOptionVal(OPTION_PROXYUSELOGON), T2CA(GetOption(OPTION_PROXYUSER)), T2CA(GetOption(OPTION_PROXYPASS)));
  598. AddLayer(m_pProxyLayer);
  599. }
  600. if (!GetOptionVal(OPTION_LIMITPORTRANGE))
  601. {
  602. if (!CAsyncSocketEx::Create(0, SOCK_STREAM, FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE, 0, GetFamily()))
  603. return FALSE;
  604. return TRUE;
  605. }
  606. else
  607. {
  608. int min=GetOptionVal(OPTION_PORTRANGELOW);
  609. int max=GetOptionVal(OPTION_PORTRANGEHIGH);
  610. if (min > max)
  611. {
  612. m_pOwner->ShowStatus(IDS_ERRORMSG_CANTCREATEDUETOPORTRANGE,FZ_LOG_ERROR);
  613. return FALSE;
  614. }
  615. int startport=static_cast<int>(min+((double)rand()*(max-min))/(RAND_MAX+1));
  616. int port=startport;
  617. // Failure to create the socket, calls Close(), which resets the family. We want to keep trying the original faimily with each port.
  618. // Only with the specific family set, the Create actually does bind(), without which the port testing does not work.
  619. int family = GetFamily();
  620. DebugAssert(family != AF_UNSPEC);
  621. while (!CAsyncSocketEx::Create(port, SOCK_STREAM, FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE, 0, family))
  622. {
  623. port++;
  624. if (port>max)
  625. port=min;
  626. if (port==startport)
  627. {
  628. m_pOwner->ShowStatus(IDS_ERRORMSG_CANTCREATEDUETOPORTRANGE, FZ_LOG_ERROR);
  629. return FALSE;
  630. }
  631. }
  632. LogMessage(FZ_LOG_INFO, L"Selected port %d", port);
  633. }
  634. return TRUE;
  635. }
  636. void CTransferSocket::Close()
  637. {
  638. m_bCheckTimeout = FALSE;
  639. CAsyncSocketEx::Close();
  640. }
  641. int CTransferSocket::OnLayerCallback(std::list<t_callbackMsg>& callbacks)
  642. {
  643. for (std::list<t_callbackMsg>::iterator iter = callbacks.begin(); iter != callbacks.end(); iter++)
  644. {
  645. if (iter->nType == LAYERCALLBACK_STATECHANGE)
  646. {
  647. if (CAsyncSocketEx::LogStateChange(iter->nParam1, iter->nParam2))
  648. {
  649. const TCHAR * state2Desc = CAsyncSocketEx::GetStateDesc(iter->nParam2);
  650. const TCHAR * state1Desc = CAsyncSocketEx::GetStateDesc(iter->nParam1);
  651. if (iter->pLayer == m_pProxyLayer)
  652. LogMessage(FZ_LOG_INFO, L"Proxy layer changed state from %s to %s", state2Desc, state1Desc);
  653. else if (iter->pLayer == m_pSslLayer)
  654. LogMessage(FZ_LOG_INFO, L"TLS layer changed state from %s to %s", state2Desc, state1Desc);
  655. #ifndef MPEXT_NO_GSS
  656. else if (iter->pLayer == m_pGssLayer)
  657. LogMessage(FZ_LOG_INFO, L"GSS layer changed state from %s to %s", state2Desc, state1Desc);
  658. #endif
  659. else
  660. LogMessage(FZ_LOG_INFO, L"Layer @ %d changed state from %s to %s", iter->pLayer, state2Desc, state1Desc);
  661. }
  662. }
  663. else if (iter->nType == LAYERCALLBACK_LAYERSPECIFIC)
  664. {
  665. if (iter->pLayer == m_pProxyLayer)
  666. {
  667. switch (iter->nParam1)
  668. {
  669. case PROXYERROR_NOERROR:
  670. m_pOwner->ShowStatus(IDS_PROXY_CONNECTED, FZ_LOG_PROGRESS);
  671. break;
  672. case PROXYERROR_NOCONN:
  673. m_pOwner->ShowStatus(IDS_ERRORMSG_PROXY_NOCONN, FZ_LOG_ERROR);
  674. break;
  675. case PROXYERROR_REQUESTFAILED:
  676. m_pOwner->ShowStatus(IDS_ERRORMSG_PROXY_REQUESTFAILED, FZ_LOG_ERROR);
  677. break;
  678. case PROXYERROR_AUTHTYPEUNKNOWN:
  679. m_pOwner->ShowStatus(IDS_ERRORMSG_PROXY_AUTHTYPEUNKNOWN, FZ_LOG_ERROR);
  680. break;
  681. case PROXYERROR_AUTHFAILED:
  682. m_pOwner->ShowStatus(IDS_ERRORMSG_PROXY_AUTHFAILED, FZ_LOG_ERROR);
  683. break;
  684. case PROXYERROR_AUTHNOLOGON:
  685. m_pOwner->ShowStatus(IDS_ERRORMSG_PROXY_AUTHNOLOGON, FZ_LOG_ERROR);
  686. break;
  687. case PROXYERROR_CANTRESOLVEHOST:
  688. m_pOwner->ShowStatus(IDS_ERRORMSG_PROXY_CANTRESOLVEHOST, FZ_LOG_ERROR);
  689. break;
  690. default:
  691. LogMessage(FZ_LOG_WARNING, L"Unknown proxy error");
  692. }
  693. }
  694. else if (iter->pLayer == m_pSslLayer)
  695. {
  696. switch (iter->nParam1)
  697. {
  698. case SSL_INFO:
  699. switch(iter->nParam2)
  700. {
  701. case SSL_INFO_SHUTDOWNCOMPLETE:
  702. CloseAndEnsureSendClose(0);
  703. break;
  704. case SSL_INFO_ESTABLISHED:
  705. m_pOwner->ShowStatus(IDS_STATUSMSG_SSLESTABLISHEDTRANSFER, FZ_LOG_PROGRESS);
  706. TriggerEvent(FD_FORCEREAD);
  707. break;
  708. }
  709. break;
  710. case SSL_FAILURE:
  711. {
  712. int Mode = CSMODE_TRANSFERERROR;
  713. switch (iter->nParam2)
  714. {
  715. case SSL_FAILURE_UNKNOWN:
  716. m_pOwner->ShowStatus(IDS_ERRORMSG_UNKNOWNSSLERROR, FZ_LOG_ERROR);
  717. // This may indicate re-key failure, make sure we retry
  718. Mode |= CSMODE_TRANSFERTIMEOUT;
  719. break;
  720. case SSL_FAILURE_ESTABLISH:
  721. m_pOwner->ShowStatus(IDS_ERRORMSG_CANTESTABLISHSSLCONNECTION, FZ_LOG_ERROR);
  722. break;
  723. case SSL_FAILURE_INITSSL:
  724. m_pOwner->ShowStatus(IDS_ERRORMSG_CANTINITSSL, FZ_LOG_ERROR);
  725. break;
  726. }
  727. CloseAndEnsureSendClose(Mode);
  728. }
  729. break;
  730. case SSL_VERIFY_CERT:
  731. t_SslCertData data;
  732. LPCTSTR CertError = NULL;
  733. if (m_pSslLayer->GetPeerCertificateData(data, CertError))
  734. m_pSslLayer->SetNotifyReply(data.priv_data, SSL_VERIFY_CERT, 1);
  735. else
  736. {
  737. CString str;
  738. str.Format(TLS_CERT_DECODE_ERROR, CertError);
  739. m_pOwner->ShowStatus(str, FZ_LOG_ERROR);
  740. CloseAndEnsureSendClose(CSMODE_TRANSFERERROR);
  741. }
  742. break;
  743. }
  744. }
  745. #ifndef MPEXT_NO_GSS
  746. else if (iter->pLayer == m_pGssLayer)
  747. {
  748. USES_CONVERSION;
  749. switch (iter->nParam1)
  750. {
  751. case GSS_INFO:
  752. LogMessageRaw(FZ_LOG_INFO, A2CT(iter->str));
  753. break;
  754. case GSS_ERROR:
  755. LogMessageRaw(FZ_LOG_APIERROR, A2CT(iter->str));
  756. break;
  757. case GSS_SHUTDOWN_COMPLETE:
  758. CloseAndEnsureSendClose(0);
  759. break;
  760. }
  761. }
  762. #endif
  763. }
  764. delete [] iter->str;
  765. }
  766. return 0;
  767. }
  768. #ifndef MPEXT_NO_GSS
  769. void CTransferSocket::UseGSS(CAsyncGssSocketLayer *pGssLayer)
  770. {
  771. m_pGssLayer = new CAsyncGssSocketLayer;
  772. m_pGssLayer->InitTransferChannel(pGssLayer);
  773. }
  774. #endif
  775. void CTransferSocket::WriteData(const char * buffer, int len)
  776. {
  777. if (m_OnTransferOut != NULL)
  778. {
  779. m_OnTransferOut(NULL, reinterpret_cast<const unsigned char *>(m_pBuffer), len);
  780. }
  781. else
  782. {
  783. m_pFile->Write(m_pBuffer, len);
  784. }
  785. }
  786. int CTransferSocket::ReadData(char * buffer, int len)
  787. {
  788. int result;
  789. if (m_OnTransferIn != NULL)
  790. {
  791. result = m_OnTransferIn(NULL, reinterpret_cast<unsigned char *>(buffer), len);
  792. }
  793. else
  794. {
  795. result = m_pFile->Read(buffer, len);
  796. }
  797. LogMessage(FZ_LOG_INFO, L"Read %d bytes from file", result);
  798. return result;
  799. }
  800. // Used only once now
  801. int CTransferSocket::ReadDataFromFile(char *buffer, int len)
  802. {
  803. try
  804. {
  805. // Comparing to Filezilla 2, we do not do any translation locally,
  806. // leaving it onto the server (what Filezilla 3 seems to do too)
  807. const char Bom[4] = "\xEF\xBB\xBF";
  808. int BomLen = strlen(Bom);
  809. int read = ReadData(buffer, len);
  810. if (GetOptionVal(OPTION_MPEXT_REMOVE_BOM) &&
  811. m_transferdata.bType && (read >= BomLen) && (memcmp(buffer, Bom, BomLen) == 0))
  812. {
  813. memcpy(buffer, buffer + BomLen, read - BomLen);
  814. read -= BomLen;
  815. int read2 = ReadData(buffer + read, BomLen);
  816. if (read2 > 0)
  817. {
  818. read += read2;
  819. }
  820. }
  821. return read;
  822. }
  823. catch (CFileException* e)
  824. {
  825. TCHAR error[BUFSIZE];
  826. if (e->GetErrorMessage(error, BUFSIZE))
  827. m_pOwner->ShowStatus(error, FZ_LOG_ERROR);
  828. CloseOnShutDownOrError(CSMODE_TRANSFERERROR);
  829. return -1;
  830. }
  831. }
  832. void CTransferSocket::LogSocketMessageRaw(int nMessageType, LPCTSTR pMsg)
  833. {
  834. LogMessageRaw(nMessageType, pMsg);
  835. }
  836. int CTransferSocket::GetSocketOptionVal(int OptionID) const
  837. {
  838. return GetOptionVal(OptionID);
  839. }
  840. void CTransferSocket::EnsureSendClose(int Mode)
  841. {
  842. if (!m_bSentClose)
  843. {
  844. if (Mode != 0)
  845. {
  846. m_pOwner->ShowStatus(L"Data connection failed", FZ_LOG_INFO);
  847. m_nMode |= Mode;
  848. }
  849. else
  850. {
  851. m_pOwner->ShowStatus(L"Data connection closed", FZ_LOG_INFO);
  852. }
  853. m_bSentClose = TRUE;
  854. DebugCheck(m_pOwner->m_pOwner->PostThreadMessage(m_nInternalMessageID, FZAPI_THREADMSG_TRANSFEREND, m_nMode));
  855. }
  856. }
  857. void CTransferSocket::CloseAndEnsureSendClose(int Mode)
  858. {
  859. Close();
  860. EnsureSendClose(Mode);
  861. }
  862. void CTransferSocket::CloseOnShutDownOrError(int Mode)
  863. {
  864. if (ShutDown())
  865. {
  866. // It would probably be correct to remove this call, and wait for OnClose (FD_CLOSE),
  867. // where CloseAndEnsureSendClose is called too.
  868. // See https://learn.microsoft.com/en-us/windows/win32/winsock/graceful-shutdown-linger-options-and-socket-closure-2
  869. CloseAndEnsureSendClose(Mode);
  870. }
  871. else
  872. {
  873. int Error = GetLastError();
  874. if (Error != WSAEWOULDBLOCK)
  875. {
  876. // Log always or only when (Mode & CSMODE_TRANSFERERROR)?
  877. // Does it anyway make sense at all to call this with Mode == 0?
  878. LogError(Error);
  879. CloseAndEnsureSendClose(Mode);
  880. }
  881. }
  882. }