post by tommy @ 04 六月, 2009 19:13
一個多月之前, Pure-ftpd 推出了新的 1.0.22 版, 對我來說, 其中最重大的改變就是支援在 TLS/SSL 時也對傳送的資料加密. 所以... 我馬上就裝起來用了. 不過... 隔天確發現下載的檔案都有問題, 不過我試了幾個小檔案, 發現又很正常. 後來想到這兒的網路狀況有點不好, 或許是斷線後續傳造成的, 再測試一下, 果然經過續傳後, 檔案大小在傳送後就不一樣了.
改了一下, 寫了一些 log, 發現在使用 TLS/SSL 下傳檔案時, 是透過 mmap_send() 去處理, 而一般的情形是用 sendfile_send() 來處理. 而且在 sendfile_send() 裡頭, 是這樣處理續傳位置的:
#ifndef SENDFILE_NONE
int sendfile_send(int f, struct stat st, double *started)
{
off_t left;
off_t o;
# ifdef THROTTLING
double ended;
off_t transmitted = 0;
# endif
o = restartat;
while (o < st.st_size) {
但是在 mmap_send() 中是:
int mmap_send(int f, struct stat st, double *started)
{
off_t s;
off_t skip;
off_t o;
char *p, *buf;
off_t left;
# ifdef THROTTLING
double ended;
off_t transmitted = 0;
# endif
o = restartat & ~(map_size - 1);
skip = restartat - o;
while (o < st.st_size) {
至少在我家的 Debian 伺服器上頭, 上頭的運作是不正常的. 所以我就改了一下:
int mmap_send(int f, struct stat st, double *started)
{
off_t s;
off_t skip;
off_t o;
char *p, *buf;
off_t left;
# ifdef THROTTLING
double ended;
off_t transmitted = 0;
# endif
// twu2 20090523 begin
// why change the restart pos?
// o = restartat & ~(map_size - 1);
o = restartat;
// twu2 20090523 end
skip = restartat - o;
直接就使用 restartat 的值, 這樣子處理之後, 至少在 Debian 裡頭是正常的.
這個 patch 的內容如下:
diff -Nur src.orig/ftpd.c src/ftpd.c
--- src.orig/ftpd.c 2009-04-26 19:34:04.000000000 +0800
+++ src/ftpd.c 2009-06-04 18:55:25.024105416 +0800
@@ -3106,7 +3106,11 @@
off_t transmitted = 0;
# endif
- o = restartat & ~(map_size - 1);
+// twu2 20090523 begin
+// why change the restart pos?
+// o = restartat & ~(map_size - 1);
+ o = restartat;
+// twu2 20090523 end
skip = restartat - o;
while (o < st.st_size) {
# ifdef FTPWHO
檔案可以在這兒抓: http://www.teatime.com.tw/~tommy/mypatch/pureftpd_1.0.22_tls_resume.patch
有需要的可能要自行修改. 這個 patch 我也有送給作者.... 不過也許是我的英文太破了, 就如同之前送的 patch 一樣, 都沒有後續的消息, 看起來似乎也不會進到官方的程式中, 至少目前的 snapshot 版本還沒包含這個修正.