Skip to content

Commit

Permalink
0.4.4
Browse files Browse the repository at this point in the history
  • Loading branch information
yinghuocho committed Nov 7, 2016
1 parent 2437511 commit 39a39b4
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 51 deletions.
16 changes: 11 additions & 5 deletions client/Makefile
@@ -1,5 +1,5 @@
VERSION := 0.4.3
SHORTVERSION := 0.4.3
VERSION := 0.4.4
SHORTVERSION := 0.4.4

.PHONY: windows package-windows linux package-linux darwin package-darwin clean

Expand All @@ -19,13 +19,13 @@ define fpm-debian-build
cp $$INSTALLER_RESOURCES/firefly.desktop $$WORKDIR/usr/share/applications && \
cp $$INSTALLER_RESOURCES/firefly_256.png $$WORKDIR/usr/share/icons/hicolor/256x256/apps/firefly.png && \
\
cp firefly $$WORKDIR/usr/bin/firefly-bin && \
cp $3 $$WORKDIR/usr/bin/firefly-bin && \
cp $$INSTALLER_RESOURCES/firefly.sh $$WORKDIR/usr/bin/firefly && \
\
chmod -x $$WORKDIR/usr/bin/firefly-bin && \
chmod +x $$WORKDIR/usr/bin/firefly && \
\
fpm --license BSD --description "$$DESC" --vendor yinghuocho --maintainer "yinghuocho <yinghuocho@gmail.com>" --url https://gofirefly.org/ -a $$PKG_ARCH -s dir -t deb -n firefly -v $$VERSION -C $$WORKDIR -f usr;
fpm --depends "libappindicator3-1" --license BSD --description "$$DESC" --vendor yinghuocho --maintainer "yinghuocho <yinghuocho@gmail.com>" --url https://gofirefly.org/ -a $$PKG_ARCH -s dir -t deb -n firefly -v $$VERSION -C $$WORKDIR -f usr;
endef

windows:
Expand All @@ -38,8 +38,14 @@ package-windows: windows
linux:
GOOS=linux GOARCH=amd64 go build -ldflags="-w -s -linkmode internal" -a -o firefly

linux32:
GOOS=linux GOARCH=386 go build -ldflags="-w -s -linkmode internal" -a -o firefly32

package-linux: linux
$(call fpm-debian-build,"amd64","${VERSION}")
$(call fpm-debian-build,"amd64","${VERSION}","firefly")

package-linux32:
$(call fpm-debian-build,"i386","${VERSION}","firefly32")

darwin:
GOOS=darwin GOARCH=amd64 go build -ldflags="-w" -a -o firefly_darwin_amd64
Expand Down
15 changes: 8 additions & 7 deletions client/main.go
Expand Up @@ -34,7 +34,7 @@ import (
)

const (
FIREFLY_VERSION = "0.4.3"
FIREFLY_VERSION = "0.4.4"
)

