mirror of https://github.com/cbeuw/Cloak
Fix infinite loop. Baseline
This commit is contained in:
parent
a8786a5576
commit
02fa072964
|
|
@ -6,7 +6,10 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
|
_ "net/http/pprof"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -19,9 +22,8 @@ var version string
|
||||||
|
|
||||||
func pipe(dst io.ReadWriteCloser, src io.ReadWriteCloser) {
|
func pipe(dst io.ReadWriteCloser, src io.ReadWriteCloser) {
|
||||||
for {
|
for {
|
||||||
_, err := io.Copy(dst, src)
|
i, err := io.Copy(dst, src)
|
||||||
if err != nil {
|
if err != nil || i == 0 {
|
||||||
log.Println(err)
|
|
||||||
go dst.Close()
|
go dst.Close()
|
||||||
go src.Close()
|
go src.Close()
|
||||||
return
|
return
|
||||||
|
|
@ -102,10 +104,12 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
|
||||||
newStream, err := sesh.AcceptStream()
|
newStream, err := sesh.AcceptStream()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to get new stream: %v", err)
|
log.Printf("Failed to get new stream: %v", err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
ssConn, err := net.Dial("tcp", sta.SS_LOCAL_HOST+":"+sta.SS_LOCAL_PORT)
|
ssConn, err := net.Dial("tcp", sta.SS_LOCAL_HOST+":"+sta.SS_LOCAL_PORT)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to connect to ssserver: %v", err)
|
log.Printf("Failed to connect to ssserver: %v", err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
go pipe(ssConn, newStream)
|
go pipe(ssConn, newStream)
|
||||||
go pipe(newStream, ssConn)
|
go pipe(newStream, ssConn)
|
||||||
|
|
@ -116,6 +120,10 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
runtime.SetBlockProfileRate(2)
|
||||||
|
go func() {
|
||||||
|
log.Println(http.ListenAndServe("0.0.0.0:8001", nil))
|
||||||
|
}()
|
||||||
// Should be 127.0.0.1 to listen to ss-server on this machine
|
// Should be 127.0.0.1 to listen to ss-server on this machine
|
||||||
var localHost string
|
var localHost string
|
||||||
// server_port in ss config, same as remotePort in plugin mode
|
// server_port in ss config, same as remotePort in plugin mode
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{
|
{
|
||||||
"WebServerAddr":"204.79.197.200:443",
|
"WebServerAddr":"204.79.197.200:443",
|
||||||
"Key":"CN+VRP9OqZR0+Im2X/1y6FvaK7+GBnX6qCiovbo+eVo="
|
"Key":"UGUmcEmxWf0pKxfkZ/8EoP35Ht+wQnqf3L0xYgyQFlQ="
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package multiplex
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"container/heap"
|
"container/heap"
|
||||||
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The data is multiplexed through several TCP connections, therefore the
|
// The data is multiplexed through several TCP connections, therefore the
|
||||||
|
|
@ -57,8 +58,10 @@ func (s *Stream) recvNewFrame() {
|
||||||
for {
|
for {
|
||||||
f := <-s.newFrameCh
|
f := <-s.newFrameCh
|
||||||
if f == nil {
|
if f == nil {
|
||||||
|
log.Println("nil frame")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the ease of demonstration, assume seq is uint8, i.e. it wraps around after 255
|
// For the ease of demonstration, assume seq is uint8, i.e. it wraps around after 255
|
||||||
fs := &frameNode{
|
fs := &frameNode{
|
||||||
f.Seq,
|
f.Seq,
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Copied from smux
|
// Copied from smux
|
||||||
errBrokenPipe = "broken pipe"
|
errBrokenPipe = "broken stream"
|
||||||
errRepeatStreamClosing = "trying to close a closed stream"
|
errRepeatStreamClosing = "trying to close a closed stream"
|
||||||
acceptBacklog = 1024
|
acceptBacklog = 1024
|
||||||
|
|
||||||
|
|
@ -84,9 +84,9 @@ func (sesh *Session) AcceptStream() (*Stream, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sesh *Session) delStream(id uint32) {
|
func (sesh *Session) delStream(id uint32) {
|
||||||
sesh.streamsM.RLock()
|
sesh.streamsM.Lock()
|
||||||
delete(sesh.streams, id)
|
delete(sesh.streams, id)
|
||||||
sesh.streamsM.RUnlock()
|
sesh.streamsM.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sesh *Session) isStream(id uint32) bool {
|
func (sesh *Session) isStream(id uint32) bool {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
readBuffer = 102400
|
readBuffer = 20480
|
||||||
)
|
)
|
||||||
|
|
||||||
type Stream struct {
|
type Stream struct {
|
||||||
|
|
@ -50,11 +50,22 @@ func makeStream(id uint32, sesh *Session) *Stream {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (stream *Stream) Read(buf []byte) (n int, err error) {
|
func (stream *Stream) Read(buf []byte) (n int, err error) {
|
||||||
if len(buf) != 0 {
|
if len(buf) == 0 {
|
||||||
select {
|
select {
|
||||||
case <-stream.die:
|
case <-stream.die:
|
||||||
|
log.Printf("Stream %v dying\n", stream.id)
|
||||||
return 0, errors.New(errBrokenPipe)
|
return 0, errors.New(errBrokenPipe)
|
||||||
case data := <-stream.sortedBufCh:
|
default:
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-stream.die:
|
||||||
|
log.Printf("Stream %v dying\n", stream.id)
|
||||||
|
return 0, errors.New(errBrokenPipe)
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
data := <-stream.sortedBufCh
|
||||||
if len(data) > 0 {
|
if len(data) > 0 {
|
||||||
copy(buf, data)
|
copy(buf, data)
|
||||||
return len(data), nil
|
return len(data), nil
|
||||||
|
|
@ -62,9 +73,6 @@ func (stream *Stream) Read(buf []byte) (n int, err error) {
|
||||||
// TODO: close stream here or not?
|
// TODO: close stream here or not?
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0, errors.New(errBrokenPipe)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,8 +119,8 @@ func (stream *Stream) Close() error {
|
||||||
return errors.New(errRepeatStreamClosing)
|
return errors.New(errRepeatStreamClosing)
|
||||||
}
|
}
|
||||||
stream.closing = true
|
stream.closing = true
|
||||||
stream.session.delStream(stream.id)
|
|
||||||
close(stream.die)
|
close(stream.die)
|
||||||
|
stream.session.delStream(stream.id)
|
||||||
stream.session.closeQCh <- stream.id
|
stream.session.closeQCh <- stream.id
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package multiplex
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
//"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -79,30 +79,36 @@ type sentNotifier struct {
|
||||||
|
|
||||||
func (ce *connEnclave) send(data []byte) {
|
func (ce *connEnclave) send(data []byte) {
|
||||||
// TODO: error handling
|
// TODO: error handling
|
||||||
n, err := ce.remoteConn.Write(data)
|
_, err := ce.remoteConn.Write(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
ce.sb.closingCECh <- ce
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
sn := &sentNotifier{
|
sn := &sentNotifier{
|
||||||
ce,
|
ce,
|
||||||
n,
|
n,
|
||||||
}
|
}
|
||||||
ce.sb.sentNotifyCh <- sn
|
ce.sb.sentNotifyCh <- sn
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dispatcher sends data coming from a stream to a remote connection
|
// Dispatcher sends data coming from a stream to a remote connection
|
||||||
// I used channels here because I didn't want to use mutex
|
// I used channels here because I didn't want to use mutex
|
||||||
func (sb *switchboard) dispatch() {
|
func (sb *switchboard) dispatch() {
|
||||||
|
var nextCE int
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
// dispatCh receives data from stream.Write
|
// dispatCh receives data from stream.Write
|
||||||
case data := <-sb.dispatCh:
|
case data := <-sb.dispatCh:
|
||||||
go sb.ces[0].send(data)
|
go sb.ces[nextCE%len(sb.ces)].send(data)
|
||||||
sb.ces[0].sendQueue += len(data)
|
//sb.ces[0].sendQueue += len(data)
|
||||||
case notified := <-sb.sentNotifyCh:
|
nextCE += 1
|
||||||
|
/*case notified := <-sb.sentNotifyCh:
|
||||||
notified.ce.sendQueue -= notified.sent
|
notified.ce.sendQueue -= notified.sent
|
||||||
sort.Sort(byQ(sb.ces))
|
sort.Sort(byQ(sb.ces))*/
|
||||||
case conn := <-sb.newConnCh:
|
case conn := <-sb.newConnCh:
|
||||||
|
log.Println("newConn")
|
||||||
newCe := &connEnclave{
|
newCe := &connEnclave{
|
||||||
sb: sb,
|
sb: sb,
|
||||||
remoteConn: conn,
|
remoteConn: conn,
|
||||||
|
|
@ -110,8 +116,9 @@ func (sb *switchboard) dispatch() {
|
||||||
}
|
}
|
||||||
sb.ces = append(sb.ces, newCe)
|
sb.ces = append(sb.ces, newCe)
|
||||||
go sb.deplex(newCe)
|
go sb.deplex(newCe)
|
||||||
sort.Sort(byQ(sb.ces))
|
//sort.Sort(byQ(sb.ces))
|
||||||
case closing := <-sb.closingCECh:
|
case closing := <-sb.closingCECh:
|
||||||
|
log.Println("Closing conn")
|
||||||
for i, ce := range sb.ces {
|
for i, ce := range sb.ces {
|
||||||
if closing == ce {
|
if closing == ce {
|
||||||
sb.ces = append(sb.ces[:i], sb.ces[i+1:]...)
|
sb.ces = append(sb.ces[:i], sb.ces[i+1:]...)
|
||||||
|
|
@ -124,7 +131,7 @@ func (sb *switchboard) dispatch() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sb *switchboard) deplex(ce *connEnclave) {
|
func (sb *switchboard) deplex(ce *connEnclave) {
|
||||||
buf := make([]byte, 204800)
|
buf := make([]byte, 20480)
|
||||||
for {
|
for {
|
||||||
i, err := sb.session.obfsedReader(ce.remoteConn, buf)
|
i, err := sb.session.obfsedReader(ce.remoteConn, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
prand "math/rand"
|
prand "math/rand"
|
||||||
"net"
|
"net"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -45,15 +46,15 @@ func ReadTillDrain(conn net.Conn, buffer []byte) (n int, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
dataLength := BtoInt(buffer[3:5])
|
dataLength := BtoInt(buffer[3:5])
|
||||||
|
if dataLength > len(buffer) {
|
||||||
|
err = errors.New("Reading TLS message: message size greater than buffer. message size: " + strconv.Itoa(dataLength))
|
||||||
|
return
|
||||||
|
}
|
||||||
left := dataLength
|
left := dataLength
|
||||||
readPtr := 5
|
readPtr := 5
|
||||||
|
|
||||||
conn.SetReadDeadline(time.Now().Add(3 * time.Second))
|
conn.SetReadDeadline(time.Now().Add(3 * time.Second))
|
||||||
for left != 0 {
|
for left != 0 {
|
||||||
if readPtr > len(buffer) || readPtr+left > len(buffer) {
|
|
||||||
err = errors.New("Reading TLS message: message size greater than buffer")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// If left > buffer size (i.e. our message got segmented), the entire MTU is read
|
// If left > buffer size (i.e. our message got segmented), the entire MTU is read
|
||||||
// if left = buffer size, the entire buffer is all there left to read
|
// if left = buffer size, the entire buffer is all there left to read
|
||||||
// if left < buffer size (i.e. multiple messages came together),
|
// if left < buffer size (i.e. multiple messages came together),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue