| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- package packetack
-
- import (
- "bytes"
- "encoding/binary"
- "fmt"
- "net"
-
- "github.com/9seconds/mtg/config"
- "github.com/9seconds/mtg/conntypes"
- "github.com/9seconds/mtg/hub"
- "github.com/9seconds/mtg/mtproto/rpc"
- "github.com/9seconds/mtg/protocol"
- )
-
- type wrapperProxy struct {
- request *protocol.TelegramRequest
- proxy *hub.ProxyConn
- clientIPPort []byte
- ourIPPort []byte
- flags rpc.ProxyRequestFlags
- }
-
- func (w *wrapperProxy) Write(packet conntypes.Packet, acks *conntypes.ConnectionAcks) error {
- buf := bytes.Buffer{}
- flags := w.flags
-
- if acks.Quick {
- flags |= rpc.ProxyRequestFlagsQuickAck
- }
-
- if bytes.HasPrefix(packet, rpc.ProxyRequestFlagsEncryptedPrefix[:]) {
- flags |= rpc.ProxyRequestFlagsEncrypted
- }
-
- buf.Write(rpc.TagProxyRequest)
- buf.Write(flags.Bytes())
- buf.Write(w.request.ConnID[:])
- buf.Write(w.clientIPPort)
- buf.Write(w.ourIPPort)
- buf.Write(rpc.ProxyRequestExtraSize)
- buf.Write(rpc.ProxyRequestProxyTag)
- buf.WriteByte(byte(len(config.C.AdTag)))
- buf.Write(config.C.AdTag)
- buf.Write(make([]byte, (4-buf.Len()%4)%4))
- buf.Grow(len(packet))
- buf.Write(packet)
-
- return w.proxy.Write(buf.Bytes()) // nolint: wrapcheck
- }
-
- func (w *wrapperProxy) Read(acks *conntypes.ConnectionAcks) (conntypes.Packet, error) {
- resp, err := w.proxy.Read()
- if err != nil {
- return nil, fmt.Errorf("cannot read a response: %w", err)
- }
-
- if resp.Type == rpc.ProxyResponseTypeSimpleAck {
- acks.Simple = true
- }
-
- return resp.Payload, nil
- }
-
- func (w *wrapperProxy) Close() error {
- w.proxy.Close()
-
- return nil
- }
-
- func NewProxy(request *protocol.TelegramRequest) (conntypes.PacketAckReadWriteCloser, error) {
- flags := rpc.ProxyRequestFlagsHasAdTag | rpc.ProxyRequestFlagsMagic | rpc.ProxyRequestFlagsExtMode2
-
- switch request.ClientProtocol.ConnectionType() {
- case conntypes.ConnectionTypeAbridged:
- flags |= rpc.ProxyRequestFlagsAbdridged
- case conntypes.ConnectionTypeIntermediate:
- flags |= rpc.ProxyRequestFlagsIntermediate
- case conntypes.ConnectionTypeSecure:
- flags |= rpc.ProxyRequestFlagsIntermediate | rpc.ProxyRequestFlagsPad
- case conntypes.ConnectionTypeUnknown:
- panic("unknown connection type")
- }
-
- proxy, err := hub.Hub.Register(request)
- if err != nil {
- return nil, fmt.Errorf("cannot make a new proxy wrapper: %w", err)
- }
-
- return &wrapperProxy{
- flags: flags,
- request: request,
- proxy: proxy,
- clientIPPort: proxyGetIPPort(request.ClientConn.RemoteAddr()),
- ourIPPort: proxyGetIPPort(request.ClientConn.LocalAddr()),
- }, nil
- }
-
- func proxyGetIPPort(addr *net.TCPAddr) []byte {
- rv := [16 + 4]byte{}
- port := [4]byte{}
-
- copy(rv[:16], addr.IP.To16())
- binary.LittleEndian.PutUint32(port[:], uint32(addr.Port))
- copy(rv[16:], port[:])
-
- return rv[:]
- }
|