diff --git a/mtproto/rpc/rpc.go b/mtproto/rpc/rpc.go index dc07a21..f72bfdd 100644 --- a/mtproto/rpc/rpc.go +++ b/mtproto/rpc/rpc.go @@ -1,5 +1,12 @@ package rpc +import "bytes" + +const ( + RPCNonceSeqNo = -2 + RPCHandshakeSeqNo = -1 +) + type RPC interface { - Bytes() []byte + Bytes() *bytes.Buffer } diff --git a/mtproto/rpc/rpc_handshake_request.go b/mtproto/rpc/rpc_handshake_request.go new file mode 100644 index 0000000..662d7a7 --- /dev/null +++ b/mtproto/rpc/rpc_handshake_request.go @@ -0,0 +1,47 @@ +package rpc + +import "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} + + rpcHandshakeBuffer *bytes.Buffer +) + +type RPCHandshakeRequest struct { +} + +func (r *RPCHandshakeRequest) Bytes() *bytes.Buffer { + buf := &bytes.Buffer{} + buf.Grow(rpcHandshakeRequestLength) + + buf.Write(rpcHandshakeTag[:]) + buf.Write(rpcHandshakeFlags[:]) + buf.Write(rpcHandshakeSenderPID[:]) + buf.Write(rpcHandshakePeerPID[:]) + + return buf +} + +func init() { + copy(rpcHandshakeSenderPID[:], "IPIPPRPDTIME") + copy(rpcHandshakePeerPID[:], "IPIPPRPDTIME") +} + +func NewRPCHandshakeRequest() *RPCHandshakeRequest { + return &RPCHandshakeRequest{} +} diff --git a/mtproto/rpc/rpc_handshake_response.go b/mtproto/rpc/rpc_handshake_response.go new file mode 100644 index 0000000..9af0984 --- /dev/null +++ b/mtproto/rpc/rpc_handshake_response.go @@ -0,0 +1,53 @@ +package rpc + +import ( + "bytes" + + "github.com/juju/errors" +) + +const rpcHandshakeResponseLength = rpcHandshakeRequestLength + +type RPCHandshakeResponse struct { + Type [rpcHandshakeTagLength]byte + Flags [rpcHandshakeFlagsLength]byte + SenderPID [rpcHandshakeSenderPIDLength]byte + PeerPID [rpcHandshakePeerPIDLength]byte +} + +func (r *RPCHandshakeResponse) Bytes() *bytes.Buffer { + buf := &bytes.Buffer{} + buf.Grow(rpcHandshakeResponseLength) + + buf.Write(r.Type[:]) + buf.Write(r.Flags[:]) + buf.Write(r.SenderPID[:]) + buf.Write(r.PeerPID[:]) + + return buf +} + +func (r *RPCHandshakeResponse) Valid(req *RPCHandshakeRequest) error { + if r.Type != rpcHandshakeTag { + return errors.New("Unexpected handshake tag") + } + if r.PeerPID != rpcHandshakeSenderPID { + return errors.New("Incorrect sender PID") + } + + return nil +} + +func NewRPCHandshakeResponse(data []byte) (*RPCHandshakeResponse, error) { + if len(data) != rpcHandshakeResponseLength { + return nil, errors.New("Incorrect handshake response length") + } + + resp := RPCHandshakeResponse{} + copy(resp.Type[:], data[:4]) + copy(resp.Flags[:], data[4:8]) + copy(resp.SenderPID[:], data[8:20]) + copy(resp.PeerPID[:], data[20:]) + + return &resp, nil +} diff --git a/mtproto/rpc/rpc_nonce_request.go b/mtproto/rpc/rpc_nonce_request.go index 8dd29e4..b94d814 100644 --- a/mtproto/rpc/rpc_nonce_request.go +++ b/mtproto/rpc/rpc_nonce_request.go @@ -10,8 +10,6 @@ import ( ) const ( - RPCNonceSeqNo = -2 - rpcNonceLength = 16 rpcNonceKeySelectorLength = 4 rpcNonceCryptoTSLength = 4 @@ -33,7 +31,7 @@ type RPCNonceRequest struct { Nonce [rpcNonceLength]byte } -func (r *RPCNonceRequest) Bytes() []byte { +func (r *RPCNonceRequest) Bytes() *bytes.Buffer { buf := &bytes.Buffer{} buf.Grow(rpcNonceRequestLength) @@ -43,7 +41,7 @@ func (r *RPCNonceRequest) Bytes() []byte { buf.Write(r.CryptoTS[:]) buf.Write(r.Nonce[:]) - return buf.Bytes() + return buf } func NewRPCNonceRequest(proxySecret []byte) (*RPCNonceRequest, error) { diff --git a/mtproto/rpc/rpc_nonce_response.go b/mtproto/rpc/rpc_nonce_response.go index 7cf90fc..cad02c3 100644 --- a/mtproto/rpc/rpc_nonce_response.go +++ b/mtproto/rpc/rpc_nonce_response.go @@ -15,7 +15,7 @@ type RPCNonceResponse struct { Crypto [rpcNonceCryptoAESLength]byte } -func (r *RPCNonceResponse) Bytes() []byte { +func (r *RPCNonceResponse) Bytes() *bytes.Buffer { buf := &bytes.Buffer{} buf.Grow(rpcNonceResponseLength) @@ -25,7 +25,7 @@ func (r *RPCNonceResponse) Bytes() []byte { buf.Write(r.CryptoTS[:]) buf.Write(r.Nonce[:]) - return buf.Bytes() + return buf } func (r *RPCNonceResponse) Valid(req *RPCNonceRequest) error {