mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-08-31 19:04:02 +03:00
FILE / ScuroNeko/mtg
_mtproto/rpc/proxy_request.go
Исходный файл и его история в репозитории.
106 lines
3.0 KiB
Go
106 lines
3.0 KiB
Go
package rpc
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/rand"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"net"
|
|
|
|
"github.com/juju/errors"
|
|
|
|
"github.com/9seconds/mtg/mtproto"
|
|
)
|
|
|
|
// ProxyRequest is the data type for storing data required to compose
|
|
// RPC_PROXY_REQ request.
|
|
type ProxyRequest struct {
|
|
Flags proxyRequestFlags
|
|
ConnectionID []byte
|
|
OurIPPort []byte
|
|
ClientIPPort []byte
|
|
ADTag []byte
|
|
Options *mtproto.ConnectionOpts
|
|
}
|
|
|
|
// MakeHeader makes RPC_PROXY_REQ header. We need only to append the
|
|
// data for it.
|
|
func (r *ProxyRequest) MakeHeader(message []byte) (*bytes.Buffer, fmt.Stringer) {
|
|
bufferLength := len(TagProxyRequest) +
|
|
4 + // len(flags)
|
|
len(r.ConnectionID) +
|
|
len(r.ClientIPPort) +
|
|
len(r.OurIPPort) +
|
|
len(ProxyRequestExtraSize) +
|
|
len(ProxyRequestProxyTag) +
|
|
1 + // len(AdTag)
|
|
len(r.ADTag)
|
|
bufferLength += bufferLength % 4
|
|
|
|
buf := &bytes.Buffer{}
|
|
buf.Grow(bufferLength + len(message))
|
|
|
|
flags := r.Flags
|
|
if r.Options.ReadHacks.QuickAck {
|
|
flags |= proxyRequestFlagsQuickAck
|
|
}
|
|
|
|
if bytes.HasPrefix(message, proxyRequestFlagsEncryptedPrefix[:]) {
|
|
flags |= proxyRequestFlagsEncrypted
|
|
}
|
|
|
|
buf.Write(TagProxyRequest) // nolint: gosec
|
|
buf.Write(flags.Bytes()) // nolint: gosec
|
|
buf.Write(r.ConnectionID) // nolint: gosec
|
|
buf.Write(r.ClientIPPort) // nolint: gosec
|
|
buf.Write(r.OurIPPort) // nolint: gosec
|
|
buf.Write(ProxyRequestExtraSize) // nolint: gosec
|
|
buf.Write(ProxyRequestProxyTag) // nolint: gosec
|
|
buf.WriteByte(byte(len(r.ADTag))) // nolint: gosec
|
|
buf.Write(r.ADTag) // nolint: gosec
|
|
buf.Write(make([]byte, (4-buf.Len()%4)%4)) // nolint: gosec
|
|
|
|
return buf, flags
|
|
}
|
|
|
|
// NewProxyRequest build new ProxyRequest data structure.
|
|
func NewProxyRequest(clientAddr, ownAddr *net.TCPAddr,
|
|
opts *mtproto.ConnectionOpts, adTag []byte) (*ProxyRequest, error) {
|
|
flags := proxyRequestFlagsHasAdTag | proxyRequestFlagsMagic | proxyRequestFlagsExtMode2
|
|
|
|
switch opts.ConnectionType {
|
|
case mtproto.ConnectionTypeAbridged:
|
|
flags |= proxyRequestFlagsAbdridged
|
|
case mtproto.ConnectionTypeIntermediate:
|
|
flags |= proxyRequestFlagsIntermediate
|
|
case mtproto.ConnectionTypeSecure:
|
|
flags |= proxyRequestFlagsIntermediate | proxyRequestFlagsPad
|
|
default:
|
|
panic("Unknown connection type")
|
|
}
|
|
|
|
request := &ProxyRequest{
|
|
Flags: flags,
|
|
ADTag: adTag,
|
|
Options: opts,
|
|
ConnectionID: make([]byte, 8),
|
|
ClientIPPort: make([]byte, 16+4),
|
|
OurIPPort: make([]byte, 16+4),
|
|
}
|
|
|
|
if _, err := rand.Read(request.ConnectionID); err != nil {
|
|
return nil, errors.Annotate(err, "Cannot generate connection ID")
|
|
}
|
|
|
|
port := [4]byte{}
|
|
copy(request.ClientIPPort[:16], clientAddr.IP.To16())
|
|
binary.LittleEndian.PutUint32(port[:], uint32(clientAddr.Port))
|
|
copy(request.ClientIPPort[16:], port[:])
|
|
|
|
copy(request.OurIPPort[:16], ownAddr.IP.To16())
|
|
binary.LittleEndian.PutUint32(port[:], uint32(ownAddr.Port))
|
|
copy(request.OurIPPort[16:], port[:])
|
|
|
|
return request, nil
|
|
}
|