From 19308037e52ec778a4f2efd2c23da66b4850d92c Mon Sep 17 00:00:00 2001 From: V2Ray Date: Wed, 9 Sep 2015 17:39:06 +0200 Subject: [PATCH] freedom connection --- io/bufferset.go | 75 +++++++++++++++++++ .../json/json.go} | 4 +- net/freedom/freedom.go | 62 +++++++++++++++ 3 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 io/bufferset.go rename io/{jsonvconfigmarshaller.go => config/json/json.go} (89%) create mode 100644 net/freedom/freedom.go diff --git a/io/bufferset.go b/io/bufferset.go new file mode 100644 index 000000000..dc0e97cd8 --- /dev/null +++ b/io/bufferset.go @@ -0,0 +1,75 @@ +package io + +import( + "errors" +) + +const ( + SizeSmall = 16 + SizeMedium = 128 + SizeLarge = 512 +) + +var ( + ErrorNoChannel = errors.New("No suitable channels found.") +) + +type VBufferSet struct { + small chan []byte + medium chan []byte + large chan []byte +} + +func NewVBufferSet() *VBufferSet { + bSet := new(VBufferSet) + bSet.small = make(chan []byte, 128) + bSet.medium = make(chan []byte, 128) + bSet.large = make(chan []byte, 128) + return bSet +} + +func (bSet *VBufferSet) detectBucket(size int, strict bool) (chan []byte, error) { + if strict { + if size == SizeSmall { + return bSet.small, nil + } else if size == SizeMedium { + return bSet.medium, nil + } else if size == SizeLarge { + return bSet.large, nil + } + } else { + if size <= SizeSmall { + return bSet.small, nil + } else if size <= SizeMedium { + return bSet.medium, nil + } else if size <= SizeLarge { + return bSet.large, nil + } + } + return nil, ErrorNoChannel +} + +func (bSet *VBufferSet) FetchBuffer(minSize int) []byte { + var buffer []byte + byteChan, err := bSet.detectBucket(minSize, false) + if err != nil { + return make([]byte, minSize) + } + select { + case buffer = <- byteChan: + default: + buffer = make([]byte, minSize) + } + return buffer +} + +func (bSet *VBufferSet) ReturnBuffer(buffer []byte) { + byteChan, err := bSet.detectBucket(len(buffer), true) + if err != nil { + return + } + select { + case byteChan <- buffer: + default: + } +} diff --git a/io/jsonvconfigmarshaller.go b/io/config/json/json.go similarity index 89% rename from io/jsonvconfigmarshaller.go rename to io/config/json/json.go index 4261845e0..66703b97f 100644 --- a/io/jsonvconfigmarshaller.go +++ b/io/config/json/json.go @@ -1,8 +1,10 @@ -package io +// Package json contains io library for VConfig in Json format. +package json import ( "encoding/json" _ "fmt" + "github.com/v2ray/v2ray-core" ) diff --git a/net/freedom/freedom.go b/net/freedom/freedom.go new file mode 100644 index 000000000..2ea1f96e1 --- /dev/null +++ b/net/freedom/freedom.go @@ -0,0 +1,62 @@ +package tcp + +import ( + "net" + "io" +) + +type VFreeConnection struct { + network string + address string +} + +func NewVFreeConnection(network string, address string) *VFreeConnection { + conn := new(VFreeConnection) + conn.network = network + conn.address = address + return conn +} + +func (vconn *VFreeConnection) Start(input <-chan []byte) chan<- []byte { + output := make(chan []byte, 128) + conn, err := net.Dial(vconn.network, vconn.address) + if err != nil { + panic(err) + } + + finish := make(chan bool, 2) + go vconn.DumpInput(conn, input, finish) + go vconn.DumpOutput(conn, output, finish) + go vconn.CloseConn(conn, finish) + return output +} + +func (vconn *VFreeConnection) DumpInput(conn net.Conn, input <-chan []byte, finish chan<- bool) { + for { + data, open := <-input + if !open { + finish <- true + break + } + conn.Write(data) + } +} + +func (vconn *VFreeConnection) DumpOutput(conn net.Conn, output chan<- []byte, finish chan<- bool) { + for { + buffer := make([]byte, 128) + nBytes, err := conn.Read(buffer) + if err == io.EOF { + finish <- true + break + } + output <- buffer[:nBytes] + } +} + +func (vconn *VFreeConnection) CloseConn(conn net.Conn, finish <-chan bool) { + for i := 0; i < 2; i++ { + <-finish + } + conn.Close() +}