Skip to content

Commit

Permalink
Merge branch 'develop', version 0.9
Browse files Browse the repository at this point in the history
  • Loading branch information
cyfdecyf committed Dec 2, 2013
2 parents 718df9a + adc0b7e commit 45981a8
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 23 deletions.
6 changes: 4 additions & 2 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
0.9 (Not released)
0.9 (2013-12-02)
* New feature: two COW servers can be connected using encrypted
connection, thus we have an encrypted HTTP proxy chain that can
be used to bypass the firewall
* Allow client to use HTTP basic authentication
* Simplified configuration syntax
* Simplify configuration syntax
* Better reuse for HTTP parent connections
* Reduce direct/blocked delta
* Generate new PAC every minute

0.8 (2013-08-10)
* Share server connections between different clients
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

COW 是一个简化穿墙的 HTTP 代理服务器。它能自动检测被墙网站,仅对这些网站使用二级代理。

当前版本:0.9-rc1 [CHANGELOG](CHANGELOG)
当前版本:0.9 [CHANGELOG](CHANGELOG)
[![Build Status](https://travis-ci.org/cyfdecyf/cow.png?branch=master)](https://travis-ci.org/cyfdecyf/cow)

**欢迎在 develop branch 进行开发并发送 pull request :)**
Expand All @@ -18,7 +18,7 @@ COW 的设计目标是自动化,理想情况下用户无需关心哪些网站
- 自动生成包含直连网站的 PAC,访问这些网站时可绕过 COW
- 内置[常见可直连网站](site_direct.go),如国内社交、视频、银行、电商等网站(可手工添加)

# Quick Start
# 快速开始

安装:

Expand All @@ -27,7 +27,7 @@ COW 的设计目标是自动化,理想情况下用户无需关心哪些网站
curl -L git.io/cow | bash

- **Windows:** [点此下载](http://dl.chenyufei.info/cow/)
- 熟悉 Go 的用户可用 `go get` 从源码安装
- 熟悉 Go 的用户可用 `go get github.com/cyfdecyf/cow` 从源码安装

编辑 `~/.cow/rc` (Linux) 或 `rc.txt` (Windows),简单的配置例子如下:

Expand Down
2 changes: 1 addition & 1 deletion config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
)

const (
version = "0.9-rc1"
version = "0.9"
defaultListenAddr = "127.0.0.1:7777"
)

Expand Down
2 changes: 1 addition & 1 deletion doc/sample-config/rc
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ listen = http://127.0.0.1:7777
#
# authinfo 中指定加密方法和密码,所有支持的加密方法如下:
# aes-128-cfb, aes-192-cfb, aes-256-cfb,
# bf-cfb, cast5-cfb, des-cfb
# bf-cfb, cast5-cfb, des-cfb, table, rc4
# 推荐使用 aes-128-cfb
#
# cow:
Expand Down
2 changes: 1 addition & 1 deletion install-cow.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

version=0.9-rc1
version=0.9

arch=`uname -m`
case $arch in
Expand Down
4 changes: 2 additions & 2 deletions pac.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,12 @@ func genPAC(c *clientConn) []byte {
}

func initPAC() {
// we can't control goroutine scheduling, this is to make sure when
// we can't control goroutine scheduling, make sure when
// initPAC is done, direct list is updated
updateDirectList()
go func() {
for {
time.Sleep(5 * time.Minute)
time.Sleep(time.Minute)
updateDirectList()
}
}()
Expand Down
16 changes: 8 additions & 8 deletions parent_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,11 @@ func (hp *httpParent) initAuth(userPasswd string) {
func (hp *httpParent) connect(url *URL) (net.Conn, error) {
c, err := net.Dial("tcp", hp.server)
if err != nil {
errl.Printf("can't connect to http parent proxy %s for %s: %v\n",
errl.Printf("can't connect to http parent %s for %s: %v\n",
hp.server, url.HostPort, err)
return nil, err
}
debug.Printf("connected to: %s via http parent proxy: %s\n",
debug.Printf("connected to: %s via http parent: %s\n",
url.HostPort, hp.server)
return httpConn{c, hp}, nil
}
Expand Down Expand Up @@ -192,8 +192,8 @@ func (sp *shadowsocksParent) initCipher(method, passwd string) {
func (sp *shadowsocksParent) connect(url *URL) (net.Conn, error) {
c, err := ss.Dial(url.HostPort, sp.server, sp.cipher.Copy())
if err != nil {
errl.Printf("create shadowsocks connection to %s through server %s failed %v\n",
url.HostPort, sp.server, err)
errl.Printf("can't connect to shadowsocks parent %s for %s: %v\n",
sp.server, url.HostPort, err)
return nil, err
}
debug.Println("connected to:", url.HostPort, "via shadowsocks:", sp.server)
Expand Down Expand Up @@ -230,11 +230,11 @@ func (cp *cowParent) genConfig() string {
func (cp *cowParent) connect(url *URL) (net.Conn, error) {
c, err := net.Dial("tcp", cp.server)
if err != nil {
errl.Printf("can't connect to cow parent proxy %s for %s: %v\n",
errl.Printf("can't connect to cow parent %s for %s: %v\n",
cp.server, url.HostPort, err)
return nil, err
}
debug.Printf("connected to: %s via cow parent proxy: %s\n",
debug.Printf("connected to: %s via cow parent: %s\n",
url.HostPort, cp.server)
ssconn := ss.NewConn(c, cp.cipher.Copy())
return cowConn{ssconn, cp}, nil
Expand Down Expand Up @@ -287,7 +287,7 @@ func (sp *socksParent) genConfig() string {
func (sp *socksParent) connect(url *URL) (net.Conn, error) {
c, err := net.Dial("tcp", sp.server)
if err != nil {
errl.Printf("can't connect to socks server %s for %s: %v\n",
errl.Printf("can't connect to socks parent %s for %s: %v\n",
sp.server, url.HostPort, err)
return nil, err
}
Expand Down Expand Up @@ -356,7 +356,7 @@ func (sp *socksParent) connect(url *URL) (net.Conn, error) {
errl.Printf("read socks reply err %v n %d\n", err, n)
}
hasErr = true
return nil, errors.New("Connection failed (by socks server). No such host?")
return nil, errors.New("connection failed (by socks server " + sp.server + "). No such host?")
}
// debug.Printf("Socks reply length %d\n", n)

Expand Down
4 changes: 4 additions & 0 deletions proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,10 @@ func (c *clientConn) getServerConn(r *Request) (*serverConn, error) {
}
sv := connPool.Get(r.URL.HostPort, siteInfo.AsDirect())
if sv != nil {
// For websites like feedly, the site itself is not blocked, but the
// content it loads may result reset. So we should reset server
// connection state to just connected.
sv.state = svConnected
if debug {
debug.Printf("cli(%s) connPool get %s\n", c.RemoteAddr(), r.URL.HostPort)
}
Expand Down
27 changes: 22 additions & 5 deletions sitestat.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ func init() {
// judging whether a site is blocked or not is more reliable.

const (
directDelta = 15
blockedDelta = 10
directDelta = 5
blockedDelta = 5
maxCnt = 100 // no protect to update visit cnt, smaller value is unlikely to overflow
userCnt = -1 // this represents user specified host or domain
)
Expand Down Expand Up @@ -288,14 +288,27 @@ func (ss *SiteStat) store(file string) (err error) {
panic("internal error: error marshalling site")
}

f, err := os.Create(file)
// Store stat into temp file first and then rename.
// This avoids problem if SIGINT causes program to exit but stat writing
// is half done.

f, err := ioutil.TempFile("", "stat")
if err != nil {
errl.Println("Can't create stat file:", err)
errl.Println("create tmp file to store stat", err)
return
}
defer f.Close()
if _, err = f.Write(b); err != nil {
errl.Println("Error writing stat file:", err)
f.Close()
return
}
f.Close()

// Windows don't allow rename to existing file.
os.Remove(file + ".bak")
os.Rename(file, file+".bak") // original stat may not exist
if err = os.Rename(f.Name(), file); err != nil {
errl.Println("can't rename newly created stat file", err)
return
}
return
Expand Down Expand Up @@ -425,8 +438,12 @@ func initSiteStat() {
}()
}

var storeLock sync.Mutex

func storeSiteStat() {
storeLock.Lock()
siteStat.store(dsFile.stat)
storeLock.Unlock()
}

func loadSiteList(fpath string) (lst []string, err error) {
Expand Down

0 comments on commit 45981a8

Please sign in to comment.