Small refactorings of rpc package

This commit is contained in:
9seconds
2018-07-05 10:37:05 +03:00
parent a7eb29cc94
commit 0738631ef8
6 changed files with 91 additions and 128 deletions
+21 -3
View File
@@ -6,7 +6,25 @@ const (
) )
var ( var (
RPCTagCloseExt = []byte{0xa2, 0x34, 0xb6, 0x5e} RPCTagCloseExt = []byte{0xa2, 0x34, 0xb6, 0x5e}
RPCTagProxyAns = []byte{0x0d, 0xda, 0x03, 0x44} RPCTagProxyAns = []byte{0x0d, 0xda, 0x03, 0x44}
RPCTagSimpleAck = []byte{0x9b, 0x40, 0xac, 0x3b} RPCTagSimpleAck = []byte{0x9b, 0x40, 0xac, 0x3b}
RPCTagHandshake = []byte{0xf5, 0xee, 0x82, 0x76}
RPCTagNonce = []byte{0xaa, 0x87, 0xcb, 0x7a}
RPCTagProxyRequest = []byte{0xee, 0xf1, 0xce, 0x36}
RPCNonceCryptoAES = []byte{0x01, 0x00, 0x00, 0x00}
RPCHandshakeFlags = []byte{0x00, 0x00, 0x00, 0x00}
RPCProxyRequestExtraSize = []byte{0x18, 0x00, 0x00, 0x00}
RPCProxyRequestProxyTag = []byte{0xae, 0x26, 0x1e, 0xdb}
RPCHandshakeSenderPID = []byte{}
RPCHandshakePeerPID = []byte{}
) )
func init() {
RPCHandshakeSenderPID = []byte("IPIPPRPDTIME")
RPCHandshakePeerPID = []byte("IPIPPRPDTIME")
}
+5 -30
View File
@@ -1,46 +1,21 @@
package rpc package rpc
import ( import "bytes"
"bytes"
)
const (
rpcHandshakeTagLength = 4
rpcHandshakeFlagsLength = 4
rpcHandshakeSenderPIDLength = 12
rpcHandshakePeerPIDLength = rpcHandshakeSenderPIDLength
rpcHandshakeRequestLength = rpcHandshakeTagLength + rpcHandshakeFlagsLength + rpcHandshakeSenderPIDLength + rpcHandshakePeerPIDLength
)
var (
rpcHandshakeSenderPID [rpcHandshakeSenderPIDLength]byte
rpcHandshakePeerPID [rpcHandshakePeerPIDLength]byte
rpcHandshakeTag = [rpcHandshakeTagLength]byte{0xf5, 0xee, 0x82, 0x76}
rpcHandshakeFlags = [rpcHandshakeFlagsLength]byte{0x00, 0x00, 0x00, 0x00}
)
type RPCHandshakeRequest struct { type RPCHandshakeRequest struct {
} }
func (r *RPCHandshakeRequest) Bytes() []byte { func (r *RPCHandshakeRequest) Bytes() []byte {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
buf.Grow(rpcHandshakeRequestLength)
buf.Write(rpcHandshakeTag[:]) buf.Write(RPCTagHandshake)
buf.Write(rpcHandshakeFlags[:]) buf.Write(RPCHandshakeFlags)
buf.Write(rpcHandshakeSenderPID[:]) buf.Write(RPCHandshakeSenderPID)
buf.Write(rpcHandshakePeerPID[:]) buf.Write(RPCHandshakePeerPID)
return buf.Bytes() return buf.Bytes()
} }
func init() {
copy(rpcHandshakeSenderPID[:], "IPIPPRPDTIME")
copy(rpcHandshakePeerPID[:], "IPIPPRPDTIME")
}
func NewRPCHandshakeRequest() *RPCHandshakeRequest { func NewRPCHandshakeRequest() *RPCHandshakeRequest {
return &RPCHandshakeRequest{} return &RPCHandshakeRequest{}
} }
+13 -17
View File
@@ -6,18 +6,15 @@ import (
"github.com/juju/errors" "github.com/juju/errors"
) )
const rpcHandshakeResponseLength = rpcHandshakeRequestLength
type RPCHandshakeResponse struct { type RPCHandshakeResponse struct {
Type [rpcHandshakeTagLength]byte Type []byte
Flags [rpcHandshakeFlagsLength]byte Flags []byte
SenderPID [rpcHandshakeSenderPIDLength]byte SenderPID []byte
PeerPID [rpcHandshakePeerPIDLength]byte PeerPID []byte
} }
func (r *RPCHandshakeResponse) Bytes() []byte { func (r *RPCHandshakeResponse) Bytes() []byte {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
buf.Grow(rpcHandshakeResponseLength)
buf.Write(r.Type[:]) buf.Write(r.Type[:])
buf.Write(r.Flags[:]) buf.Write(r.Flags[:])
@@ -28,10 +25,10 @@ func (r *RPCHandshakeResponse) Bytes() []byte {
} }
func (r *RPCHandshakeResponse) Valid(req *RPCHandshakeRequest) error { func (r *RPCHandshakeResponse) Valid(req *RPCHandshakeRequest) error {
if r.Type != rpcHandshakeTag { if !bytes.Equal(r.Type, RPCTagHandshake) {
return errors.New("Unexpected handshake tag") return errors.New("Unexpected handshake tag")
} }
if r.PeerPID != rpcHandshakeSenderPID { if !bytes.Equal(r.PeerPID, RPCHandshakeSenderPID) {
return errors.New("Incorrect sender PID") return errors.New("Incorrect sender PID")
} }
@@ -39,15 +36,14 @@ func (r *RPCHandshakeResponse) Valid(req *RPCHandshakeRequest) error {
} }
func NewRPCHandshakeResponse(data []byte) (*RPCHandshakeResponse, error) { func NewRPCHandshakeResponse(data []byte) (*RPCHandshakeResponse, error) {
if len(data) != rpcHandshakeResponseLength { if len(data) != 32 {
return nil, errors.New("Incorrect handshake response length") return nil, errors.New("Incorrect handshake response length")
} }
resp := RPCHandshakeResponse{} return &RPCHandshakeResponse{
copy(resp.Type[:], data[:4]) Type: data[:4],
copy(resp.Flags[:], data[4:8]) Flags: data[4:8],
copy(resp.SenderPID[:], data[8:20]) SenderPID: data[8:20],
copy(resp.PeerPID[:], data[20:]) PeerPID: data[20:],
}, nil
return &resp, nil
} }
+14 -30
View File
@@ -9,52 +9,36 @@ import (
"github.com/juju/errors" "github.com/juju/errors"
) )
const (
rpcNonceLength = 16
rpcNonceKeySelectorLength = 4
rpcNonceCryptoTSLength = 4
rpcNonceTagLength = 4
rpcNonceCryptoAESLength = 4
rpcNonceRequestLength = rpcNonceTagLength + rpcNonceKeySelectorLength + rpcNonceCryptoAESLength + rpcNonceCryptoTSLength + rpcNonceLength
)
var (
rpcNonceTag = [rpcNonceTagLength]byte{0xaa, 0x87, 0xcb, 0x7a}
rpcNonceCryptoAESTag = [rpcNonceCryptoAESLength]byte{0x01, 0x00, 0x00, 0x00}
)
type RPCNonceRequest struct { type RPCNonceRequest struct {
KeySelector [rpcNonceKeySelectorLength]byte KeySelector []byte
CryptoTS [rpcNonceCryptoTSLength]byte CryptoTS []byte
Nonce [rpcNonceLength]byte Nonce []byte
} }
func (r *RPCNonceRequest) Bytes() []byte { func (r *RPCNonceRequest) Bytes() []byte {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
buf.Grow(rpcNonceRequestLength)
buf.Write(rpcNonceTag[:]) buf.Write(RPCTagNonce)
buf.Write(r.KeySelector[:]) buf.Write(r.KeySelector)
buf.Write(rpcNonceCryptoAESTag[:]) buf.Write(RPCNonceCryptoAES)
buf.Write(r.CryptoTS[:]) buf.Write(r.CryptoTS)
buf.Write(r.Nonce[:]) buf.Write(r.Nonce)
return buf.Bytes() return buf.Bytes()
} }
func NewRPCNonceRequest(proxySecret []byte) (*RPCNonceRequest, error) { func NewRPCNonceRequest(proxySecret []byte) (*RPCNonceRequest, error) {
var nonce [rpcNonceLength]byte nonce := make([]byte, 16)
var keySelector [rpcNonceKeySelectorLength]byte keySelector := make([]byte, 4)
var cryptoTS [rpcNonceCryptoTSLength]byte cryptoTS := make([]byte, 4)
if _, err := rand.Read(nonce[:]); err != nil { if _, err := rand.Read(nonce); err != nil {
return nil, errors.Annotate(err, "Cannot generate nonce") return nil, errors.Annotate(err, "Cannot generate nonce")
} }
copy(keySelector[:], proxySecret) copy(keySelector, proxySecret)
timestamp := time.Now().Truncate(time.Second).Unix() % 4294967296 // 256 ^ 4 - do not know how to name timestamp := time.Now().Truncate(time.Second).Unix() % 4294967296 // 256 ^ 4 - do not know how to name
binary.LittleEndian.PutUint32(cryptoTS[:], uint32(timestamp)) binary.LittleEndian.PutUint32(cryptoTS, uint32(timestamp))
return &RPCNonceRequest{ return &RPCNonceRequest{
KeySelector: keySelector, KeySelector: keySelector,
+20 -22
View File
@@ -6,36 +6,33 @@ import (
"github.com/juju/errors" "github.com/juju/errors"
) )
const rpcNonceResponseLength = rpcNonceRequestLength
type RPCNonceResponse struct { type RPCNonceResponse struct {
RPCNonceRequest RPCNonceRequest
RPCType [rpcNonceTagLength]byte RPCType []byte
Crypto [rpcNonceCryptoAESLength]byte Crypto []byte
} }
func (r *RPCNonceResponse) Bytes() []byte { func (r *RPCNonceResponse) Bytes() []byte {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
buf.Grow(rpcNonceResponseLength)
buf.Write(r.RPCType[:]) buf.Write(r.RPCType)
buf.Write(r.KeySelector[:]) buf.Write(r.KeySelector)
buf.Write(r.Crypto[:]) buf.Write(r.Crypto)
buf.Write(r.CryptoTS[:]) buf.Write(r.CryptoTS)
buf.Write(r.Nonce[:]) buf.Write(r.Nonce)
return buf.Bytes() return buf.Bytes()
} }
func (r *RPCNonceResponse) Valid(req *RPCNonceRequest) error { func (r *RPCNonceResponse) Valid(req *RPCNonceRequest) error {
if r.RPCType != rpcNonceTag { if !bytes.Equal(r.RPCType, RPCTagNonce) {
return errors.New("Unexpected RPC type") return errors.New("Unexpected RPC type")
} }
if r.Crypto != rpcNonceCryptoAESTag { if !bytes.Equal(r.Crypto, RPCNonceCryptoAES) {
return errors.New("Unexpected crypto type") return errors.New("Unexpected crypto type")
} }
if r.KeySelector != req.KeySelector { if !bytes.Equal(r.KeySelector, req.KeySelector) {
return errors.New("Unexpected key selector") return errors.New("Unexpected key selector")
} }
@@ -43,16 +40,17 @@ func (r *RPCNonceResponse) Valid(req *RPCNonceRequest) error {
} }
func NewRPCNonceResponse(data []byte) (*RPCNonceResponse, error) { func NewRPCNonceResponse(data []byte) (*RPCNonceResponse, error) {
if len(data) != rpcNonceResponseLength { if len(data) != 32 {
return nil, errors.New("Unexpected message length") return nil, errors.New("Unexpected message length")
} }
resp := RPCNonceResponse{} return &RPCNonceResponse{
copy(resp.RPCType[:], data[:4]) RPCNonceRequest: RPCNonceRequest{
copy(resp.KeySelector[:], data[4:8]) KeySelector: data[4:8],
copy(resp.Crypto[:], data[8:12]) CryptoTS: data[12:16],
copy(resp.CryptoTS[:], data[12:16]) Nonce: data[16:],
copy(resp.Nonce[:], data[16:]) },
RPCType: data[:4],
return &resp, nil Crypto: data[8:12],
}, nil
} }
+18 -26
View File
@@ -11,22 +11,11 @@ import (
"github.com/9seconds/mtg/mtproto" "github.com/9seconds/mtg/mtproto"
) )
const (
rpcProxyRequestConnectionIDLength = 8
rpcProxyRequestIPPortLength = 16 + 4
)
var (
rpcProxyRequestTag = []byte{0xee, 0xf1, 0xce, 0x36}
rpcProxyRequestExtraSize = []byte{0x18, 0x00, 0x00, 0x00}
rpcProxyRequestProxyTag = []byte{0xae, 0x26, 0x1e, 0xdb}
)
type RPCProxyRequest struct { type RPCProxyRequest struct {
Flags RPCProxyRequestFlags Flags RPCProxyRequestFlags
ConnectionID [rpcProxyRequestConnectionIDLength]byte ConnectionID []byte
OurIPPort [rpcProxyRequestIPPortLength]byte OurIPPort []byte
ClientIPPort [rpcProxyRequestIPPortLength]byte ClientIPPort []byte
ADTag []byte ADTag []byte
Options *mtproto.ConnectionOpts Options *mtproto.ConnectionOpts
} }
@@ -43,13 +32,13 @@ func (r *RPCProxyRequest) Bytes(message []byte) []byte {
flags |= RPCProxyRequestFlagsEncrypted flags |= RPCProxyRequestFlagsEncrypted
} }
buf.Write(rpcProxyRequestTag) buf.Write(RPCTagProxyRequest)
buf.Write(flags.Bytes()) buf.Write(flags.Bytes())
buf.Write(r.ConnectionID[:]) buf.Write(r.ConnectionID[:])
buf.Write(r.ClientIPPort[:]) buf.Write(r.ClientIPPort[:])
buf.Write(r.OurIPPort[:]) buf.Write(r.OurIPPort[:])
buf.Write(rpcProxyRequestExtraSize) buf.Write(RPCProxyRequestExtraSize)
buf.Write(rpcProxyRequestProxyTag) buf.Write(RPCProxyRequestProxyTag)
buf.WriteByte(byte(len(r.ADTag))) buf.WriteByte(byte(len(r.ADTag)))
buf.Write(r.ADTag) buf.Write(r.ADTag)
buf.Write(bytes.Repeat([]byte{0x00}, buf.Len()%4)) buf.Write(bytes.Repeat([]byte{0x00}, buf.Len()%4))
@@ -69,23 +58,26 @@ func NewRPCProxyRequest(clientAddr, ownAddr *net.TCPAddr, opts *mtproto.Connecti
} }
request := RPCProxyRequest{ request := RPCProxyRequest{
Flags: flags, Flags: flags,
ADTag: adTag, ADTag: adTag,
Options: opts, Options: opts,
ConnectionID: make([]byte, 8),
ClientIPPort: make([]byte, 16+4),
OurIPPort: make([]byte, 16+4),
} }
if _, err := rand.Read(request.ConnectionID[:]); err != nil { if _, err := rand.Read(request.ConnectionID); err != nil {
return nil, errors.Annotate(err, "Cannot generate connection ID") return nil, errors.Annotate(err, "Cannot generate connection ID")
} }
port := make([]byte, 4) port := [4]byte{}
copy(request.ClientIPPort[:16], clientAddr.IP.To16()) copy(request.ClientIPPort[:16], clientAddr.IP.To16())
binary.LittleEndian.PutUint32(port, uint32(clientAddr.Port)) binary.LittleEndian.PutUint32(port[:], uint32(clientAddr.Port))
copy(request.ClientIPPort[16:], port) copy(request.ClientIPPort[16:], port[:])
copy(request.OurIPPort[:16], ownAddr.IP.To16()) copy(request.OurIPPort[:16], ownAddr.IP.To16())
binary.LittleEndian.PutUint32(port, uint32(ownAddr.Port)) binary.LittleEndian.PutUint32(port[:], uint32(ownAddr.Port))
copy(request.OurIPPort[16:], port) copy(request.OurIPPort[16:], port[:])
return &request, nil return &request, nil
} }