type clientOptions struct {
Expand Down Expand Up @@ -469,13 +469,19 @@ func (c *fireflyClient) _main() {
os.Exit(1)
}

// state, report without using proxy
c.state = newState(c.uuid(), c.options.trackingID, nil)
go c.state.run()
c.state.event("client", "launch", strings.Join([]string{runtime.GOOS, runtime.GOARCH}, "_"), 0)

// start tunnel client
c.tunnelListener, err = net.ListenTCP("tcp", &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 0})
if err != nil {
log.Printf("FATAL: fail to listen on tunnel client (SOCKS): %s", err)
os.Exit(1)
}
handler := &tunnelHandler{
state: c.state,
caCerts: c.loadCaCerts(),
appData: c.appData,
ch: make(chan *tunnelRequest),
Expand All @@ -484,7 +490,7 @@ func (c *fireflyClient) _main() {
}
err = handler.loadTunnelPeers(c.fs)
if err != nil {
log.Printf("FATAL: fail to load tunnel peers")
log.Printf("FATAL: fail to load tunnel peers: %s", err)
os.Exit(1)
}
go handler.run()
Expand Down Expand Up @@ -618,11 +624,6 @@ func (c *fireflyClient) _main() {
c.startUpdater()
}

// state, report without using proxy
c.state = newState(c.uuid(), c.options.trackingID, nil)
go c.state.run()
c.state.event("client", "launch")

c.waitForExit()
os.Exit(0)
}
Expand Down
2 changes: 1 addition & 1 deletion client/resources.go

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions client/resources/keys/cacerts.pem
@@ -1,4 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIDnzCCAyWgAwIBAgIQWyXOaQfEJlVm0zkMmalUrTAKBggqhkjOPQQDAzCBhTEL
MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTQwOTI1MDAw
MDAwWhcNMjkwOTI0MjM1OTU5WjCBkjELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
T0RPIENBIExpbWl0ZWQxODA2BgNVBAMTL0NPTU9ETyBFQ0MgRG9tYWluIFZhbGlk
YXRpb24gU2VjdXJlIFNlcnZlciBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
QgAEAjgZgTrJaYRwWQKOqIofMN+83gP8eR06JSxrQSEYgur5PkrkM8wSzypD/A7y
ZADA4SVQgiTNtkk4DyVHkUikraOCAWYwggFiMB8GA1UdIwQYMBaAFHVxpxlIGbyd
nepBR9+UxEh3mdN5MB0GA1UdDgQWBBRACWFn8LyDcU/eEggsb9TUK3Y9ljAOBgNV
HQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHSUEFjAUBggrBgEF
BQcDAQYIKwYBBQUHAwIwGwYDVR0gBBQwEjAGBgRVHSAAMAgGBmeBDAECATBMBgNV
HR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9FQ0ND
ZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDByBggrBgEFBQcBAQRmMGQwOwYIKwYB
BQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9ET0VDQ0FkZFRydXN0
Q0EuY3J0MCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC5jb21vZG9jYTQuY29tMAoG
CCqGSM49BAMDA2gAMGUCMQCsaEclgBNPE1bAojcJl1pQxOfttGHLKIoKETKm4nHf
EQGJbwd6IGZrGNC5LkP3Um8CMBKFfI4TZpIEuppFCZRKMGHRSdxv6+ctyYnPHmp8
7IXOMCVZuoFwNLg0f+cB0eLLUg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFKjCCBBKgAwIBAgIQJYla65BEyOYXYEoVLPiPpjANBgkqhkiG9w0BAQUFADBv
MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk
ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF
Expand Down
4 changes: 2 additions & 2 deletions client/resources/meektunnels.txt
@@ -1,2 +1,2 @@
# format: front_url,real_host
https://a0.awsstatic.com,d288jep9bb0hx9.cloudfront.net
# format: front_url,real_host,group
https://a0.awsstatic.com,d288jep9bb0hx9.cloudfront.net,group1
12 changes: 7 additions & 5 deletions client/state.go
Expand Up @@ -5,6 +5,7 @@ import (
"net/http"
"net/url"
"runtime"
"strconv"
"strings"
"time"
)
Expand All @@ -30,7 +31,7 @@ func newState(clientID string, trackingID string, proxyURL *url.URL) *fireflySta
}
}

