Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 0dab521

Browse files
committedMay 12, 2015
Merge branch 'develop', version 0.9.5
2 parents b465963 + f3ae2bf commit 0dab521

16 files changed

+74
-39
lines changed
 

‎.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
language: go
22
go:
3-
- 1.3
3+
- 1.4.2
44
env:
55
- TRAVIS="yes"
66
install:

‎CHANGELOG

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
0.9.5 (2015-05-12)
2+
* Support new encryption method "chacha20" and "salsa20"
3+
* Avoid biased parent proxy selection for hash load balacing
4+
* Fix AirDrop on OS X when using PAC
5+
* Fix failed start with corrupted stat file
6+
* Support changing the estimate timeout target
7+
18
0.9.4 (2014-10-08)
29
* Bug fix (#179): close stat file after load
310

‎README.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ COW 是一个简化穿墙的 HTTP 代理服务器。它能自动检测被墙网
44

55
[English README](README-en.md).
66

7-
当前版本:0.9.4 [CHANGELOG](CHANGELOG)
7+
当前版本:0.9.5 [CHANGELOG](CHANGELOG)
88
[![Build Status](https://travis-ci.org/cyfdecyf/cow.png?branch=master)](https://travis-ci.org/cyfdecyf/cow)
99

1010
**欢迎在 develop branch 进行开发并发送 pull request :)**
@@ -37,6 +37,7 @@ COW 的设计目标是自动化,理想情况下用户无需关心哪些网站
3737
#开头的行是注释,会被忽略
3838
# 本地 HTTP 代理地址
3939
# 配置 HTTP 和 HTTPS 代理时请填入该地址
40+
# 若配置代理时有对所有协议使用该代理的选项,且你不清楚此选项的含义,请勾选
4041
# 或者在自动代理配置中填入 http://127.0.0.1:7777/pac
4142
listen = http://127.0.0.1:7777
4243

@@ -120,14 +121,14 @@ COW 默认配置下检测到被墙后,过两分钟再次尝试直连也是为
120121
- 不提供 cache
121122
- 不支持 HTTP pipeline(Chrome, Firefox 默认都没开启 pipeline,支持这个功能容易增加问题而好处并不明显)
122123

123-
# 致谢
124+
# 致谢 (Acknowledgements)
124125

125126
贡献代码:
126127

127128
- @tevino: http parent proxy basic authentication
128129
- @xupefei: 提供 cow-hide.exe 以在 windows 上在后台执行 cow.exe
129130
- @sunteya: 改进启动和安装脚本
130-
- @fzerorubigd: identify blocked site by HTTP error code
131+
- @fzerorubigd: identify blocked site by HTTP error code and various bug fixes
131132

132133
Bug reporter:
133134

‎config.go

+13-4
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,21 @@ import (
44
"errors"
55
"flag"
66
"fmt"
7-
"github.com/cyfdecyf/bufio"
87
"net"
98
"os"
109
"path"
1110
"reflect"
1211
"strconv"
1312
"strings"
1413
"time"
14+
15+
"github.com/cyfdecyf/bufio"
1516
)
1617

1718
const (
18-
version = "0.9.4"
19-
defaultListenAddr = "127.0.0.1:7777"
19+
version = "0.9.5"
20+
defaultListenAddr = "127.0.0.1:7777"
21+
defaultEstimateTarget = "example.com"
2022
)
2123

2224
type LoadBalanceMode byte
@@ -64,7 +66,8 @@ type Config struct {
6466

6567
// not configurable in config file
6668
PrintVer bool
67-
EstimateTimeout bool // if run estimateTimeout()
69+
EstimateTimeout bool // Whether to run estimateTimeout().
70+
EstimateTarget string // Timeout estimate target site.
6871

6972
// not config option
7073
saveReqLine bool // for http and cow parent, should save request line from client
@@ -103,6 +106,8 @@ func init() {
103106
for _, port := range defaultTunnelAllowedPort {
104107
config.TunnelAllowedPort[port] = true
105108
}
109+
110+
config.EstimateTarget = defaultEstimateTarget
106111
}
107112

108113
// Whether command line options specifies listen addr
@@ -560,6 +565,10 @@ func (p configParser) ParseDetectSSLErr(val string) {
560565
config.DetectSSLErr = parseBool(val, "detectSSLErr")
561566
}
562567

568+
func (p configParser) ParseEstimateTarget(val string) {
569+
config.EstimateTarget = val
570+
}
571+
563572
// overrideConfig should contain options from command line to override options
564573
// in config file.
565574
func parseConfig(rc string, override *Config) {

‎doc/sample-config/rc

+7-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
# listen = http://127.0.0.1:7777
1111
#
1212
# 上面的例子中,cow 生成的 PAC url 为 http://127.0.0.1:7777/pac
13+
# 配置浏览器或系统 HTTP 和 HTTPS 代理时请填入该地址
14+
# 若配置代理时有对所有协议使用该代理的选项,且你不清楚此选项的含义,请勾选
1315
#
1416
# cow (需两个 cow 服务器配合使用):
1517
# listen = cow://encrypt_method:password@1.2.3.4:5678
@@ -67,7 +69,8 @@ listen = http://127.0.0.1:7777
6769
#
6870
# authinfo 中指定加密方法和密码,所有支持的加密方法如下:
6971
# aes-128-cfb, aes-192-cfb, aes-256-cfb,
70-
# bf-cfb, cast5-cfb, des-cfb, rc4-md5, rc4, table
72+
# bf-cfb, cast5-cfb, des-cfb, rc4-md5,
73+
# chacha20, salsa20, rc4, table
7174
# 推荐使用 aes-128-cfb
7275
#
7376
# cow:
@@ -124,6 +127,9 @@ listen = http://127.0.0.1:7777
124127
# 最多允许使用多少个 CPU 核
125128
#core = 2
126129

130+
# 检测超时时间使用的网站,最好使用能快速访问的站点
131+
#estimateTarget = example.com
132+
127133
# 允许建立隧道连接的端口,多个端口用逗号分隔,可重复多次
128134
# 默认总是允许下列服务的端口: ssh, http, https, rsync, imap, pop, jabber, cvs, git, svn
129135
# 如需允许其他端口,请用该选项添加

‎doc/sample-config/rc-en

+5-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ listen = http://127.0.0.1:7777
7979
# Here are the supported encryption methods:
8080
#
8181
# aes-128-cfb, aes-192-cfb, aes-256-cfb,
82-
# bf-cfb, cast5-cfb, des-cfb, rc4-md5, rc4, table
82+
# bf-cfb, cast5-cfb, des-cfb, rc4-md5,
83+
# chacha20, salsa20, rc4, table
8384
#
8485
# aes-128-cfb is recommended.
8586
#
@@ -145,6 +146,9 @@ listen = http://127.0.0.1:7777
145146
# Maximum CPU core to use.
146147
#core = 2
147148

149+
# cow uses this site to estimate timeout, better to use a fast website.
150+
#estimateTarget = example.com
151+
148152
# Ports allowed to create tunnel (HTTP CONNECT method), comma separated list
149153
# or repeat to append more ports.
150154
# Ports for the following service are allowed by default:

‎estimate_timeout.go

+6-9
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,8 @@ const maxTimeout = 15 * time.Second
1717
var dialTimeout = defaultDialTimeout
1818
var readTimeout = defaultReadTimeout
1919

20-
// use a fast to fetch web site
21-
const estimateSite = "www.baidu.com"
22-
2320
var estimateReq = []byte("GET / HTTP/1.1\r\n" +
24-
"Host: " + estimateSite + "\r\n" +
21+
"Host: " + config.EstimateTarget + "\r\n" +
2522
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:11.0) Gecko/20100101 Firefox/11.0\r\n" +
2623
"Accept: */*\r\n" +
2724
"Accept-Language: en-us,en;q=0.5\r\n" +
@@ -32,16 +29,16 @@ var estimateReq = []byte("GET / HTTP/1.1\r\n" +
3229
// how much time is spent on connect and fetch. This avoids incorrectly
3330
// considering non-blocked sites as blocked when network connection is bad.
3431
func estimateTimeout() {
35-
// debug.Println("estimating timeout")
32+
//debug.Println("estimating timeout")
3633
buf := connectBuf.Get()
3734
defer connectBuf.Put(buf)
3835
var est time.Duration
3936

4037
start := time.Now()
41-
c, err := net.Dial("tcp", estimateSite+":80")
38+
c, err := net.Dial("tcp", config.EstimateTarget+":80")
4239
if err != nil {
4340
errl.Printf("estimateTimeout: can't connect to %s: %v, network has problem?\n",
44-
estimateSite, err)
41+
config.EstimateTarget, err)
4542
goto onErr
4643
}
4744
defer c.Close()
@@ -71,7 +68,7 @@ func estimateTimeout() {
7168
}
7269
if err != io.EOF {
7370
errl.Printf("estimateTimeout: error getting %s: %v, network has problem?\n",
74-
estimateSite, err)
71+
config.EstimateTarget, err)
7572
goto onErr
7673
}
7774
est = time.Now().Sub(start) * 10
@@ -97,7 +94,7 @@ func runEstimateTimeout() {
9794
dialTimeout = config.DialTimeout
9895
for {
9996
estimateTimeout()
100-
time.Sleep(30 * time.Second)
97+
time.Sleep(time.Minute)
10198
}
10299
}
103100

‎http.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,7 @@ func parseResponse(sv *serverConn, r *Request, rp *Response) (err error) {
710710

711711
//Check for http error code from config file
712712
if config.HttpErrorCode > 0 && rp.Status == config.HttpErrorCode {
713-
errl.Println("Requested http code is raised")
713+
debug.Println("Requested http code is raised")
714714
return CustomHttpErr
715715
}
716716

‎install-cow.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/bash
22

3-
version=0.9.4
3+
version=0.9.5
44

55
arch=`uname -m`
66
case $arch in
@@ -83,7 +83,7 @@ fi
8383
bin=cow-$os$arch-$version
8484
tmpdir=`mktemp -d /tmp/cow.XXXXXX`
8585
tmpbin=$tmpdir/cow
86-
binary_url="http://dl.chenyufei.info/cow/$bin.gz"
86+
binary_url="http://dl.chenyufei.info/cow/$version/$bin.gz"
8787
echo "Downloading cow binary $binary_url to $tmpbin.gz"
8888
curl -L "$binary_url" -o $tmpbin.gz || \
8989
exit_on_fail "Downloading cow binary failed"

‎main.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ func sigHandler() {
1616
// TODO On Windows, these signals will not be triggered on closing cmd
1717
// window. How to detect this?
1818
sigChan := make(chan os.Signal, 1)
19-
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM,
20-
syscall.SIGHUP)
19+
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
2120

2221
for sig := range sigChan {
2322
// May handle other signals in the future.

‎pac.go

+3
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ function host2Domain(host) {
116116
function FindProxyForURL(url, host) {
117117
if (url.substring(0,4) == "ftp:")
118118
return direct;
119+
if (host.indexOf(".local", host.length - 6) !== -1) {
120+
return direct;
121+
}
119122
var domain = host2Domain(host);
120123
if (host.length == domain.length) {
121124
return directAcc[host] ? direct : httpProxy;

‎pac.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ function host2Domain(host) {
8686
function FindProxyForURL(url, host) {
8787
if (url.substring(0,4) == "ftp:")
8888
return direct;
89+
if (host.indexOf(".local", host.length - 6) !== -1) {
90+
return direct;
91+
}
8992
var domain = host2Domain(host);
9093
if (host.length == domain.length) {
9194
return directAcc[host] ? direct : httpProxy;
@@ -160,7 +163,11 @@ testData = [
160163
{ host: 'foo.baidu.com', mode: httpProxy},
161164
{ host: 'google.com', mode: httpProxy},
162165
{ host: 'www.google.com', mode: httpProxy},
163-
{ host: 'www.google.com.hk', mode: httpProxy}
166+
{ host: 'www.google.com.hk', mode: httpProxy},
167+
168+
// host in local domain should return direct
169+
{ host: 'test.local', mode: direct},
170+
{ host: '.local', mode: direct},
164171
];
165172

166173
for (i = 0; i < testData.length; i += 1) {

‎parent_proxy.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"errors"
77
"fmt"
88
ss "github.com/shadowsocks/shadowsocks-go/shadowsocks"
9+
"hash/crc32"
910
"io"
1011
"math/rand"
1112
"net"
@@ -109,7 +110,7 @@ type hashParentPool struct {
109110
}
110111

111112
func (pp *hashParentPool) connect(url *URL) (srvconn net.Conn, err error) {
112-
start := int(stringHash(url.Host) % uint64(len(pp.parent)))
113+
start := int(crc32.ChecksumIEEE([]byte(url.Host)) % uint32(len(pp.parent)))
113114
debug.Printf("hash host %s try %d parent first", url.Host, start)
114115
return connectInOrder(url, pp.parent, start)
115116
}

‎script/build.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ build() {
4848
}
4949

5050
build darwin amd64 mac64
51-
build darwin 386 mac32
51+
#build darwin 386 mac32
5252
build linux amd64 linux64
5353
build linux 386 linux32
5454
build linux arm linux-armv5tel

‎sitestat.go

+13-3
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ import (
44
"encoding/json"
55
"errors"
66
"fmt"
7-
"github.com/cyfdecyf/bufio"
87
"io/ioutil"
98
"math/rand"
109
"os"
1110
"strings"
1211
"sync"
1312
"time"
13+
14+
"github.com/cyfdecyf/bufio"
1415
)
1516

1617
func init() {
@@ -426,9 +427,18 @@ func (ss *SiteStat) GetDirectList() []string {
426427
var siteStat = newSiteStat()
427428

428429
func initSiteStat() {
429-
if err := siteStat.load(configPath.stat); err != nil {
430-
os.Exit(1)
430+
err := siteStat.load(configPath.stat)
431+
if err != nil {
432+
errl.Printf("loading stat file failed, reason : %s", err.Error())
433+
// Simply try to load the stat.back
434+
err = siteStat.load(configPath.stat + ".bak")
435+
// After all its not critical , simply re-create a stat object if anything is not ok
436+
if err != nil {
437+
errl.Printf("loading stat backup failed, creating new one , reason: %s", err.Error())
438+
siteStat = newSiteStat()
439+
}
431440
}
441+
432442
// Dump site stat while running, so we don't always need to close cow to
433443
// get updated stat.
434444
go func() {

‎util.go

-9
Original file line numberDiff line numberDiff line change
@@ -453,15 +453,6 @@ func host2Domain(host string) (domain string) {
453453
return host[dot2ndLast+1:]
454454
}
455455

456-
// djb2 string hash function, from http://www.cse.yorku.ca/~oz/hash.html
457-
func stringHash(s string) (hash uint64) {
458-
hash = 5381
459-
for i := 0; i < len(s); i++ {
460-
hash = ((hash << 5) + 1) + uint64(s[i])
461-
}
462-
return
463-
}
464-
465456
// IgnoreUTF8BOM consumes UTF-8 encoded BOM character if present in the file.
466457
func IgnoreUTF8BOM(f *os.File) error {
467458
bom := make([]byte, 3)

0 commit comments

Comments
 (0)
Failed to load comments.