diff --git a/client/client.go b/client/client.go index 3c6e29e..54e1310 100644 --- a/client/client.go +++ b/client/client.go @@ -7,4 +7,5 @@ import ( "github.com/9seconds/mtg/config" ) +// Init has to initialize client connection based on given config. type Init func(net.Conn, *config.Config) (int16, io.ReadWriteCloser, error) diff --git a/client/direct.go b/client/direct.go index ce56646..14776c4 100644 --- a/client/direct.go +++ b/client/direct.go @@ -11,6 +11,7 @@ import ( "github.com/9seconds/mtg/wrappers" ) +// DirectInit initializes client to access Telegram bypassing middleproxies. func DirectInit(conn net.Conn, conf *config.Config) (int16, io.ReadWriteCloser, error) { socket := wrappers.NewTimeoutRWC(conn, conf.TimeoutRead, conf.TimeoutWrite) frame, err := obfuscated2.ExtractFrame(socket) diff --git a/telegram/direct.go b/telegram/direct.go index 6ac6c51..f2437ea 100644 --- a/telegram/direct.go +++ b/telegram/direct.go @@ -50,6 +50,8 @@ func (t *directTelegram) Init(conn io.ReadWriteCloser) (io.ReadWriteCloser, erro return wrappers.NewStreamCipherRWC(conn, obfs2.Encryptor, obfs2.Decryptor), nil } +// NewDirectTelegram returns Telegram instance which connects directly +// to Telegram bypassing middleproxies. func NewDirectTelegram(conf *config.Config) Telegram { return &directTelegram{baseTelegram{ dialer: newDialer(conf), diff --git a/telegram/telegram.go b/telegram/telegram.go index 00a9268..c06f934 100644 --- a/telegram/telegram.go +++ b/telegram/telegram.go @@ -7,6 +7,9 @@ import ( "github.com/juju/errors" ) +// Telegram defines an interface to connect to Telegram. This +// encapsulates logic of working with middleproxies or direct +// connections. type Telegram interface { Dial(int16) (io.ReadWriteCloser, error) Init(io.ReadWriteCloser) (io.ReadWriteCloser, error) diff --git a/wrappers/blockcipherrwc.go b/wrappers/blockcipherrwc.go deleted file mode 100644 index fa72ecb..0000000 --- a/wrappers/blockcipherrwc.go +++ /dev/null @@ -1,73 +0,0 @@ -package wrappers - -import ( - "bytes" - "crypto/cipher" - "io" - - "github.com/juju/errors" -) - -type BlockCipherReadWriteCloser struct { - encryptor cipher.BlockMode - decryptor cipher.BlockMode - conn io.ReadWriteCloser - buf *bytes.Buffer -} - -func (c *BlockCipherReadWriteCloser) Read(p []byte) (n int, err error) { - blockSize := c.decryptor.BlockSize() - if len(p) < blockSize { - return 0, errors.New("Cannot read less than blocksize") - } - - n, err = c.conn.Read(p) - c.buf.Write(p[:n]) - - wantToRead := c.getFullBlocks(len(p), blockSize) - haveBlocks := c.getFullBlocks(c.buf.Len(), blockSize) - if haveBlocks < wantToRead { - wantToRead = haveBlocks - } - wantToRead *= blockSize - - data := c.buf.Bytes() - c.decryptor.CryptBlocks(p, data[:wantToRead]) - c.buf = bytes.NewBuffer(data[wantToRead:]) - - return wantToRead, err -} - -func (c *BlockCipherReadWriteCloser) Write(p []byte) (n int, err error) { - blockSize := c.encryptor.BlockSize() - if len(p)%blockSize != 0 { - return 0, errors.New("Write size should be compatible with block size") - } - - buf := make([]byte, len(p)) - c.encryptor.CryptBlocks(buf, p) - - return c.conn.Write(buf) -} - -func (c *BlockCipherReadWriteCloser) Close() error { - return c.conn.Close() -} - -func (c *BlockCipherReadWriteCloser) getFullBlocks(number, blockSize int) int { - blocks := number / blockSize - - if blocks > 0 && number%blockSize != 0 { - blocks-- - } - - return blocks -} - -func NewBlockCipherRWC(conn io.ReadWriteCloser, encryptor, decryptor cipher.BlockMode) io.ReadWriteCloser { - return &BlockCipherReadWriteCloser{ - conn: conn, - encryptor: encryptor, - decryptor: decryptor, - } -} diff --git a/wrappers/ctxrwc.go b/wrappers/ctxrwc.go index 452d2e3..26f47be 100644 --- a/wrappers/ctxrwc.go +++ b/wrappers/ctxrwc.go @@ -48,6 +48,8 @@ func (c *CtxReadWriteCloser) Close() error { return c.conn.Close() } +// NewCtxRWC returns ReadWriteCloser which respects given context, +// cancellation etc. func NewCtxRWC(ctx context.Context, cancel context.CancelFunc, conn io.ReadWriteCloser) io.ReadWriteCloser { return &CtxReadWriteCloser{ conn: conn, diff --git a/wrappers/logrwc.go b/wrappers/logrwc.go index 00ef597..355e239 100644 --- a/wrappers/logrwc.go +++ b/wrappers/logrwc.go @@ -36,6 +36,7 @@ func (l *LogReadWriteCloser) Close() error { return err } +// NewLogRWC wraps ReadWriteCloser with logger calls. func NewLogRWC(conn io.ReadWriteCloser, logger *zap.SugaredLogger, sockid string, name string) io.ReadWriteCloser { return &LogReadWriteCloser{ conn: conn, diff --git a/wrappers/streamcipherrwc.go b/wrappers/streamcipherrwc.go index 5d7d018..77243b7 100644 --- a/wrappers/streamcipherrwc.go +++ b/wrappers/streamcipherrwc.go @@ -5,6 +5,8 @@ import ( "io" ) +// StreamCipherReadWriteCloser is a ReadWriteCloser which ciphers +// incoming and outgoing data with givem cipher.Stream instances. type StreamCipherReadWriteCloser struct { encryptor cipher.Stream decryptor cipher.Stream @@ -41,6 +43,8 @@ func (c *StreamCipherReadWriteCloser) Close() error { return c.conn.Close() } +// NewStreamCipherRWC returns wrapper which transparently +// encrypts/decrypts traffic with obfuscated2 protocol. func NewStreamCipherRWC(conn io.ReadWriteCloser, encryptor, decryptor cipher.Stream) io.ReadWriteCloser { return &StreamCipherReadWriteCloser{ conn: conn, diff --git a/wrappers/timeoutrwc.go b/wrappers/timeoutrwc.go index b83236c..b5f637d 100644 --- a/wrappers/timeoutrwc.go +++ b/wrappers/timeoutrwc.go @@ -31,6 +31,8 @@ func (t *TimeoutReadWriteCloser) Close() error { return t.conn.Close() } +// NewTimeoutRWC returns wrapper over net.Conn which sets deadlines for +// every wrapped Read/Write. func NewTimeoutRWC(conn net.Conn, readTimeout, writeTimeout time.Duration) io.ReadWriteCloser { return &TimeoutReadWriteCloser{ conn: conn, diff --git a/wrappers/trafficrwc.go b/wrappers/trafficrwc.go index 207addd..485a54c 100644 --- a/wrappers/trafficrwc.go +++ b/wrappers/trafficrwc.go @@ -29,6 +29,7 @@ func (t *TrafficReadWriteCloser) Close() error { return t.conn.Close() } +// NewTrafficRWC wraps ReadWriteCloser to have read/write callbacks. func NewTrafficRWC(conn io.ReadWriteCloser, readCallback, writeCallback func(int)) io.ReadWriteCloser { return &TrafficReadWriteCloser{ conn: conn,