func (s *fireflyState) reportEvent(category, action string) {
func (s *fireflyState) reportEvent(category, action, label, value string) {
log.Printf("report google analytics event: [%s %s]", category, action)
resp, err := s.httpClient.PostForm("https://www.google-analytics.com/collect", url.Values{
"v": {"1"},
Expand All @@ -42,7 +43,8 @@ func (s *fireflyState) reportEvent(category, action string) {
"t": {"event"},
"ec": {category},
"ea": {action},
"el": {strings.Join([]string{runtime.GOOS, runtime.GOARCH}, "_")},
"el": {label},
"ev": {value},
})
if err != nil {
log.Printf("error to report google analytics event: %s", err)
Expand All @@ -51,8 +53,8 @@ func (s *fireflyState) reportEvent(category, action string) {
}
}

func (s *fireflyState) event(category string, action string) {
s.ch <- strings.Join([]string{"event", category, action}, "|")
func (s *fireflyState) event(category string, action string, label string, value int) {
s.ch <- strings.Join([]string{"event", category, action, label, strconv.Itoa(value)}, "|")
}

func (s *fireflyState) run() {
Expand All @@ -61,7 +63,7 @@ func (s *fireflyState) run() {
switch {
case strings.HasPrefix(cmd, "event"):
args := strings.Split(cmd, "|")
s.reportEvent(args[1], args[2])
s.reportEvent(args[1], args[2], args[3], args[4])
}
}
}
69 changes: 52 additions & 17 deletions client/tunnel.go
Expand Up @@ -25,14 +25,15 @@ type tunnelPeer interface {
}

type tunnelHandler struct {
state *fireflyState
caCerts *x509.CertPool
appData *utils.AppData

quit chan bool
ch chan *tunnelRequest
auth sockstun.TunnelAuthenticator

peers []tunnelPeer
peerGroups map[string][]tunnelPeer
}

func (t *tunnelHandler) savePeerState(succ tunnelPeer, fail []tunnelPeer) {
Expand Down Expand Up @@ -77,32 +78,63 @@ func (s *peerSorter) Less(i, j int) bool {
return s.by(s.peers[i], s.peers[j])
}

func (t *tunnelHandler) sortPeers() {
func (t *tunnelHandler) sortPeers() []tunnelPeer {
state := make(map[string]int)
v, ok := t.appData.Get("tunnelPeerState")
if ok {
json.Unmarshal([]byte(v), &state)
}

// shuffle
for i := range t.peers {
j := rand.Intn(i + 1)
t.peers[i], t.peers[j] = t.peers[j], t.peers[i]
}

// sort by state
by := func(p1, p2 tunnelPeer) bool {
return state[p1.serialize()] < state[p2.serialize()]
}
sort.Reverse(&peerSorter{peers: t.peers, by: by})

var groups [][]tunnelPeer
cnt := 0
for _, peers := range t.peerGroups {
// shuffle
cnt += len(peers)
for i := range peers {
j := rand.Intn(i + 1)
peers[i], peers[j] = peers[j], peers[i]
}
sort.Reverse(&peerSorter{peers: peers, by: by})
groups = append(groups, peers)
}
all := make([]tunnelPeer, cnt)
i := 0
j := 0
cur := 0
for {
if j < len(groups[i]) {
all[cur] = groups[i][j]
cur += 1
if cur == cnt {
break
}
}
i += 1
if i >= len(groups) {
i = 0
j += 1
}
}
return all
}

func (t *tunnelHandler) muxClient() *mux.Client {
conn, succ, failed := t.dialParallel(30 * time.Minute)
start := time.Now()
conn, succ, failed := t.dialParallel(10 * time.Minute)
ms := int(time.Now().Sub(start).Nanoseconds() / 1000)
t.savePeerState(succ, failed)
if conn == nil {
t.state.event("client", "connect-timeout", "", 0)
log.Printf("connect attempt timed out")
return nil
}
p := succ.serialize()
log.Printf("connected to peer: %s", p)
t.state.event("client", "connect-succ", p, ms)
return mux.NewClient(conn)
}

Expand All @@ -114,9 +146,12 @@ type tunnelDailRet struct {
func (t *tunnelHandler) dialParallel(timeout time.Duration) (net.Conn, tunnelPeer, []tunnelPeer) {
ret := make(chan *tunnelDailRet)
quit := make(chan bool)

// rand by historical connectivity
all := t.sortPeers()
// give enough buffer so token channel would not be blocked
// initiate five attemps
waiting := len(t.peers)
waiting := len(all)
token := make(chan bool, waiting)
for i := 0; i < 5; i++ {
token <- true
Expand All @@ -125,9 +160,7 @@ func (t *tunnelHandler) dialParallel(timeout time.Duration) (net.Conn, tunnelPee
break
}
}
// rand by historical connectivity
t.sortPeers()
for _, peer := range t.peers {
for _, peer := range all {
go func(p tunnelPeer) {
select {
case <-token:
Expand All @@ -153,13 +186,14 @@ func (t *tunnelHandler) dialParallel(timeout time.Duration) (net.Conn, tunnelPee
case r := <-ret:
if r.c == nil {
failedCnt++
log.Printf("failed to connect peer: %s", r.p.serialize())
failedPeers = append(failedPeers, r.p)
// one fail, fire another if someone waiting
if waiting > 0 {
token <- true
waiting -= 1
}
if failedCnt == len(t.peers) {
if failedCnt == len(all) {
log.Printf("all attemps to connect tunnel address have failed")
} else {
continue
Expand Down Expand Up @@ -207,6 +241,7 @@ func (t *tunnelHandler) muxStream(client *mux.Client) (*mux.Client, *mux.Stream)
func (t *tunnelHandler) run() {
var client *mux.Client
var stream *mux.Stream
loop:
for {
select {
case request := <-t.ch:
Expand All @@ -217,7 +252,7 @@ func (t *tunnelHandler) run() {
request.ret <- stream
}
case <-t.quit:
break
break loop
}
}
}
Expand Down

0 comments on commit 39a39b4

Please sign in to comment.