playit.gg go implementation #1
67
api/api.go
67
api/api.go
@ -1,7 +1,12 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
GoPlayitVersion string = "0.17.1"
|
GoPlayitVersion string = "0.17.1"
|
||||||
|
PlayitAPI string = "https://api.playit.gg" // Playit API
|
||||||
|
|
||||||
TunnelTypeMCBedrock string = "minecraft-bedrock" // Minecraft Bedrock server
|
TunnelTypeMCBedrock string = "minecraft-bedrock" // Minecraft Bedrock server
|
||||||
TunnelTypeMCJava string = "minecraft-java" // Minecraft java server
|
TunnelTypeMCJava string = "minecraft-java" // Minecraft java server
|
||||||
@ -26,12 +31,6 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
PlayitAPI string = "https://api.playit.gg" // Playit API
|
|
||||||
PortType []string = []string{
|
|
||||||
PortTypeBoth,
|
|
||||||
PortTypeTcp,
|
|
||||||
PortTypeUdp,
|
|
||||||
} // Tunnel protocol supports
|
|
||||||
TunnelType []string = []string{
|
TunnelType []string = []string{
|
||||||
TunnelTypeMCBedrock,
|
TunnelTypeMCBedrock,
|
||||||
TunnelTypeMCJava,
|
TunnelTypeMCJava,
|
||||||
@ -57,3 +56,59 @@ type Api struct {
|
|||||||
Code string // Claim code
|
Code string // Claim code
|
||||||
Secret string // Agent Secret
|
Secret string // Agent Secret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PortProto string
|
||||||
|
func (proto PortProto) IsValid() bool {
|
||||||
|
switch proto {
|
||||||
|
case PortProto(PortTypeBoth):
|
||||||
|
case PortProto(PortTypeTcp):
|
||||||
|
case PortProto(PortTypeUdp): return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func (proto PortProto) SetBoth() {
|
||||||
|
proto = "both"
|
||||||
|
}
|
||||||
|
func (proto PortProto) SetTcp() {
|
||||||
|
proto = "tcp"
|
||||||
|
}
|
||||||
|
func (proto PortProto) SetUdp() {
|
||||||
|
proto = "udp"
|
||||||
|
}
|
||||||
|
|
||||||
|
type Platform string
|
||||||
|
func (Platform Platform) Host() {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "linux": Platform = "linux";
|
||||||
|
case "freebsd": Platform = "freebsd";
|
||||||
|
case "windows": Platform = "windows";
|
||||||
|
case "darwin": Platform = "macos";
|
||||||
|
case "android": Platform = "android";
|
||||||
|
case "ios": Platform = "ios";
|
||||||
|
default: Platform = "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (Platform Platform) Linux() {
|
||||||
|
Platform = "linux"
|
||||||
|
}
|
||||||
|
func (Platform Platform) Freebsd() {
|
||||||
|
Platform = "freebsd"
|
||||||
|
}
|
||||||
|
func (Platform Platform) Windows() {
|
||||||
|
Platform = "windows"
|
||||||
|
}
|
||||||
|
func (Platform Platform) Macos() {
|
||||||
|
Platform = "macos"
|
||||||
|
}
|
||||||
|
func (Platform Platform) Android() {
|
||||||
|
Platform = "android"
|
||||||
|
}
|
||||||
|
func (Platform Platform) Ios() {
|
||||||
|
Platform = "ios"
|
||||||
|
}
|
||||||
|
func (Platform Platform) MinecraftPlugin() {
|
||||||
|
Platform = "minecraft-plugin"
|
||||||
|
}
|
||||||
|
func (Platform Platform) Unknown() {
|
||||||
|
Platform = "unknown"
|
||||||
|
}
|
@ -12,7 +12,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ClaimAgents []string = []string{
|
ClaimAgents []string = []string{
|
||||||
"default", "assignable", "self-managed",
|
"default", "assignable", "self-managed",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -32,7 +32,7 @@ type AgentTunnel struct {
|
|||||||
type AgentPendingTunnel struct {
|
type AgentPendingTunnel struct {
|
||||||
ID uuid.UUID `json:"id"` // Agent ID
|
ID uuid.UUID `json:"id"` // Agent ID
|
||||||
Name string `json:"name"` // Agent Name
|
Name string `json:"name"` // Agent Name
|
||||||
PortType string `json:"proto"` // Port type
|
PortType PortProto `json:"proto"` // Port type
|
||||||
PortCount uint16 `json:"port_count"` // Port count
|
PortCount uint16 `json:"port_count"` // Port count
|
||||||
TunnelType string `json:"tunnel_type"` // Tunnel type
|
TunnelType string `json:"tunnel_type"` // Tunnel type
|
||||||
Disabled bool `json:"is_disabled"` // Tunnel is disabled
|
Disabled bool `json:"is_disabled"` // Tunnel is disabled
|
||||||
|
@ -46,22 +46,22 @@ func (w *Api) requestToApi(Path string, Body io.Reader, Response any, Headers ma
|
|||||||
if err = json.NewDecoder(res.Body).Decode(&ResBody); err != nil {
|
if err = json.NewDecoder(res.Body).Decode(&ResBody); err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if res.StatusCode >= 300 {
|
if res.StatusCode >= 300 {
|
||||||
|
defer res.Body.Close()
|
||||||
var errStatus struct {
|
var errStatus struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
if data, is := ResBody.Data.(string); is {
|
if data, is := ResBody.Data.(string); is {
|
||||||
return res, fmt.Errorf(data)
|
return res, fmt.Errorf("api.playit.gg: %s", data)
|
||||||
} else if err = recodeJson(&ResBody.Data, &errStatus); err != nil {
|
} else if err = recodeJson(&ResBody.Data, &errStatus); err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
if len(errStatus.Message) > 0 {
|
if len(errStatus.Message) > 0 {
|
||||||
return res, fmt.Errorf("%s: %s", errStatus.Type, errStatus.Message)
|
return res, fmt.Errorf("api.playit.gg: %s %s", errStatus.Type, errStatus.Message)
|
||||||
}
|
}
|
||||||
return res, fmt.Errorf("%s", errStatus.Type)
|
return res, fmt.Errorf("api.playit.gg: %s", errStatus.Type)
|
||||||
}
|
}
|
||||||
if Response != nil {
|
if Response != nil {
|
||||||
if err = recodeJson(&ResBody.Data, Response); err != nil {
|
if err = recodeJson(&ResBody.Data, Response); err != nil {
|
||||||
|
@ -54,23 +54,26 @@ type UseAllocPortAlloc struct {
|
|||||||
type UseRegion struct {
|
type UseRegion struct {
|
||||||
Region string `json:"region"`
|
Region string `json:"region"`
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
"status": "allocated",
|
"status": "allocated",
|
||||||
"data": {
|
|
||||||
"assigned_domain": "going-scales.gl.at.ply.gg",
|
"data": {
|
||||||
"assigned_srv": null,
|
"assigned_domain": "going-scales.gl.at.ply.gg",
|
||||||
"assignment": {
|
"assigned_srv": null,
|
||||||
"type": "shared-ip"
|
"assignment": {
|
||||||
},
|
"type": "shared-ip"
|
||||||
"id": "f667b538-0294-4817-9332-5cba5e94d79e",
|
},
|
||||||
"ip_hostname": "19.ip.gl.ply.gg",
|
"id": "f667b538-0294-4817-9332-5cba5e94d79e",
|
||||||
"ip_type": "both",
|
"ip_hostname": "19.ip.gl.ply.gg",
|
||||||
"port_end": 49913,
|
"ip_type": "both",
|
||||||
"port_start": 49912,
|
"port_end": 49913,
|
||||||
"region": "global",
|
"port_start": 49912,
|
||||||
"static_ip4": "147.185.221.19",
|
"region": "global",
|
||||||
"tunnel_ip": "2602:fbaf:0:1::13"
|
"static_ip4": "147.185.221.19",
|
||||||
}
|
"tunnel_ip": "2602:fbaf:0:1::13"
|
||||||
|
}
|
||||||
*/
|
*/
|
||||||
type TunnelCreateUseAllocation struct {
|
type TunnelCreateUseAllocation struct {
|
||||||
Status string `json:"status"` // For tunnel list
|
Status string `json:"status"` // For tunnel list
|
||||||
@ -99,7 +102,7 @@ type Tunnel struct {
|
|||||||
ID *uuid.UUID `json:"tunnel_id,omitempty"` // Tunnel UUID
|
ID *uuid.UUID `json:"tunnel_id,omitempty"` // Tunnel UUID
|
||||||
Name string `json:"name,omitempty"` // Tunnel name
|
Name string `json:"name,omitempty"` // Tunnel name
|
||||||
TunnelType string `json:"tunnel_type,omitempty"` // Tunnel type from TunnelType const's
|
TunnelType string `json:"tunnel_type,omitempty"` // Tunnel type from TunnelType const's
|
||||||
PortType string `json:"port_type"` // tcp, udp or both
|
PortType PortProto `json:"port_type"` // tcp, udp or both
|
||||||
PortCount uint16 `json:"port_count"` // Port count to assign to connect
|
PortCount uint16 `json:"port_count"` // Port count to assign to connect
|
||||||
Origin TunnelOriginCreate `json:"origin"`
|
Origin TunnelOriginCreate `json:"origin"`
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
@ -167,14 +170,14 @@ func (w *Api) DeleteTunnel(TunnelID *uuid.UUID) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AccountTunnel struct {
|
type AccountTunnel struct {
|
||||||
ID uuid.UUID `json:"id"`
|
ID uuid.UUID `json:"id"`
|
||||||
TunnelType string `json:"tunnel_type"`
|
TunnelType string `json:"tunnel_type"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
PortType string `json:"port_type"`
|
PortType PortProto `json:"port_type"`
|
||||||
PortCount int32 `json:"port_count"`
|
PortCount int32 `json:"port_count"`
|
||||||
Alloc TunnelCreateUseAllocation `json:"alloc"`
|
Alloc TunnelCreateUseAllocation `json:"alloc"`
|
||||||
Origin TunnelOriginCreate `json:"origin"`
|
Origin TunnelOriginCreate `json:"origin"`
|
||||||
Domain *struct {
|
Domain *struct {
|
||||||
ID uuid.UUID `json:"id"`
|
ID uuid.UUID `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
package tunnel
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/netip"
|
|
||||||
"slices"
|
|
||||||
|
|
||||||
"sirherobrine23.org/playit-cloud/go-playit/api"
|
|
||||||
)
|
|
||||||
|
|
||||||
type PortType struct {
|
|
||||||
Value string
|
|
||||||
}
|
|
||||||
func (w *PortType) IsValid() bool {
|
|
||||||
return slices.Contains(api.PortType, w.Value)
|
|
||||||
}
|
|
||||||
func (proto *PortProto) SetBoth() {
|
|
||||||
proto.Value = "both"
|
|
||||||
}
|
|
||||||
func (proto *PortProto) SetTcp() {
|
|
||||||
proto.Value = "tcp"
|
|
||||||
}
|
|
||||||
func (proto *PortProto) SetUdp() {
|
|
||||||
proto.Value = "udp"
|
|
||||||
}
|
|
||||||
|
|
||||||
type AddressValue[T any] struct {
|
|
||||||
Value T
|
|
||||||
FromPort, ToPort uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
type AddressLookup[T any] interface {
|
|
||||||
// Resolve address if exist return value else return nil point
|
|
||||||
Lookup(IpPort netip.AddrPort, Proto PortType) *AddressValue[T]
|
|
||||||
}
|
|
||||||
|
|
||||||
type MatchIp struct {
|
|
||||||
IP netip.AddrPort
|
|
||||||
RegionID *uint16
|
|
||||||
}
|
|
||||||
func (mat *MatchIp) Matches(ip netip.AddrPort) bool {
|
|
||||||
return mat.IP.Compare(ip) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type MappingOverride struct {
|
|
||||||
MatchIP MatchIp
|
|
||||||
Proto PortType
|
|
||||||
Port api.PortRange
|
|
||||||
LocalAddr netip.AddrPort
|
|
||||||
}
|
|
||||||
|
|
||||||
type LookupWithOverrides []MappingOverride
|
|
||||||
|
|
||||||
func (Look *LookupWithOverrides) Lookup(IpPort netip.AddrPort, Proto PortType) *AddressValue[netip.AddrPort] {
|
|
||||||
for _, Over := range *Look {
|
|
||||||
if Over.Proto.Value == Proto.Value && Over.MatchIP.Matches(IpPort) {
|
|
||||||
return &AddressValue[netip.AddrPort]{
|
|
||||||
Value: Over.LocalAddr,
|
|
||||||
FromPort: Over.Port.From,
|
|
||||||
ToPort: Over.Port.To,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &AddressValue[netip.AddrPort]{
|
|
||||||
Value: netip.AddrPortFrom(netip.AddrFrom4([4]byte{127, 0, 0, 1}), IpPort.Port()),
|
|
||||||
FromPort: IpPort.Port(),
|
|
||||||
ToPort: IpPort.Port() + 1,
|
|
||||||
}
|
|
||||||
}
|
|
219
tunnel/bigint.go
219
tunnel/bigint.go
@ -1,219 +0,0 @@
|
|||||||
package tunnel
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/netip"
|
|
||||||
)
|
|
||||||
|
|
||||||
type RawSlice struct {
|
|
||||||
Buff []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *RawSlice) WriteTo(I io.Writer) error {
|
|
||||||
_, err := I.Write(w.Buff)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
func (w *RawSlice) ReadFrom(I io.Reader) error {
|
|
||||||
_, err := I.Read(w.Buff)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadU8(w io.Reader) uint8 {
|
|
||||||
var value uint8
|
|
||||||
binary.Read(w, binary.BigEndian, &value)
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteU8(w io.Writer, value uint8) error {
|
|
||||||
return binary.Write(w, binary.BigEndian, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadU16(w io.Reader) uint16 {
|
|
||||||
var value uint16
|
|
||||||
binary.Read(w, binary.BigEndian, &value)
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteU16(w io.Writer, value uint16) error {
|
|
||||||
return binary.Write(w, binary.BigEndian, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadU32(w io.Reader) uint32 {
|
|
||||||
var value uint32
|
|
||||||
binary.Read(w, binary.BigEndian, &value)
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteU32(w io.Writer, value uint32) error {
|
|
||||||
return binary.Write(w, binary.BigEndian, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadU64(w io.Reader) uint64 {
|
|
||||||
var value uint64
|
|
||||||
binary.Read(w, binary.BigEndian, &value)
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteU64(w io.Writer, value uint64) error {
|
|
||||||
return binary.Write(w, binary.BigEndian, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteData(w io.Writer, val any) error {
|
|
||||||
return binary.Write(w, binary.BigEndian, val)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadBuff(w io.Reader, buff []byte) error {
|
|
||||||
for index := range buff {
|
|
||||||
if err := binary.Read(w, binary.BigEndian, &buff[index]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadBuffN(w io.Reader, size int) ([]byte, error) {
|
|
||||||
buff := make([]byte, size)
|
|
||||||
return buff, ReadBuff(w, buff)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadU8Buff(w io.Reader, buff []uint8) error {
|
|
||||||
for index := range buff {
|
|
||||||
if err := binary.Read(w, binary.BigEndian, &buff[index]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadU16Buff(w io.Reader, buff []uint16) error {
|
|
||||||
for index := range buff {
|
|
||||||
if err := binary.Read(w, binary.BigEndian, &buff[index]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadU32Buff(w io.Reader, buff []uint32) error {
|
|
||||||
for index := range buff {
|
|
||||||
if err := binary.Read(w, binary.BigEndian, &buff[index]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadU64Buff(w io.Reader, buff []uint64) error {
|
|
||||||
for index := range buff {
|
|
||||||
if err := binary.Read(w, binary.BigEndian, &buff[index]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadOption(w io.Reader, callback func(reader io.Reader) error) error {
|
|
||||||
code := ReadU8(w)
|
|
||||||
if code == 1 {
|
|
||||||
return callback(w)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteOption(w io.Writer, value MessageEncoding) error {
|
|
||||||
fmt.Printf("%+v\n", value)
|
|
||||||
if value != nil {
|
|
||||||
if err := binary.Write(w, binary.BigEndian, uint8(1)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return value.WriteTo(w)
|
|
||||||
}
|
|
||||||
return binary.Write(w, binary.BigEndian, uint8(0))
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteOptionU8(w io.Writer, value *uint8) error {
|
|
||||||
if value == nil {
|
|
||||||
return binary.Write(w, binary.BigEndian, uint8(0))
|
|
||||||
}
|
|
||||||
if err := binary.Write(w, binary.BigEndian, uint8(1)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return WriteU8(w, *value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteOptionU16(w io.Writer, value *uint16) error {
|
|
||||||
if value == nil {
|
|
||||||
return binary.Write(w, binary.BigEndian, uint8(0))
|
|
||||||
}
|
|
||||||
if err := binary.Write(w, binary.BigEndian, uint8(1)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return WriteU16(w, *value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteOptionU32(w io.Writer, value *uint32) error {
|
|
||||||
if value == nil {
|
|
||||||
return binary.Write(w, binary.BigEndian, uint8(0))
|
|
||||||
}
|
|
||||||
if err := binary.Write(w, binary.BigEndian, uint8(1)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return WriteU32(w, *value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteOptionU64(w io.Writer, value *uint64) error {
|
|
||||||
if value == nil {
|
|
||||||
return binary.Write(w, binary.BigEndian, uint8(0))
|
|
||||||
}
|
|
||||||
if err := binary.Write(w, binary.BigEndian, uint8(1)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return WriteU64(w, *value)
|
|
||||||
}
|
|
||||||
|
|
||||||
type AddressPort struct {
|
|
||||||
netip.AddrPort
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sock *AddressPort) WriteTo(w io.Writer) error {
|
|
||||||
addr := sock.Addr()
|
|
||||||
ip, _ := addr.MarshalBinary()
|
|
||||||
if addr.Is6() {
|
|
||||||
if err := WriteU8(w, uint8(6)); err != nil {
|
|
||||||
return err
|
|
||||||
} else if _, err = w.Write(ip); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err := WriteU8(w, uint8(4)); err != nil {
|
|
||||||
return err
|
|
||||||
} else if _, err = w.Write(ip); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := WriteU16(w, sock.Port()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (sock *AddressPort) ReadFrom(w io.Reader) error {
|
|
||||||
switch ReadU8(w) {
|
|
||||||
case 4:
|
|
||||||
buff, err := ReadBuffN(w, 4)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
sock.AddrPort = netip.AddrPortFrom(netip.AddrFrom4([4]byte(buff)), ReadU16(w))
|
|
||||||
return nil
|
|
||||||
case 6:
|
|
||||||
buff, err := ReadBuffN(w, 16)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
sock.AddrPort = netip.AddrPortFrom(netip.AddrFrom16([16]byte(buff)), ReadU16(w))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return fmt.Errorf("cannot get IP type")
|
|
||||||
}
|
|
178
tunnel/binary.go
Normal file
178
tunnel/binary.go
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
package tunnel
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/netip"
|
||||||
|
)
|
||||||
|
|
||||||
|
func readU8(r io.Reader) uint8 {
|
||||||
|
var d uint8
|
||||||
|
err := binary.Read(r, binary.BigEndian, d)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
func readU16(r io.Reader) uint16 {
|
||||||
|
var d uint16
|
||||||
|
err := binary.Read(r, binary.BigEndian, d)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
func readU32(r io.Reader) uint32 {
|
||||||
|
var d uint32
|
||||||
|
err := binary.Read(r, binary.BigEndian, d)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
func readU64(r io.Reader) uint64 {
|
||||||
|
var d uint64
|
||||||
|
err := binary.Read(r, binary.BigEndian, d)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeU8(w io.Writer, d uint8) (int64, error) {
|
||||||
|
return 1, binary.Write(w, binary.BigEndian, d)
|
||||||
|
}
|
||||||
|
func writeU16(w io.Writer, d uint16) (int64, error) {
|
||||||
|
return 2, binary.Write(w, binary.BigEndian, d)
|
||||||
|
}
|
||||||
|
func writeU32(w io.Writer, d uint32) (int64, error) {
|
||||||
|
return 4, binary.Write(w, binary.BigEndian, d)
|
||||||
|
}
|
||||||
|
func writeU64(w io.Writer, d uint64) (int64, error) {
|
||||||
|
return 8, binary.Write(w, binary.BigEndian, d)
|
||||||
|
}
|
||||||
|
|
||||||
|
func readByteN(r io.Reader, size int) (buff []byte, err error) {
|
||||||
|
buff = make([]byte, size)
|
||||||
|
for index := range buff {
|
||||||
|
if err = binary.Read(r, binary.BigEndian, &buff[index]); err != nil {
|
||||||
|
buff = buff[:index]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func writeBytes(w io.Writer, buff []byte) (n int64, err error) {
|
||||||
|
n = int64(len(buff))
|
||||||
|
err = binary.Write(w, binary.BigEndian, buff)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func addrWrite(w io.Writer, addr netip.Addr) (n int64, err error) {
|
||||||
|
if addr.Is6() {
|
||||||
|
if _, err = writeU8(w, 6); err != nil {
|
||||||
|
n = 0
|
||||||
|
return
|
||||||
|
} else if _, err = writeBytes(w, addr.AsSlice()); err != nil {
|
||||||
|
n = 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n = 17
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err = writeU8(w, 4); err != nil {
|
||||||
|
n = 0
|
||||||
|
return
|
||||||
|
} else if _, err = writeBytes(w, addr.AsSlice()); err != nil {
|
||||||
|
n = 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n = 5
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func addrRead(r io.Reader) (addr netip.Addr, n int64, err error) {
|
||||||
|
var buff []byte
|
||||||
|
n = 1
|
||||||
|
switch readU8(r) {
|
||||||
|
case 4:
|
||||||
|
buff, err = readByteN(r, 4)
|
||||||
|
n += int64(len(buff))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
addr = netip.AddrFrom4([4]byte(buff))
|
||||||
|
return
|
||||||
|
case 6:
|
||||||
|
buff, err = readByteN(r, 16)
|
||||||
|
n += int64(len(buff))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
netip.AddrFrom16([16]byte(buff))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = fmt.Errorf("connet get ip type")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func addrPortRead(r io.Reader) (netip.AddrPort, int64, error) {
|
||||||
|
switch readU8(r) {
|
||||||
|
case 4:
|
||||||
|
buff, err := readByteN(r, 4)
|
||||||
|
if err != nil {
|
||||||
|
return netip.AddrPort{}, int64(len(buff)), err
|
||||||
|
}
|
||||||
|
return netip.AddrPortFrom(netip.AddrFrom4([4]byte(buff)), readU16(r)), 6, nil
|
||||||
|
case 6:
|
||||||
|
buff, err := readByteN(r, 16)
|
||||||
|
if err != nil {
|
||||||
|
return netip.AddrPort{}, int64(len(buff)), err
|
||||||
|
}
|
||||||
|
return netip.AddrPortFrom(netip.AddrFrom16([16]byte(buff)), readU16(r)), 19, nil
|
||||||
|
}
|
||||||
|
return netip.AddrPort{}, 1, fmt.Errorf("connet get ip type")
|
||||||
|
}
|
||||||
|
func addrPortWrite(w io.Writer, addr netip.AddrPort) (n int64, err error) {
|
||||||
|
if !addr.IsValid() {
|
||||||
|
return 0, fmt.Errorf("invalid ip address")
|
||||||
|
} else if addr.Addr().Is6() {
|
||||||
|
if _, err = writeU8(w, 6); err != nil {
|
||||||
|
return 0, err
|
||||||
|
} else if err = binary.Write(w, binary.BigEndian, addr.Addr().AsSlice()); err != nil {
|
||||||
|
return 1, err
|
||||||
|
}
|
||||||
|
n = 18
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err = writeU8(w, 4); err != nil {
|
||||||
|
return 0, err
|
||||||
|
} else if err = binary.Write(w, binary.BigEndian, addr.Addr().AsSlice()); err != nil {
|
||||||
|
return 1, err
|
||||||
|
}
|
||||||
|
n = 5
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeOption(w io.Writer, d any, callback func(w io.Writer) (n int64, err error)) (n int64, err error) {
|
||||||
|
if d == nil {
|
||||||
|
return writeU8(w, 0)
|
||||||
|
}
|
||||||
|
n, err = writeU8(w, 1)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n2, err2 := callback(w)
|
||||||
|
return n + n2, err2
|
||||||
|
}
|
||||||
|
func readOption(r io.Reader, callback func(r io.Reader) (n int64, err error)) (n int64, err error) {
|
||||||
|
n = 1
|
||||||
|
switch readU8(r) {
|
||||||
|
case 0:
|
||||||
|
return 1, nil
|
||||||
|
case 1:
|
||||||
|
n2, err := callback(r)
|
||||||
|
return n + n2, err
|
||||||
|
}
|
||||||
|
return 1, fmt.Errorf("invalid Option value")
|
||||||
|
}
|
@ -1,141 +0,0 @@
|
|||||||
package tunnel
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"net/netip"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"sirherobrine23.org/playit-cloud/go-playit/api"
|
|
||||||
)
|
|
||||||
|
|
||||||
type AuthenticatedControl struct {
|
|
||||||
ApiClient api.Api
|
|
||||||
Conn ConnectedControl
|
|
||||||
CurrentPing *uint32
|
|
||||||
LastPong Pong
|
|
||||||
ForceEpired bool
|
|
||||||
Registered AgentRegistered
|
|
||||||
Buff []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Auth *AuthenticatedControl) Send(Req ControlRpcMessage[MessageEncoding]) error {
|
|
||||||
Auth.Buff = []byte{}
|
|
||||||
bufio := bytes.NewBuffer(Auth.Buff)
|
|
||||||
if err := Req.WriteTo(bufio); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
Auth.Buff = bufio.Bytes()
|
|
||||||
_, err := Auth.Conn.Udp.WriteToUDPAddrPort(Auth.Buff, Auth.Conn.ControlAddr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Auth *AuthenticatedControl) SendKeepAlive(RequestID uint64) error {
|
|
||||||
return Auth.Send(ControlRpcMessage[MessageEncoding]{
|
|
||||||
RequestID: RequestID,
|
|
||||||
Content: &ControlRequest{
|
|
||||||
AgentKeepAlive: &Auth.Registered.ID,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Auth *AuthenticatedControl) SendSetupUDPChannel(RequestID uint64) error {
|
|
||||||
return Auth.Send(ControlRpcMessage[MessageEncoding]{
|
|
||||||
RequestID: RequestID,
|
|
||||||
Content: &ControlRequest{
|
|
||||||
SetupUdpChannel: &Auth.Registered.ID,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Auth *AuthenticatedControl) SendPing(RequestID uint64, Now time.Time) error {
|
|
||||||
return Auth.Send(ControlRpcMessage[MessageEncoding]{
|
|
||||||
RequestID: RequestID,
|
|
||||||
Content: &ControlRequest{
|
|
||||||
Ping: &Ping{
|
|
||||||
Now: Now,
|
|
||||||
CurrentPing: Auth.CurrentPing,
|
|
||||||
SessionID: &Auth.Registered.ID,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Auth *AuthenticatedControl) FlowChanged() bool {
|
|
||||||
return Auth.LastPong.ClientAddr.Compare(Auth.LastPong.ClientAddr.AddrPort) != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Auth *AuthenticatedControl) IsIspired() bool {
|
|
||||||
return Auth.ForceEpired || Auth.LastPong.SessionExpireAt == nil || Auth.FlowChanged()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Auth *AuthenticatedControl) IntoRequiresAuth() *ConnectedControl {
|
|
||||||
return &ConnectedControl{
|
|
||||||
ControlAddr: Auth.Conn.ControlAddr,
|
|
||||||
Udp: Auth.Conn.Udp,
|
|
||||||
Pong: &Auth.LastPong,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type InvalidRemote struct {
|
|
||||||
Expected, Got netip.AddrPort
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a InvalidRemote) Error() string {
|
|
||||||
return fmt.Sprintf("expected %s, got %s", a.Expected.String(), a.Got.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Auth *AuthenticatedControl) RecFeedMsg() (*ControlFeed, error) {
|
|
||||||
Auth.Buff = append(Auth.Buff, make([]byte, 1024)...)
|
|
||||||
size, remote, err := Auth.Conn.Udp.ReadFromUDP(Auth.Buff)
|
|
||||||
LogDebug.Println(size, remote, err)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if remote.AddrPort().Compare(Auth.Conn.ControlAddr) != 0 {
|
|
||||||
return nil, InvalidRemote{Expected: Auth.Conn.ControlAddr, Got: remote.AddrPort()}
|
|
||||||
}
|
|
||||||
|
|
||||||
var feed ControlFeed
|
|
||||||
if err := feed.ReadFrom(bytes.NewBuffer(Auth.Buff[size:])); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if feed.Response != nil {
|
|
||||||
if feed.Response.Content != nil {
|
|
||||||
if feed.Response.Content.AgentRegistered != nil {
|
|
||||||
LogDebug.Println("agent registred")
|
|
||||||
LogDebug.Printf("%+v\n", feed.Response.Content.AgentRegistered)
|
|
||||||
Auth.Registered = *feed.Response.Content.AgentRegistered
|
|
||||||
} else if feed.Response.Content.Pong != nil {
|
|
||||||
CurrentPing := uint32(feed.Response.Content.Pong.RequestNow - uint64(time.Now().UnixMilli()))
|
|
||||||
Auth.CurrentPing = &CurrentPing
|
|
||||||
Auth.LastPong = *feed.Response.Content.Pong
|
|
||||||
if feed.Response.Content.Pong.SessionExpireAt != nil {
|
|
||||||
Auth.Registered.ExpiresAt = time.UnixMilli(int64(*feed.Response.Content.Pong.SessionExpireAt))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return &feed, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Auth *AuthenticatedControl) Authenticate() error {
|
|
||||||
conn, err := (&ConnectedControl{
|
|
||||||
ControlAddr: Auth.Conn.ControlAddr,
|
|
||||||
Udp: Auth.Conn.Udp,
|
|
||||||
Pong: &Auth.LastPong,
|
|
||||||
}).Authenticate(Auth.ApiClient)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
Auth.Buff = conn.Buff
|
|
||||||
Auth.Conn = conn.Conn
|
|
||||||
Auth.CurrentPing = conn.CurrentPing
|
|
||||||
Auth.LastPong = conn.LastPong
|
|
||||||
Auth.Registered = conn.Registered
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,110 +1,140 @@
|
|||||||
package tunnel
|
package tunnel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"net/netip"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ClaimInstructions struct {
|
var (
|
||||||
Address AddressPort
|
ErrFeedRead error = fmt.Errorf("invalid controlFeed id")
|
||||||
Token []byte
|
)
|
||||||
}
|
|
||||||
|
|
||||||
func (w *ClaimInstructions) WriteTo(I io.Writer) error {
|
|
||||||
if err := w.Address.WriteTo(I); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := WriteU64(I, uint64(len(w.Token))); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err = binary.Write(I, binary.BigEndian, w.Token); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (w *ClaimInstructions) ReadFrom(I io.Reader) error {
|
|
||||||
w.Address = AddressPort{}
|
|
||||||
if err := w.Address.ReadFrom(I); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.Token = make([]byte, ReadU64(I))
|
|
||||||
if err := ReadBuff(I, w.Token); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type NewClient struct {
|
|
||||||
ConnectAddr AddressPort
|
|
||||||
PeerAddr AddressPort
|
|
||||||
ClaimInstructions ClaimInstructions
|
|
||||||
TunnelServerId uint64
|
|
||||||
DataCenterId uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *NewClient) WriteTo(I io.Writer) error {
|
|
||||||
if err := w.ConnectAddr.WriteTo(I); err != nil {
|
|
||||||
return err
|
|
||||||
} else if w.PeerAddr.WriteTo(I); err != nil {
|
|
||||||
return err
|
|
||||||
} else if w.ClaimInstructions.WriteTo(I); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := WriteU64(I, w.TunnelServerId); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := WriteU32(I, w.DataCenterId); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (w *NewClient) ReadFrom(I io.Reader) error {
|
|
||||||
w.ConnectAddr, w.PeerAddr = AddressPort{}, AddressPort{}
|
|
||||||
if err := w.ConnectAddr.ReadFrom(I); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := w.PeerAddr.ReadFrom(I); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := w.ClaimInstructions.ReadFrom(I); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.TunnelServerId, w.DataCenterId = ReadU64(I), ReadU32(I)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type ControlFeed struct {
|
type ControlFeed struct {
|
||||||
Response *ControlRpcMessage[*ControlResponse]
|
Response *ControlRpcMessage[*ControlResponse]
|
||||||
NewClient *NewClient
|
NewClient *NewClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *ControlFeed) WriteTo(I io.Writer) error {
|
func (Feed *ControlFeed) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
defer func(){
|
id := readU32(r)
|
||||||
d, _ := json.MarshalIndent(w, "", " ")
|
if id == 1 {
|
||||||
LogDebug.Printf("Write Feed: %s\n", string(d))
|
Feed.Response = new(ControlRpcMessage[*ControlResponse])
|
||||||
}()
|
Feed.Response.Content = new(ControlResponse)
|
||||||
if w.Response != nil {
|
n, err = Feed.Response.ReadFrom(r)
|
||||||
if err := WriteU32(I, 1); err != nil {
|
n += 4
|
||||||
return err
|
return
|
||||||
}
|
} else if id == 2 {
|
||||||
return w.Response.WriteTo(I)
|
Feed.NewClient = &NewClient{}
|
||||||
} else if w.NewClient != nil {
|
n, err = Feed.NewClient.ReadFrom(r)
|
||||||
if err := WriteU32(I, 2); err != nil {
|
n += 4
|
||||||
return err
|
return
|
||||||
}
|
|
||||||
return w.NewClient.WriteTo(I)
|
|
||||||
}
|
}
|
||||||
return fmt.Errorf("set ResponseControl or NewClient")
|
return 4, ErrFeedRead
|
||||||
}
|
}
|
||||||
func (w *ControlFeed) ReadFrom(I io.Reader) error {
|
func (Feed *ControlFeed) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
defer func(){
|
if Feed.Response != nil {
|
||||||
d, _ := json.MarshalIndent(w, "", " ")
|
if err := writeU32(w, 1); err != nil {
|
||||||
LogDebug.Printf("Read Feed: %s\n", string(d))
|
return 0, err
|
||||||
}()
|
}
|
||||||
switch ReadU32(I) {
|
n, err = Feed.Response.WriteTo(w)
|
||||||
case 1:
|
n += 4
|
||||||
w.Response = &ControlRpcMessage[*ControlResponse]{}
|
return
|
||||||
w.Response.Content = &ControlResponse{}
|
} else if Feed.NewClient != nil {
|
||||||
return w.Response.ReadFrom(I)
|
if err := writeU32(w, 2); err != nil {
|
||||||
case 2:
|
return 0, err
|
||||||
w.NewClient = &NewClient{}
|
}
|
||||||
return w.NewClient.ReadFrom(I)
|
n, err = Feed.NewClient.WriteTo(w)
|
||||||
|
n += 4
|
||||||
|
return
|
||||||
}
|
}
|
||||||
return fmt.Errorf("invalid ControlFeed id")
|
return 0, fmt.Errorf("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NewClient struct {
|
||||||
|
ConnectAddr netip.AddrPort
|
||||||
|
PeerAddr netip.AddrPort
|
||||||
|
ClaimInstructions ClaimInstructions
|
||||||
|
TunnelServerId uint64
|
||||||
|
DataCenterId uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *NewClient) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
|
client.ConnectAddr, n, err = addrPortRead(r)
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
n2 := n
|
||||||
|
client.PeerAddr, n, err = addrPortRead(r)
|
||||||
|
if err != nil {
|
||||||
|
return n2 + n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
n3 := n2 + n
|
||||||
|
n, err = client.ClaimInstructions.ReadFrom(r);
|
||||||
|
if err != nil {
|
||||||
|
return n3 + n, err
|
||||||
|
}
|
||||||
|
n+=n3 + 8 + 4
|
||||||
|
client.TunnelServerId, client.DataCenterId = readU64(r), readU32(r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (client *NewClient) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
|
n, err = addrPortWrite(w, client.ConnectAddr)
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
n2 := n
|
||||||
|
n, err = addrPortWrite(w, client.PeerAddr)
|
||||||
|
if err != nil {
|
||||||
|
return n+n2, err
|
||||||
|
}
|
||||||
|
n3:= n+n2
|
||||||
|
if n, err = client.ClaimInstructions.WriteTo(w); err != nil {
|
||||||
|
return n + n3, err
|
||||||
|
}
|
||||||
|
|
||||||
|
n4 := n + n3
|
||||||
|
if err = writeU64(w, client.TunnelServerId); err != nil {
|
||||||
|
return n4, err
|
||||||
|
}
|
||||||
|
n4 += 8
|
||||||
|
if err = writeU32(w, client.DataCenterId); err != nil {
|
||||||
|
return n4, err
|
||||||
|
}
|
||||||
|
n = n4+8
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type ClaimInstructions struct {
|
||||||
|
Address netip.AddrPort
|
||||||
|
Token []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (claim *ClaimInstructions) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
|
claim.Address, n, err = addrPortRead(r)
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
claim.Token, err = readByteN(r, int(readU64(r)))
|
||||||
|
n += int64(len(claim.Token)) + 8
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (claim *ClaimInstructions) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
|
n, err = addrPortWrite(w, claim.Address)
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = writeU64(w, uint64(len(claim.Token))); err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
n2 := 8 + n
|
||||||
|
n, err = writeBytes(w, claim.Token)
|
||||||
|
if err != nil {
|
||||||
|
return n2, err
|
||||||
|
}
|
||||||
|
n = n2 + n
|
||||||
|
return
|
||||||
|
}
|
@ -1,411 +0,0 @@
|
|||||||
package tunnel
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Ping struct {
|
|
||||||
Now time.Time
|
|
||||||
CurrentPing *uint32
|
|
||||||
SessionID *AgentSessionId
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Ping) WriteTo(I io.Writer) error {
|
|
||||||
if err := WriteU64(I, uint64(w.Now.UnixMilli())); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if w.CurrentPing == nil {
|
|
||||||
if err := binary.Write(I, binary.BigEndian, uint8(0)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err := binary.Write(I, binary.BigEndian, uint8(1)); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := binary.Write(I, binary.BigEndian, w.CurrentPing); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if w.SessionID == nil {
|
|
||||||
return binary.Write(I, binary.BigEndian, uint8(0))
|
|
||||||
} else if err := binary.Write(I, binary.BigEndian, uint8(1)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return w.SessionID.WriteTo(I)
|
|
||||||
}
|
|
||||||
func (w *Ping) ReadFrom(I io.Reader) error {
|
|
||||||
w.Now = time.UnixMilli(int64(ReadU64(I)))
|
|
||||||
|
|
||||||
CurrentPing := ReadU32(I)
|
|
||||||
w.CurrentPing = &CurrentPing
|
|
||||||
|
|
||||||
w.SessionID = &AgentSessionId{}
|
|
||||||
w.SessionID.ReadFrom(I)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type Pong struct {
|
|
||||||
RequestNow uint64
|
|
||||||
ServerNow uint64
|
|
||||||
ServerId uint64
|
|
||||||
DataCenterId uint32
|
|
||||||
ClientAddr AddressPort
|
|
||||||
TunnelAddr AddressPort
|
|
||||||
SessionExpireAt *uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Pong) WriteTo(I io.Writer) error {
|
|
||||||
if err := WriteU64(I, w.RequestNow); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := WriteU64(I, w.ServerNow); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := WriteU64(I, w.ServerId); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := WriteU32(I, w.DataCenterId); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := w.ClientAddr.WriteTo(I); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := w.TunnelAddr.WriteTo(I); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := WriteOptionU64(I, w.SessionExpireAt); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (w *Pong) ReadFrom(I io.Reader) error {
|
|
||||||
w.RequestNow, w.ServerNow, w.ServerId = ReadU64(I), ReadU64(I), ReadU64(I)
|
|
||||||
w.DataCenterId = ReadU32(I)
|
|
||||||
w.ClientAddr = AddressPort{}
|
|
||||||
w.TunnelAddr = AddressPort{}
|
|
||||||
|
|
||||||
if err := w.ClientAddr.ReadFrom(I); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := w.TunnelAddr.ReadFrom(I); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
Sess := ReadU64(I)
|
|
||||||
w.SessionExpireAt = &Sess
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type AgentRegister struct {
|
|
||||||
AccountID, AgentId, AgentVersion, Timestamp uint64
|
|
||||||
ClientAddr, TunnelAddr AddressPort
|
|
||||||
Signature []byte // 32 bytes
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *AgentRegister) WritePlain(buff io.Writer) error {
|
|
||||||
if err := WriteU64(buff, w.AccountID); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := WriteU64(buff, w.AgentId); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := WriteU64(buff, w.AgentVersion); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := WriteU64(buff, w.Timestamp); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := w.ClientAddr.WriteTo(buff); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := w.TunnelAddr.WriteTo(buff); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (w *AgentRegister) WriteTo(I io.Writer) error {
|
|
||||||
if err := WriteU64(I, w.AccountID); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := WriteU64(I, w.AgentId); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := WriteU64(I, w.AgentVersion); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := WriteU64(I, w.Timestamp); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := w.ClientAddr.WriteTo(I); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := w.TunnelAddr.WriteTo(I); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := binary.Write(I, binary.BigEndian, w.Signature); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (w *AgentRegister) ReadFrom(I io.Reader) error {
|
|
||||||
w.AccountID = ReadU64(I)
|
|
||||||
w.AgentId = ReadU64(I)
|
|
||||||
w.AgentVersion = ReadU64(I)
|
|
||||||
w.Timestamp = ReadU64(I)
|
|
||||||
w.ClientAddr, w.TunnelAddr = AddressPort{}, AddressPort{}
|
|
||||||
if err := w.ClientAddr.ReadFrom(I); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := w.TunnelAddr.ReadFrom(I); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.Signature = make([]byte, 32)
|
|
||||||
if err := ReadBuff(I, w.Signature); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type AgentCheckPortMapping struct {
|
|
||||||
AgentSessionId AgentSessionId
|
|
||||||
PortRange PortRange
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *AgentCheckPortMapping) WriteTo(I io.Writer) error {
|
|
||||||
if err := w.AgentSessionId.WriteTo(I); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := w.PortRange.WriteTo(I); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (w *AgentCheckPortMapping) ReadFrom(I io.Reader) error {
|
|
||||||
w.AgentSessionId, w.PortRange = AgentSessionId{}, PortRange{}
|
|
||||||
if err := w.AgentSessionId.ReadFrom(I); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := w.PortRange.ReadFrom(I); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type ControlRequest struct {
|
|
||||||
Ping *Ping
|
|
||||||
AgentRegister *AgentRegister
|
|
||||||
AgentKeepAlive *AgentSessionId
|
|
||||||
SetupUdpChannel *AgentSessionId
|
|
||||||
AgentCheckPortMapping *AgentCheckPortMapping
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *ControlRequest) WriteTo(I io.Writer) error {
|
|
||||||
if w.Ping != nil {
|
|
||||||
if err := WriteU32(I, uint32(6)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return w.Ping.WriteTo(I)
|
|
||||||
} else if w.AgentRegister != nil {
|
|
||||||
if err := WriteU32(I, uint32(2)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return w.AgentRegister.WriteTo(I)
|
|
||||||
} else if w.AgentKeepAlive != nil {
|
|
||||||
if err := WriteU32(I, uint32(3)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return w.AgentKeepAlive.WriteTo(I)
|
|
||||||
} else if w.SetupUdpChannel != nil {
|
|
||||||
if err := WriteU32(I, uint32(4)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return w.SetupUdpChannel.WriteTo(I)
|
|
||||||
} else if w.AgentCheckPortMapping != nil {
|
|
||||||
if err := WriteU32(I, uint32(5)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return w.AgentCheckPortMapping.WriteTo(I)
|
|
||||||
}
|
|
||||||
return fmt.Errorf("set ControlRequest")
|
|
||||||
}
|
|
||||||
func (w *ControlRequest) ReadFrom(I io.Reader) error {
|
|
||||||
switch ReadU32(I) {
|
|
||||||
case 1:
|
|
||||||
w.Ping = &Ping{}
|
|
||||||
return w.Ping.ReadFrom(I)
|
|
||||||
case 2:
|
|
||||||
w.AgentRegister = &AgentRegister{}
|
|
||||||
return w.AgentRegister.ReadFrom(I)
|
|
||||||
case 3:
|
|
||||||
w.AgentKeepAlive = &AgentSessionId{}
|
|
||||||
return w.AgentKeepAlive.ReadFrom(I)
|
|
||||||
case 4:
|
|
||||||
w.SetupUdpChannel = &AgentSessionId{}
|
|
||||||
return w.SetupUdpChannel.ReadFrom(I)
|
|
||||||
case 5:
|
|
||||||
w.AgentCheckPortMapping = &AgentCheckPortMapping{}
|
|
||||||
return w.AgentCheckPortMapping.ReadFrom(I)
|
|
||||||
}
|
|
||||||
return fmt.Errorf("invalid ControlRequest id")
|
|
||||||
}
|
|
||||||
|
|
||||||
type AgentRegistered struct {
|
|
||||||
ID AgentSessionId
|
|
||||||
ExpiresAt time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *AgentRegistered) WriteTo(I io.Writer) error {
|
|
||||||
if err := w.ID.WriteTo(I); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := WriteU64(I, uint64(w.ExpiresAt.UnixMilli())); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (w *AgentRegistered) ReadFrom(I io.Reader) error {
|
|
||||||
w.ID = AgentSessionId{}
|
|
||||||
if err := w.ID.ReadFrom(I); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.ExpiresAt = time.UnixMilli(int64(ReadU64(I)))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type AgentPortMappingFound struct {
|
|
||||||
ToAgent *AgentSessionId
|
|
||||||
}
|
|
||||||
|
|
||||||
func (agentPort *AgentPortMappingFound) WriteTo(I io.Writer) error {
|
|
||||||
if agentPort.ToAgent != nil {
|
|
||||||
if err := WriteU32(I, 1); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := agentPort.ToAgent.WriteTo(I); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (agentPort *AgentPortMappingFound) ReadFrom(I io.Reader) error {
|
|
||||||
if ReadU32(I) == 1 {
|
|
||||||
agentPort.ToAgent = &AgentSessionId{}
|
|
||||||
return agentPort.ToAgent.ReadFrom(I)
|
|
||||||
}
|
|
||||||
return fmt.Errorf("unknown AgentPortMappingFound id")
|
|
||||||
}
|
|
||||||
|
|
||||||
type AgentPortMapping struct {
|
|
||||||
Range PortRange
|
|
||||||
Found *AgentPortMappingFound
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *AgentPortMapping) WriteTo(I io.Writer) error {
|
|
||||||
if err := w.Range.WriteTo(I); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := w.Found.WriteTo(I); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (w *AgentPortMapping) ReadFrom(I io.Reader) error {
|
|
||||||
if err := w.Range.ReadFrom(I); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := w.Found.ReadFrom(I); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type UdpChannelDetails struct {
|
|
||||||
TunnelAddr AddressPort
|
|
||||||
Token []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *UdpChannelDetails) WriteTo(I io.Writer) error {
|
|
||||||
if err := w.TunnelAddr.WriteTo(I); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := WriteU64(I, uint64(len(w.Token))); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := binary.Write(I, binary.BigEndian, w.Token); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (w *UdpChannelDetails) ReadFrom(I io.Reader) error {
|
|
||||||
w.TunnelAddr = AddressPort{}
|
|
||||||
if err := w.TunnelAddr.ReadFrom(I); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.Token = make([]byte, ReadU64(I))
|
|
||||||
if err := ReadBuff(I, w.Token); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type ControlResponse struct {
|
|
||||||
InvalidSignature bool
|
|
||||||
Unauthorized bool
|
|
||||||
RequestQueued bool
|
|
||||||
TryAgainLater bool
|
|
||||||
Pong *Pong
|
|
||||||
AgentRegistered *AgentRegistered
|
|
||||||
AgentPortMapping *AgentPortMapping
|
|
||||||
UdpChannelDetails *UdpChannelDetails
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *ControlResponse) WriteTo(I io.Writer) error {
|
|
||||||
if w.Pong != nil {
|
|
||||||
if err := WriteU32(I, 1); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return w.Pong.WriteTo(I)
|
|
||||||
} else if w.InvalidSignature {
|
|
||||||
if err := WriteU32(I, 2); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
} else if w.Unauthorized {
|
|
||||||
if err := WriteU32(I, 3); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
} else if w.RequestQueued {
|
|
||||||
if err := WriteU32(I, 4); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
} else if w.TryAgainLater {
|
|
||||||
if err := WriteU32(I, 5); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
} else if w.AgentRegistered != nil {
|
|
||||||
if err := WriteU32(I, 6); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return w.AgentRegistered.WriteTo(I)
|
|
||||||
} else if w.AgentPortMapping != nil {
|
|
||||||
if err := WriteU32(I, 7); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return w.AgentPortMapping.WriteTo(I)
|
|
||||||
} else if w.UdpChannelDetails != nil {
|
|
||||||
if err := WriteU32(I, 8); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return w.UdpChannelDetails.WriteTo(I)
|
|
||||||
}
|
|
||||||
return fmt.Errorf("set one option to write")
|
|
||||||
}
|
|
||||||
func (w *ControlResponse) ReadFrom(I io.Reader) error {
|
|
||||||
switch ReadU32(I) {
|
|
||||||
case 1:
|
|
||||||
w.Pong = &Pong{}
|
|
||||||
return w.Pong.ReadFrom(I)
|
|
||||||
case 2:
|
|
||||||
w.InvalidSignature = true
|
|
||||||
return nil
|
|
||||||
case 3:
|
|
||||||
w.Unauthorized = true
|
|
||||||
return nil
|
|
||||||
case 4:
|
|
||||||
w.RequestQueued = true
|
|
||||||
return nil
|
|
||||||
case 5:
|
|
||||||
w.TryAgainLater = true
|
|
||||||
return nil
|
|
||||||
case 6:
|
|
||||||
w.AgentRegistered = &AgentRegistered{}
|
|
||||||
return w.AgentRegistered.ReadFrom(I)
|
|
||||||
case 7:
|
|
||||||
w.AgentPortMapping = &AgentPortMapping{}
|
|
||||||
return w.AgentPortMapping.ReadFrom(I)
|
|
||||||
case 8:
|
|
||||||
w.UdpChannelDetails = &UdpChannelDetails{}
|
|
||||||
return w.UdpChannelDetails.ReadFrom(I)
|
|
||||||
}
|
|
||||||
return fmt.Errorf("invalid ControlResponse id")
|
|
||||||
}
|
|
394
tunnel/control_messages.go
Normal file
394
tunnel/control_messages.go
Normal file
@ -0,0 +1,394 @@
|
|||||||
|
package tunnel
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/netip"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ControlRequest struct {
|
||||||
|
Ping *Ping
|
||||||
|
AgentRegister *AgentRegister
|
||||||
|
AgentKeepAlive *AgentSessionId
|
||||||
|
SetupUdpChannel *AgentSessionId
|
||||||
|
AgentCheckPortMapping *AgentCheckPortMapping
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Control *ControlRequest) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
|
if Control.Ping != nil {
|
||||||
|
n, err = writeU32(w, 6)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n2 := n
|
||||||
|
n, err = Control.Ping.WriteTo(w)
|
||||||
|
if err != nil {
|
||||||
|
return n2, err
|
||||||
|
}
|
||||||
|
n += n2
|
||||||
|
return
|
||||||
|
} else if Control.AgentRegister != nil {
|
||||||
|
n, err = writeU32(w, 2)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n2 := n
|
||||||
|
n, err = Control.AgentRegister.WriteTo(w)
|
||||||
|
if err != nil {
|
||||||
|
return n2, err
|
||||||
|
}
|
||||||
|
n += n2
|
||||||
|
return
|
||||||
|
} else if Control.AgentKeepAlive != nil {
|
||||||
|
n, err = writeU32(w, 3)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n2 := n
|
||||||
|
n, err = Control.AgentKeepAlive.WriteTo(w)
|
||||||
|
if err != nil {
|
||||||
|
return n2, err
|
||||||
|
}
|
||||||
|
n += n2
|
||||||
|
return
|
||||||
|
} else if Control.SetupUdpChannel != nil {
|
||||||
|
n, err = writeU32(w, 4)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n2 := n
|
||||||
|
n, err = Control.SetupUdpChannel.WriteTo(w)
|
||||||
|
if err != nil {
|
||||||
|
return n2, err
|
||||||
|
}
|
||||||
|
n += n2
|
||||||
|
return
|
||||||
|
} else if Control.AgentCheckPortMapping != nil {
|
||||||
|
n, err = writeU32(w, 5)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n2 := n
|
||||||
|
n, err = Control.AgentCheckPortMapping.WriteTo(w)
|
||||||
|
if err != nil {
|
||||||
|
return n2, err
|
||||||
|
}
|
||||||
|
n += n2
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = fmt.Errorf("set ControlRequest")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (Control *ControlRequest) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
|
n = 1
|
||||||
|
switch readU32(r) {
|
||||||
|
case 1:
|
||||||
|
Control.Ping = new(Ping)
|
||||||
|
np, err := Control.Ping.ReadFrom(r)
|
||||||
|
return np + n, err
|
||||||
|
case 2:
|
||||||
|
Control.AgentRegister = new(AgentRegister)
|
||||||
|
np, err := Control.AgentRegister.ReadFrom(r)
|
||||||
|
return np + n, err
|
||||||
|
case 3:
|
||||||
|
Control.AgentKeepAlive = new(AgentSessionId)
|
||||||
|
np, err := Control.AgentKeepAlive.ReadFrom(r)
|
||||||
|
return np + n, err
|
||||||
|
case 4:
|
||||||
|
Control.SetupUdpChannel = new(AgentSessionId)
|
||||||
|
np, err := Control.SetupUdpChannel.ReadFrom(r)
|
||||||
|
return np + n, err
|
||||||
|
case 5:
|
||||||
|
Control.AgentCheckPortMapping = new(AgentCheckPortMapping)
|
||||||
|
np, err := Control.AgentCheckPortMapping.ReadFrom(r)
|
||||||
|
return np + n, err
|
||||||
|
}
|
||||||
|
err = fmt.Errorf("invalid ControlRequest id")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type AgentCheckPortMapping struct {
|
||||||
|
AgentSessionId AgentSessionId
|
||||||
|
PortRange PortRange
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Agent *AgentCheckPortMapping) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
|
n, err = Agent.AgentSessionId.WriteTo(w)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n2 := n
|
||||||
|
n, err = Agent.PortRange.WriteTo(w)
|
||||||
|
return n + n2, err
|
||||||
|
}
|
||||||
|
func (Agent *AgentCheckPortMapping) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
|
n, err = Agent.AgentSessionId.ReadFrom(r)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n2 := n
|
||||||
|
n, err = Agent.AgentSessionId.ReadFrom(r)
|
||||||
|
return n + n2, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type Ping struct {
|
||||||
|
Now time.Time
|
||||||
|
CurrentPing *time.Time
|
||||||
|
SessionId *AgentSessionId
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ping *Ping) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
|
n, err = writeU64(w, uint64(ping.Now.UnixMilli()))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n2 := n
|
||||||
|
if n, err = writeOption(w, ping.CurrentPing, func(w io.Writer) (int64, error) {
|
||||||
|
return writeU64(w, uint64(ping.CurrentPing.UnixMilli()))
|
||||||
|
}); err != nil {
|
||||||
|
n = n2
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n += n2
|
||||||
|
if n, err = writeOption(w, ping.SessionId, ping.SessionId.WriteTo); err != nil {
|
||||||
|
n = n2
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (ping *Ping) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
|
ping.Now = time.UnixMilli(int64(readU64(r)))
|
||||||
|
n, err = readOption(r, func(r io.Reader) (n int64, err error) {
|
||||||
|
ping.CurrentPing = new(time.Time)
|
||||||
|
d, _ := time.UnixMilli(int64(readU64(r))).MarshalBinary()
|
||||||
|
ping.CurrentPing.UnmarshalBinary(d)
|
||||||
|
return 8, nil
|
||||||
|
})
|
||||||
|
n += 8
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n, err = readOption(r, func(r io.Reader) (n int64, err error) {
|
||||||
|
return ping.SessionId.ReadFrom(r)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type AgentRegister struct {
|
||||||
|
AccountID, AgentId, AgentVersion, Timestamp uint64
|
||||||
|
ClientAddr, TunnelAddr netip.AddrPort
|
||||||
|
Signature [32]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (agent *AgentRegister) writePlain() *bytes.Buffer {
|
||||||
|
buff := new(bytes.Buffer)
|
||||||
|
writeU64(buff, agent.AccountID)
|
||||||
|
writeU64(buff, agent.AgentId)
|
||||||
|
writeU64(buff, agent.AgentVersion)
|
||||||
|
writeU64(buff, agent.Timestamp)
|
||||||
|
addrPortWrite(buff, agent.ClientAddr)
|
||||||
|
addrPortWrite(buff, agent.TunnelAddr)
|
||||||
|
return buff
|
||||||
|
}
|
||||||
|
func (agent *AgentRegister) UpdateSignature(hmac HmacSha256) {
|
||||||
|
agent.Signature = hmac.Sign(agent.writePlain().Bytes())
|
||||||
|
}
|
||||||
|
func (agent *AgentRegister) VerifySignature(hmac HmacSha256) bool {
|
||||||
|
return hmac.Verify(agent.writePlain().Bytes(), agent.Signature[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (AgentReg *AgentRegister) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
|
if _, err := writeU64(w, AgentReg.AccountID); err != nil {
|
||||||
|
return 0, err
|
||||||
|
} else if _, err := writeU64(w, AgentReg.AgentId); err != nil {
|
||||||
|
return 0, err
|
||||||
|
} else if _, err := writeU64(w, AgentReg.AgentVersion); err != nil {
|
||||||
|
return 0, err
|
||||||
|
} else if _, err := writeU64(w, AgentReg.Timestamp); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
n = 8 * 4
|
||||||
|
if n2, err := addrPortWrite(w, AgentReg.ClientAddr); err != nil {
|
||||||
|
return n, err
|
||||||
|
} else if n3, err := addrPortWrite(w, AgentReg.TunnelAddr); err != nil {
|
||||||
|
return n + n2, err
|
||||||
|
} else {
|
||||||
|
n += n3
|
||||||
|
}
|
||||||
|
if n4, err := w.Write(AgentReg.Signature[:]); err != nil {
|
||||||
|
return n, err
|
||||||
|
} else {
|
||||||
|
n += int64(n4)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (AgentReg *AgentRegister) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
|
AgentReg.AccountID, AgentReg.AccountID, AgentReg.AgentVersion, AgentReg.Timestamp = readU64(r), readU64(r), readU64(r), readU64(r)
|
||||||
|
if AgentReg.ClientAddr, n, err = addrPortRead(r); err != nil {
|
||||||
|
return
|
||||||
|
} else if AgentReg.TunnelAddr, n, err = addrPortRead(r); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
AgentReg.Signature = [32]byte(make([]byte, 32))
|
||||||
|
if n2, _ := r.Read(AgentReg.Signature[:]); n != 32 {
|
||||||
|
return int64(n2), fmt.Errorf("missing signature")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type ControlResponse struct {
|
||||||
|
InvalidSignature, Unauthorized, RequestQueued, TryAgainLater bool
|
||||||
|
Pong *Pong
|
||||||
|
AgentRegistered *AgentRegistered
|
||||||
|
AgentPortMapping *AgentPortMapping
|
||||||
|
UdpChannelDetails *UdpChannelDetails
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Control *ControlResponse) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
|
defer func() {
|
||||||
|
if err == nil {
|
||||||
|
n += 4
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if Control.Pong != nil {
|
||||||
|
writeU32(w, 1)
|
||||||
|
n, err = Control.Pong.WriteTo(w)
|
||||||
|
return
|
||||||
|
} else if Control.InvalidSignature {
|
||||||
|
return writeU32(w, 2)
|
||||||
|
} else if Control.Unauthorized {
|
||||||
|
return writeU32(w, 3)
|
||||||
|
} else if Control.RequestQueued {
|
||||||
|
return writeU32(w, 4)
|
||||||
|
} else if Control.TryAgainLater {
|
||||||
|
return writeU32(w, 5)
|
||||||
|
} else if Control.AgentRegistered != nil {
|
||||||
|
writeU32(w, 6)
|
||||||
|
return Control.AgentRegistered.WriteTo(w)
|
||||||
|
} else if Control.AgentPortMapping != nil {
|
||||||
|
writeU32(w, 7)
|
||||||
|
return Control.AgentPortMapping.WriteTo(w)
|
||||||
|
} else if Control.UdpChannelDetails != nil {
|
||||||
|
writeU32(w, 8)
|
||||||
|
return Control.UdpChannelDetails.WriteTo(w)
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf("insert any options to write")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (Control *ControlResponse) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
|
defer func() {
|
||||||
|
if err == nil {
|
||||||
|
n += 4
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
switch readU32(r) {
|
||||||
|
case 1:
|
||||||
|
Control.Pong = &Pong{}
|
||||||
|
return Control.Pong.ReadFrom(r)
|
||||||
|
case 2:
|
||||||
|
Control.InvalidSignature = true
|
||||||
|
return
|
||||||
|
case 3:
|
||||||
|
Control.Unauthorized = true
|
||||||
|
return
|
||||||
|
case 4:
|
||||||
|
Control.RequestQueued = true
|
||||||
|
return
|
||||||
|
case 5:
|
||||||
|
Control.TryAgainLater = true
|
||||||
|
return
|
||||||
|
case 6:
|
||||||
|
Control.AgentRegistered = &AgentRegistered{}
|
||||||
|
return Control.AgentRegistered.ReadFrom(r)
|
||||||
|
case 7:
|
||||||
|
Control.AgentPortMapping = &AgentPortMapping{}
|
||||||
|
return Control.AgentPortMapping.ReadFrom(r)
|
||||||
|
case 8:
|
||||||
|
Control.UdpChannelDetails = &UdpChannelDetails{}
|
||||||
|
return Control.UdpChannelDetails.ReadFrom(r)
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("invalid ControlResponse id")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type AgentPortMapping struct {
|
||||||
|
Range PortRange
|
||||||
|
Found *AgentPortMappingFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Agent *AgentPortMapping) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
|
Agent.Range.WriteTo(w)
|
||||||
|
Agent.Found.WriteTo(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (Agent *AgentPortMapping) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
|
Agent.Range.ReadFrom(r)
|
||||||
|
Agent.Found.ReadFrom(r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type AgentPortMappingFound struct {
|
||||||
|
ToAgent *AgentSessionId
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Agent *AgentPortMappingFound) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
|
if Agent.ToAgent != nil {
|
||||||
|
writeU32(w, 1)
|
||||||
|
Agent.ToAgent.WriteTo(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (Agent *AgentPortMappingFound) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
|
if readU32(r) == 1 {
|
||||||
|
defer func() { n += 4 }()
|
||||||
|
Agent.ToAgent = new(AgentSessionId)
|
||||||
|
return Agent.ToAgent.ReadFrom(r)
|
||||||
|
}
|
||||||
|
return 4, fmt.Errorf("unknown AgentPortMappingFound id")
|
||||||
|
}
|
||||||
|
|
||||||
|
type UdpChannelDetails struct {
|
||||||
|
TunnelAddr netip.AddrPort
|
||||||
|
Token []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UdpChannel *UdpChannelDetails) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
|
addrPortWrite(w, UdpChannel.TunnelAddr)
|
||||||
|
writeU64(w, uint64(len(UdpChannel.Token)))
|
||||||
|
writeBytes(w, UdpChannel.Token)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (UdpChannel *UdpChannelDetails) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
|
UdpChannel.TunnelAddr, _, _ = addrPortRead(r)
|
||||||
|
UdpChannel.Token, _ = readByteN(r, int(readU64(r)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type Pong struct {
|
||||||
|
RequestNow, ServerNow time.Time
|
||||||
|
ServerId uint64
|
||||||
|
DataCenterId uint32
|
||||||
|
ClientAddr, TunnelAddr netip.AddrPort
|
||||||
|
SessionExpireAt *time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pong *Pong) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
func (pong *Pong) ReadFrom(r io.Reader) (n int64, err error) {}
|
||||||
|
|
||||||
|
type AgentRegistered struct {
|
||||||
|
Id AgentSessionId
|
||||||
|
ExpiresAt time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func (agent *AgentRegistered) WriteTo(w io.Writer) (n int64, err error) {}
|
||||||
|
func (agent *AgentRegistered) ReadFrom(r io.Reader) (n int64, err error) {}
|
29
tunnel/hmacsha256.go
Normal file
29
tunnel/hmacsha256.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package tunnel
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/hmac"
|
||||||
|
"crypto/sha256"
|
||||||
|
"hash"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HmacSha256 struct {
|
||||||
|
mac hash.Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHmacSha256(secret []byte) *HmacSha256 {
|
||||||
|
mac := hmac.New(sha256.New, secret)
|
||||||
|
return &HmacSha256{mac}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HmacSha256) Verify(data, sig []byte) bool {
|
||||||
|
expectedMAC := h.mac.Sum(nil)
|
||||||
|
h.mac.Reset()
|
||||||
|
h.mac.Write(data)
|
||||||
|
return hmac.Equal(expectedMAC, sig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HmacSha256) Sign(data []byte) [32]byte {
|
||||||
|
h.mac.Reset()
|
||||||
|
h.mac.Write(data)
|
||||||
|
return [32]byte(h.mac.Sum(nil))
|
||||||
|
}
|
@ -47,15 +47,15 @@ func TcpSocket(SpecialLan bool, Peer, Host netip.AddrPort) (*net.TCPConn, error)
|
|||||||
local_ip := mapToLocalIP4(Peer.Addr().AsSlice());
|
local_ip := mapToLocalIP4(Peer.Addr().AsSlice());
|
||||||
stream, err := net.DialTCP("tcp4", net.TCPAddrFromAddrPort(netip.AddrPortFrom(netip.AddrFrom4([4]byte(local_ip.To4())), 0)), net.TCPAddrFromAddrPort(Host))
|
stream, err := net.DialTCP("tcp4", net.TCPAddrFromAddrPort(netip.AddrPortFrom(netip.AddrFrom4([4]byte(local_ip.To4())), 0)), net.TCPAddrFromAddrPort(Host))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
LogDebug.Printf("Failed to establish connection using special lan %s for flow %s -> %s\n", local_ip, Peer.String(), Host.String())
|
logDebug.Printf("Failed to establish connection using special lan %s for flow %s -> %s\n", local_ip, Peer.String(), Host.String())
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return stream, nil
|
return stream, nil
|
||||||
}
|
}
|
||||||
LogDebug.Printf("Failed to bind connection to special local address to support IP based banning")
|
logDebug.Printf("Failed to bind connection to special local address to support IP based banning")
|
||||||
stream, err := net.DialTCP("tcp", nil, net.TCPAddrFromAddrPort(Host))
|
stream, err := net.DialTCP("tcp", nil, net.TCPAddrFromAddrPort(Host))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
LogDebug.Printf("Failed to establish connection for flow %s -> %s. Is your server running? %q", Peer.String(), Host.String(), err.Error())
|
logDebug.Printf("Failed to establish connection for flow %s -> %s. Is your server running? %q", Peer.String(), Host.String(), err.Error())
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return stream, nil
|
return stream, nil
|
||||||
@ -68,14 +68,15 @@ func UdpSocket(SpecialLan bool, Peer, Host netip.AddrPort) (*net.UDPConn, error)
|
|||||||
local_port := 40000 + (Peer.Port() % 24000);
|
local_port := 40000 + (Peer.Port() % 24000);
|
||||||
stream, err := net.DialUDP("udp4", net.UDPAddrFromAddrPort(netip.AddrPortFrom(netip.AddrFrom16([16]byte(local_ip)), local_port)), net.UDPAddrFromAddrPort(Host))
|
stream, err := net.DialUDP("udp4", net.UDPAddrFromAddrPort(netip.AddrPortFrom(netip.AddrFrom16([16]byte(local_ip)), local_port)), net.UDPAddrFromAddrPort(Host))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
LogDebug.Printf("Failed to bind UDP port to %d to have connections survive agent restart: %s", local_port, err.Error())
|
logDebug.Printf("Failed to bind UDP port to %d to have connections survive agent restart: %s", local_port, err.Error())
|
||||||
stream, err = net.DialUDP("udp4", net.UDPAddrFromAddrPort(netip.AddrPortFrom(netip.AddrFrom16([16]byte(local_ip)), 0)), net.UDPAddrFromAddrPort(Host))
|
stream, err = net.DialUDP("udp4", net.UDPAddrFromAddrPort(netip.AddrPortFrom(netip.AddrFrom16([16]byte(local_ip)), 0)), net.UDPAddrFromAddrPort(Host))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
err2 := err
|
||||||
stream, err = net.DialUDP("udp4", nil, nil)
|
stream, err = net.DialUDP("udp4", nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
LogDebug.Printf("Failed to bind UDP to special local address, in-game ip banning will not work: %s", err.Error())
|
logDebug.Printf("Failed to bind UDP to special local address, in-game ip banning will not work: %s", err2.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return stream, nil
|
return stream, nil
|
||||||
|
148
tunnel/lib.go
148
tunnel/lib.go
@ -1,85 +1,97 @@
|
|||||||
package tunnel
|
package tunnel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net/netip"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PortProto struct {
|
|
||||||
// 1 => "tcp"
|
|
||||||
//
|
|
||||||
// 2 => "udp"
|
|
||||||
//
|
|
||||||
// 3 => "both"
|
|
||||||
Value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *PortProto) WriteTo(I io.Writer) error {
|
|
||||||
switch w.Value {
|
|
||||||
case "tcp": return WriteU8(I, 1)
|
|
||||||
case "udp": return WriteU8(I, 2)
|
|
||||||
case "both": return WriteU8(I, 3)
|
|
||||||
}
|
|
||||||
return fmt.Errorf("set valid proto")
|
|
||||||
}
|
|
||||||
func (w *PortProto) ReadFrom(I io.Reader) error {
|
|
||||||
switch ReadU8(I) {
|
|
||||||
case 1:
|
|
||||||
w.Value = "tcp"
|
|
||||||
return nil
|
|
||||||
case 2:
|
|
||||||
w.Value = "udp"
|
|
||||||
return nil
|
|
||||||
case 3:
|
|
||||||
w.Value = "both"
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return fmt.Errorf("invalid proto")
|
|
||||||
}
|
|
||||||
|
|
||||||
type AgentSessionId struct {
|
type AgentSessionId struct {
|
||||||
SessionID, AccountID, AgentID uint64
|
SessionID, AccountID, AgentID uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *AgentSessionId) WriteTo(I io.Writer) error {
|
|
||||||
var err error
|
|
||||||
if err = WriteU64(I, w.SessionID); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err = WriteU64(I, w.AccountID); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err = WriteU64(I, w.AgentID); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (w *AgentSessionId) ReadFrom(I io.Reader) error {
|
|
||||||
w.SessionID, w.AccountID, w.AgentID = ReadU64(I), ReadU64(I), ReadU64(I)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type PortRange struct {
|
type PortRange struct {
|
||||||
IP net.IP
|
IP netip.Addr
|
||||||
PortStart uint16
|
PortStart, PortEnd uint16
|
||||||
PortEnd uint16
|
PortProto PortProto
|
||||||
PortProto PortProto
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *PortRange) WriteTo(I io.Writer) error {
|
type PortProto string
|
||||||
if err := binary.Write(I, binary.BigEndian, w.IP); err != nil {
|
|
||||||
return err
|
func (AgentSession *AgentSessionId) WriteTo(w io.Writer) (int64, error) {
|
||||||
} else if err := WriteU16(I, w.PortStart); err != nil {
|
if _, err := writeU64(w, AgentSession.SessionID); err != nil {
|
||||||
return err
|
return 0, err
|
||||||
} else if err := WriteU16(I, w.PortEnd); err != nil {
|
} else if _, err = writeU64(w, AgentSession.AccountID); err != nil {
|
||||||
return err
|
return 8, err
|
||||||
} else if err := w.PortProto.WriteTo(I); err != nil {
|
} else if _, err = writeU64(w, AgentSession.AgentID); err != nil {
|
||||||
return err
|
return 16, err
|
||||||
}
|
}
|
||||||
return nil
|
return 24, nil
|
||||||
|
}
|
||||||
|
func (AgentSession *AgentSessionId) ReadFrom(r io.Reader) (int64, error) {
|
||||||
|
AgentSession.SessionID, AgentSession.AccountID, AgentSession.AgentID = readU64(r), readU64(r), readU64(r)
|
||||||
|
return 24, nil
|
||||||
}
|
}
|
||||||
func (w *PortRange) ReadFrom(I io.Reader) error {
|
|
||||||
|
|
||||||
return nil
|
func (portRange *PortRange) WriteTo(w io.Writer) (int64, error) {
|
||||||
}
|
var len int64 = 4
|
||||||
|
sizeIP, err := addrWrite(w, portRange.IP)
|
||||||
|
if err != nil {
|
||||||
|
return len, err
|
||||||
|
}
|
||||||
|
len += sizeIP
|
||||||
|
if _, err = writeU16(w, portRange.PortStart); err != nil {
|
||||||
|
return len, err
|
||||||
|
} else if _, err = writeU16(w, portRange.PortEnd); err != nil {
|
||||||
|
return len, err
|
||||||
|
}
|
||||||
|
protoSize, err := portRange.PortProto.WriteTo(w)
|
||||||
|
if err != nil {
|
||||||
|
return len, err
|
||||||
|
}
|
||||||
|
return len + protoSize, nil
|
||||||
|
}
|
||||||
|
func (portRange *PortRange) ReadFrom(r io.Reader) (int64, error) {
|
||||||
|
var (
|
||||||
|
ipSize int64
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
portRange.IP, ipSize, err = addrRead(r)
|
||||||
|
if err != nil {
|
||||||
|
return ipSize, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ipSize += 4
|
||||||
|
portRange.PortStart, portRange.PortEnd = readU16(r), readU16(r)
|
||||||
|
|
||||||
|
portRange.PortProto = PortProto("")
|
||||||
|
protoSize, err := portRange.PortProto.ReadFrom(r)
|
||||||
|
if err != nil {
|
||||||
|
return ipSize, err
|
||||||
|
}
|
||||||
|
return ipSize + protoSize, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (proto PortProto) WriteTo(w io.Writer) (int64, error) {
|
||||||
|
switch proto {
|
||||||
|
case "tcp":
|
||||||
|
return writeU8(w, 1)
|
||||||
|
case "udp":
|
||||||
|
return writeU8(w, 2)
|
||||||
|
case "both":
|
||||||
|
return writeU8(w, 3)
|
||||||
|
}
|
||||||
|
return 0, fmt.Errorf("invalid port proto")
|
||||||
|
}
|
||||||
|
func (proto PortProto) ReadFrom(r io.Reader) (int64, error) {
|
||||||
|
switch readU8(r) {
|
||||||
|
case 1:
|
||||||
|
proto = PortProto("tcp")
|
||||||
|
case 2:
|
||||||
|
proto = PortProto("udp")
|
||||||
|
case 3:
|
||||||
|
proto = PortProto("both")
|
||||||
|
default: return 0, fmt.Errorf("invalid port proto")
|
||||||
|
}
|
||||||
|
return 1, nil
|
||||||
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package tunnel
|
package tunnel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/binary"
|
||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MessageEncoding interface {
|
type MessageEncoding interface {
|
||||||
WriteTo(I io.Writer) error
|
io.ReaderFrom
|
||||||
ReadFrom(I io.Reader) error
|
io.WriterTo
|
||||||
}
|
}
|
||||||
|
|
||||||
type ControlRpcMessage[T MessageEncoding] struct {
|
type ControlRpcMessage[T MessageEncoding] struct {
|
||||||
@ -15,22 +15,22 @@ type ControlRpcMessage[T MessageEncoding] struct {
|
|||||||
Content T // Convert with .(*type)
|
Content T // Convert with .(*type)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *ControlRpcMessage[T]) WriteTo(I io.Writer) error {
|
func (rpc *ControlRpcMessage[T]) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
if err := WriteU64(I, w.RequestID); err != nil {
|
if err = binary.Write(w, binary.BigEndian, rpc.RequestID); err != nil {
|
||||||
return err
|
return 0, err
|
||||||
|
} else if n, err = rpc.Content.WriteTo(w); err != nil {
|
||||||
|
return 8, err
|
||||||
}
|
}
|
||||||
defer func() {
|
n += 8
|
||||||
d, _ := json.MarshalIndent(w, "", " ")
|
return
|
||||||
LogDebug.Printf("Write RPC: %s\n", string(d))
|
|
||||||
}()
|
|
||||||
return w.Content.WriteTo(I)
|
|
||||||
}
|
}
|
||||||
|
func (rpc *ControlRpcMessage[T]) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
func (w *ControlRpcMessage[T]) ReadFrom(I io.Reader) error {
|
if err = binary.Read(r, binary.BigEndian, &rpc.RequestID); err != nil {
|
||||||
w.RequestID = ReadU64(I)
|
n = 0
|
||||||
defer func() {
|
return n, err
|
||||||
d, _ := json.MarshalIndent(w, "", " ")
|
} else if n, err = rpc.Content.ReadFrom(r); err != nil {
|
||||||
LogDebug.Printf("Read RPC: %s\n", string(d))
|
return 8, err
|
||||||
}()
|
}
|
||||||
return w.Content.ReadFrom(I)
|
n += 8
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
@ -1,94 +0,0 @@
|
|||||||
package tunnel
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/netip"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TunnelRunner struct {
|
|
||||||
Lookup AddressLookup[netip.AddrPort]
|
|
||||||
Tunnel SimplesTunnel
|
|
||||||
KeepRunning atomic.Bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tun *TunnelRunner) UseSpecialLan(set bool) {
|
|
||||||
panic("no implemented UseSpecialLan")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tun *TunnelRunner) Run() error {
|
|
||||||
channel := make(chan error)
|
|
||||||
// udp := tun.Tunnel.UdpTunnel
|
|
||||||
|
|
||||||
// Setup Tunnel
|
|
||||||
if err := tun.Tunnel.Setup(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
LogDebug.Println("Success Tunnel setup")
|
|
||||||
|
|
||||||
c := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(c, os.Interrupt)
|
|
||||||
go func() {
|
|
||||||
<-c
|
|
||||||
LogDebug.Println("Cleaning process")
|
|
||||||
tun.KeepRunning.Store(false)
|
|
||||||
tun.Tunnel.ControlChannel.Conn.Udp.Close()
|
|
||||||
os.Exit(1)
|
|
||||||
}()
|
|
||||||
|
|
||||||
// TCP Clients
|
|
||||||
go func() {
|
|
||||||
lastControlUpdate := time.Now().UnixMilli()
|
|
||||||
defer os.Exit(2)
|
|
||||||
for tun.KeepRunning.Load() {
|
|
||||||
now := time.Now().UnixMilli()
|
|
||||||
if 30_000 < now-lastControlUpdate {
|
|
||||||
lastControlUpdate = now
|
|
||||||
LogDebug.Println("Reloading control addr")
|
|
||||||
if _, err := tun.Tunnel.ReloadControlAddr(); err != nil {
|
|
||||||
LogDebug.Println("failed to reload control addr")
|
|
||||||
LogDebug.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
newClient, err := tun.Tunnel.Update()
|
|
||||||
if err != nil {
|
|
||||||
LogDebug.Println(err.Error())
|
|
||||||
channel <- err
|
|
||||||
return
|
|
||||||
} else if newClient == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
LogDebug.Println("tcp client")
|
|
||||||
LogDebug.Printf("%#v\n", newClient)
|
|
||||||
LogDebug.Panic(newClient)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// go func() {
|
|
||||||
// buffer := make([]byte, 2048)
|
|
||||||
// had_success := false
|
|
||||||
// for tun.KeepRunning.Load() {
|
|
||||||
// LogDebug.Println("rec udp tun")
|
|
||||||
// rx, err := udp.ReceiveFrom(buffer)
|
|
||||||
// if err != nil {
|
|
||||||
// LogDebug.Println(err)
|
|
||||||
// if had_success {
|
|
||||||
// LogDebug.Panicln("got error")
|
|
||||||
// }
|
|
||||||
// time.Sleep(time.Second)
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// LogDebug.Println("success")
|
|
||||||
// had_success = true
|
|
||||||
// if rx.ConfirmerdConnection {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// LogDebug.Printf("%#v\n", rx.ReceivedPacket)
|
|
||||||
// }
|
|
||||||
// }()
|
|
||||||
return <-channel
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
package rwlock
|
|
||||||
|
|
||||||
import "sync"
|
|
||||||
|
|
||||||
type Rwlock[T any] struct {
|
|
||||||
Value T
|
|
||||||
sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get writer value and return unlocker function
|
|
||||||
//
|
|
||||||
// if call this function before end call function
|
|
||||||
func (rw *Rwlock[T]) Write() (T, func()) {
|
|
||||||
rw.Lock()
|
|
||||||
return rw.Value, rw.Unlock
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get reader value and unlocker function
|
|
||||||
func (rw *Rwlock[T]) Read() (T, func()) {
|
|
||||||
rw.RLock()
|
|
||||||
return rw.Value, rw.RUnlock
|
|
||||||
}
|
|
190
tunnel/setup.go
190
tunnel/setup.go
@ -1,190 +0,0 @@
|
|||||||
package tunnel
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"net/netip"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"sirherobrine23.org/playit-cloud/go-playit/api"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SetupFindSuitableChannel struct {
|
|
||||||
Address []netip.AddrPort
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Setup *SetupFindSuitableChannel) Setup() (*ConnectedControl, error) {
|
|
||||||
for _, Addr := range Setup.Address {
|
|
||||||
network := "udp6"
|
|
||||||
if Addr.Addr().Is4() && !Addr.Addr().Is4In6() {
|
|
||||||
network = "udp4"
|
|
||||||
}
|
|
||||||
conn, err := net.ListenUDP(network, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for range 3 {
|
|
||||||
// Make initial ping
|
|
||||||
buffer := bytes.NewBuffer([]byte{})
|
|
||||||
if err = (&ControlRpcMessage[*ControlRequest]{
|
|
||||||
RequestID: 1,
|
|
||||||
Content: &ControlRequest{
|
|
||||||
Ping: &Ping{
|
|
||||||
Now: time.Now(),
|
|
||||||
CurrentPing: nil,
|
|
||||||
SessionID: nil,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}).WriteTo(buffer); err != nil {
|
|
||||||
conn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write initial ping
|
|
||||||
_, err = conn.WriteToUDP(buffer.Bytes(), net.UDPAddrFromAddrPort(Addr))
|
|
||||||
if err != nil {
|
|
||||||
conn.Close()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
for range 5 {
|
|
||||||
buff := make([]byte, 2048)
|
|
||||||
if err = conn.SetReadDeadline(time.Now().Add(time.Millisecond * 5)); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
bytesSize, peer, err := conn.ReadFrom(buff)
|
|
||||||
if err != nil {
|
|
||||||
if netErr, isNet := err.(net.Error); isNet {
|
|
||||||
if netErr.Timeout() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
} else if peer.String() != Addr.String() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
buff = buff[:bytesSize]
|
|
||||||
var feed ControlFeed
|
|
||||||
if err := feed.ReadFrom(bytes.NewReader(buff)); err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if feed.Response == nil {
|
|
||||||
return nil, fmt.Errorf("unexpected control feed")
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := feed.Response
|
|
||||||
if msg.RequestID != 1 {
|
|
||||||
continue
|
|
||||||
} else if msg.Content.Pong == nil {
|
|
||||||
return nil, fmt.Errorf("expected pong got other response")
|
|
||||||
}
|
|
||||||
return &ConnectedControl{
|
|
||||||
ControlAddr: Addr,
|
|
||||||
Udp: conn,
|
|
||||||
Pong: msg.Content.Pong,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("cannot make UDP tunnel to playit controller, check you internet conenction")
|
|
||||||
}
|
|
||||||
|
|
||||||
type ConnectedControl struct {
|
|
||||||
ControlAddr netip.AddrPort
|
|
||||||
Udp *net.UDPConn
|
|
||||||
Pong *Pong
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Control *ConnectedControl) Authenticate(Api api.Api) (*AuthenticatedControl, error) {
|
|
||||||
if !Control.Pong.ClientAddr.AddrPort.IsValid() {
|
|
||||||
return nil, fmt.Errorf("invalid pong Client address")
|
|
||||||
} else if !Control.Pong.TunnelAddr.AddrPort.IsValid() {
|
|
||||||
return nil, fmt.Errorf("invalid pong Tunnel address")
|
|
||||||
}
|
|
||||||
|
|
||||||
LogDebug.Println("Registring agent proto")
|
|
||||||
tk, err := Api.ProtoRegisterRegister(Control.Pong.ClientAddr.AddrPort, Control.Pong.TunnelAddr.AddrPort)
|
|
||||||
if err != nil {
|
|
||||||
LogDebug.Println("failed to sign and register")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
tkBytes, err := hex.DecodeString(tk)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for range 5 {
|
|
||||||
buffer := bytes.NewBuffer([]byte{})
|
|
||||||
if err := (&ControlRpcMessage[*RawSlice]{
|
|
||||||
RequestID: 10,
|
|
||||||
Content: &RawSlice{
|
|
||||||
Buff: tkBytes,
|
|
||||||
},
|
|
||||||
}).WriteTo(buffer); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_, err := Control.Udp.WriteTo(buffer.Bytes(), net.UDPAddrFromAddrPort(Control.ControlAddr))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for range 5 {
|
|
||||||
reciver := append(buffer.Bytes(), make([]byte, 1024)...)
|
|
||||||
Control.Udp.SetReadDeadline(time.Now().Add(time.Millisecond * 5))
|
|
||||||
recSize, remote, err := Control.Udp.ReadFrom(reciver)
|
|
||||||
if err != nil {
|
|
||||||
if errNet, isNet := err.(net.Error); isNet {
|
|
||||||
if errNet.Timeout() {
|
|
||||||
LogDebug.Println("Timeout")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
} else if remote.String() != Control.ControlAddr.String() {
|
|
||||||
LogDebug.Println("got response not from tunnel server")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
feed := &ControlFeed{}
|
|
||||||
if err = feed.ReadFrom(bytes.NewReader(reciver[:recSize])); err != nil {
|
|
||||||
LogDebug.Println("failed to read response from tunnel")
|
|
||||||
return nil, err
|
|
||||||
} else if feed.Response.RequestID != 10 {
|
|
||||||
LogDebug.Println("got response for different request")
|
|
||||||
continue
|
|
||||||
} else if feed.Response == nil || feed.Response.Content == nil {
|
|
||||||
LogDebug.Println("feed response or Response content is empty")
|
|
||||||
return nil, fmt.Errorf("cannot get response")
|
|
||||||
}
|
|
||||||
|
|
||||||
controlRes := feed.Response.Content
|
|
||||||
if controlRes.RequestQueued {
|
|
||||||
LogDebug.Println("register queued, waiting 1s")
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
continue
|
|
||||||
} else if controlRes.InvalidSignature {
|
|
||||||
return nil, fmt.Errorf("register return invalid signature")
|
|
||||||
} else if controlRes.Unauthorized {
|
|
||||||
return nil, fmt.Errorf("unauthorized")
|
|
||||||
} else if controlRes.AgentRegistered != nil {
|
|
||||||
return &AuthenticatedControl{
|
|
||||||
ApiClient: Api,
|
|
||||||
Conn: *Control,
|
|
||||||
LastPong: *Control.Pong,
|
|
||||||
CurrentPing: nil,
|
|
||||||
Registered: *controlRes.AgentRegistered,
|
|
||||||
Buff: reciver[recSize:],
|
|
||||||
ForceEpired: false,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
LogDebug.Println("expected AgentRegistered but got something else")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("failed1 to connect agent")
|
|
||||||
}
|
|
@ -1,213 +0,0 @@
|
|||||||
package tunnel
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/netip"
|
|
||||||
"slices"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"sirherobrine23.org/playit-cloud/go-playit/api"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SimplesTunnel struct {
|
|
||||||
ApiClaim api.Api
|
|
||||||
ControlAddr netip.AddrPort
|
|
||||||
ControlChannel *AuthenticatedControl
|
|
||||||
UdpTunnel UdpTunnel
|
|
||||||
LastKeepAlive uint64
|
|
||||||
LastPing uint64
|
|
||||||
LastPong uint64
|
|
||||||
LastUdpAuth uint64
|
|
||||||
lastControlTargets []netip.AddrPort
|
|
||||||
}
|
|
||||||
|
|
||||||
func ControlAddresses(Api api.Api) ([]netip.AddrPort, error) {
|
|
||||||
controls, err := Api.AgentRoutings(nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
addrs := []netip.AddrPort{}
|
|
||||||
for _, v := range append(controls.Targets6, controls.Targets4...) {
|
|
||||||
addrs = append(addrs, netip.AddrPortFrom(v, 5525))
|
|
||||||
}
|
|
||||||
return addrs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Tun *SimplesTunnel) Setup() error {
|
|
||||||
if err := AssignUdpTunnel(&Tun.UdpTunnel); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
addresses, err := ControlAddresses(Tun.ApiClaim)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
setup, err := (&SetupFindSuitableChannel{Address: addresses}).Setup()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
control_channel, err := setup.Authenticate(Tun.ApiClaim)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
Tun.ControlAddr = setup.ControlAddr
|
|
||||||
Tun.ControlChannel = control_channel
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Tun *SimplesTunnel) ReloadControlAddr() (bool, error) {
|
|
||||||
addresses, err := ControlAddresses(Tun.ApiClaim)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if slices.ContainsFunc(Tun.lastControlTargets, func(a netip.AddrPort) bool {
|
|
||||||
return !slices.ContainsFunc(addresses, func(b netip.AddrPort) bool {
|
|
||||||
return a.Compare(b) == 0
|
|
||||||
})
|
|
||||||
}) {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
setup, err := (&SetupFindSuitableChannel{addresses}).Setup()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
updated, err := Tun.UpdateControlAddr(*setup)
|
|
||||||
Tun.lastControlTargets = addresses
|
|
||||||
return updated, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Tun *SimplesTunnel) UpdateControlAddr(conncted ConnectedControl) (ok bool, err error) {
|
|
||||||
if conncted.ControlAddr.Compare(Tun.ControlAddr) == 0 {
|
|
||||||
LogDebug.Println("not required Update control addr")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var controlChannel *AuthenticatedControl
|
|
||||||
controlChannel, err = conncted.Authenticate(Tun.ApiClaim)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
LogDebug.Printf("Update control address %s to %s\n", Tun.ControlAddr.String(), conncted.ControlAddr.String())
|
|
||||||
|
|
||||||
Tun.ControlChannel = controlChannel
|
|
||||||
Tun.ControlAddr = conncted.ControlAddr
|
|
||||||
Tun.LastPing = 0
|
|
||||||
Tun.LastKeepAlive = 0
|
|
||||||
Tun.LastUdpAuth = 0
|
|
||||||
Tun.UdpTunnel.InvalidateSession()
|
|
||||||
ok = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Tun *SimplesTunnel) Update() (*NewClient, error) {
|
|
||||||
if Tun.ControlChannel.IsIspired() {
|
|
||||||
LogDebug.Println("Creating new controller channel...")
|
|
||||||
if err := Tun.ControlChannel.Authenticate(); err != nil {
|
|
||||||
LogDebug.Println(err)
|
|
||||||
time.Sleep(time.Second * 2)
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
now := uint64(time.Now().UnixMilli())
|
|
||||||
if now-Tun.LastPing > 1_000 {
|
|
||||||
Tun.LastPing = now
|
|
||||||
if err := Tun.ControlChannel.SendPing(200, time.UnixMilli(int64(now))); err != nil {
|
|
||||||
LogDebug.Println("failed to send ping")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// d, _ := json.MarshalIndent(Tun, "", " ")
|
|
||||||
// LogDebug.Panicf(string(d))
|
|
||||||
|
|
||||||
if Tun.UdpTunnel.RequiresAuth() {
|
|
||||||
if 5_000 < now-Tun.LastUdpAuth {
|
|
||||||
Tun.LastUdpAuth = now
|
|
||||||
if err := Tun.ControlChannel.SendSetupUDPChannel(9000); err != nil {
|
|
||||||
LogDebug.Println("failed to send udp setup request to control")
|
|
||||||
LogDebug.Println(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if Tun.UdpTunnel.RequireResend() {
|
|
||||||
if 1_000 < now-Tun.LastUdpAuth {
|
|
||||||
Tun.LastUdpAuth = now
|
|
||||||
if _, err := Tun.UdpTunnel.ResendToken(); err != nil {
|
|
||||||
LogDebug.Println("failed to send udp auth request")
|
|
||||||
LogDebug.Println(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
timeTillExpire := func(x, y uint64) uint64 {
|
|
||||||
if x > y {
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
return x
|
|
||||||
}(uint64(Tun.ControlChannel.Registered.ExpiresAt.UnixMilli()), uint64(now))
|
|
||||||
if 10_000 < now-Tun.LastKeepAlive && timeTillExpire < 30_000 {
|
|
||||||
Tun.LastKeepAlive = now
|
|
||||||
LogDebug.Println("send KeepAlive")
|
|
||||||
if err := Tun.ControlChannel.SendKeepAlive(100); err != nil {
|
|
||||||
LogDebug.Println("failed to send KeepAlive")
|
|
||||||
LogDebug.Println(err)
|
|
||||||
}
|
|
||||||
if err := Tun.ControlChannel.SendSetupUDPChannel(1); err != nil {
|
|
||||||
LogDebug.Println("failed to send setup udp channel request")
|
|
||||||
LogDebug.Println(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout := 0
|
|
||||||
for range 30 {
|
|
||||||
if timeout >= 10 {
|
|
||||||
LogDebug.Println("feed recv timeout")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
LogDebug.Println("RX Feed message")
|
|
||||||
men, err := Tun.ControlChannel.RecFeedMsg()
|
|
||||||
if err != nil {
|
|
||||||
timeout++
|
|
||||||
LogDebug.Printf("failed to parse response: %s\n", err.Error())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if men.NewClient != nil {
|
|
||||||
return men.NewClient, nil
|
|
||||||
} else if men.Response != nil {
|
|
||||||
cont := men.Response.Content
|
|
||||||
if cont.UdpChannelDetails != nil {
|
|
||||||
LogDebug.Print("Response SetUdpTunnel")
|
|
||||||
if err := Tun.UdpTunnel.SetUdpTunnel(*men.Response.Content.UdpChannelDetails); err != nil {
|
|
||||||
timeout++
|
|
||||||
LogDebug.Print(err)
|
|
||||||
}
|
|
||||||
} else if cont.Pong != nil {
|
|
||||||
Tun.LastPong = uint64(time.Now().UnixMilli())
|
|
||||||
if cont.Pong.ClientAddr.Compare(Tun.ControlChannel.Conn.Pong.ClientAddr.AddrPort) != 0 {
|
|
||||||
LogDebug.Printf("Client IP changed: %q -> %q\n", cont.Pong.ClientAddr, Tun.ControlChannel.Conn.Pong.ClientAddr.AddrPort)
|
|
||||||
}
|
|
||||||
} else if cont.Unauthorized {
|
|
||||||
LogDebug.Panicln("unauthorized, check token or reload agent")
|
|
||||||
Tun.ControlChannel.ForceEpired = true
|
|
||||||
return nil, fmt.Errorf("unauthorized, check token or reload agent")
|
|
||||||
} else {
|
|
||||||
LogDebug.Printf("got response")
|
|
||||||
d , _ := json.MarshalIndent(men, "", " ")
|
|
||||||
LogDebug.Printf(string(d))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if Tun.LastPong != 0 && uint64(time.Now().UnixMilli())-Tun.LastPong > 6_000 {
|
|
||||||
LogDebug.Println("timeout waiting for pong")
|
|
||||||
Tun.LastPong = 0
|
|
||||||
Tun.ControlChannel.ForceEpired = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package tunnel
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
type TcpTunnel struct {
|
|
||||||
ClaimInstructions ClaimInstructions
|
|
||||||
}
|
|
||||||
func (tcp *TcpTunnel) Connect() (*net.TCPConn, error) {
|
|
||||||
stream, err := net.DialTCP("tcp", nil, net.TCPAddrFromAddrPort(tcp.ClaimInstructions.Address.AddrPort))
|
|
||||||
if err != nil {
|
|
||||||
LogDebug.Printf("%q: Failed to establish connection to tunnel server\n", tcp.ClaimInstructions.Address.AddrPort.String())
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if _, err := stream.Write(tcp.ClaimInstructions.Token); err != nil {
|
|
||||||
stream.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
res := make([]byte, 8)
|
|
||||||
if _, err := stream.Read(res); err != nil {
|
|
||||||
stream.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
LogDebug.Printf("%+v\n", res)
|
|
||||||
return stream, nil
|
|
||||||
}
|
|
@ -5,4 +5,5 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
var LogDebug = log.New(os.Stderr, "go-playit.gg: ", log.Ldate|log.Ltime)
|
// Write log and show in terminal to debug
|
||||||
|
var logDebug *log.Logger = log.New(os.Stderr, "plait.gg", log.Ltime|log.Ldate)
|
@ -1,134 +0,0 @@
|
|||||||
package tunnel
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/netip"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
REDIRECT_FLOW_4_FOOTER_ID_OLD uint64 = 0x5cb867cf788173b2
|
|
||||||
REDIRECT_FLOW_4_FOOTER_ID uint64 = 0x4448474f48414344
|
|
||||||
REDIRECT_FLOW_6_FOOTER_ID uint64 = 0x6668676f68616366
|
|
||||||
UDP_CHANNEL_ESTABLISH_ID uint64 = 0xd01fe6830ddce781
|
|
||||||
|
|
||||||
V4_LEN int = 20
|
|
||||||
V6_LEN int = 48
|
|
||||||
)
|
|
||||||
|
|
||||||
type UdpFlowBase struct {
|
|
||||||
Src, Dst netip.AddrPort
|
|
||||||
}
|
|
||||||
|
|
||||||
type UdpFlow struct {
|
|
||||||
V4 *UdpFlowBase
|
|
||||||
V6 *struct {
|
|
||||||
UdpFlowBase
|
|
||||||
Flow uint32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *UdpFlow) Len() int {
|
|
||||||
if w.V4 == nil {
|
|
||||||
return V6_LEN
|
|
||||||
}
|
|
||||||
return V4_LEN
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *UdpFlow) Src() netip.AddrPort {
|
|
||||||
if w.V4 == nil {
|
|
||||||
return w.V6.UdpFlowBase.Src
|
|
||||||
}
|
|
||||||
return w.V4.Src
|
|
||||||
}
|
|
||||||
func (w *UdpFlow) Dst() netip.AddrPort {
|
|
||||||
if w.V4 == nil {
|
|
||||||
return w.V6.UdpFlowBase.Dst
|
|
||||||
}
|
|
||||||
return w.V4.Dst
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *UdpFlow) WriteTo(writer io.Writer) error {
|
|
||||||
var conn UdpFlowBase
|
|
||||||
if w.V4 != nil {
|
|
||||||
conn = *w.V4
|
|
||||||
} else {
|
|
||||||
conn = w.V6.UdpFlowBase
|
|
||||||
}
|
|
||||||
if err := WriteData(writer, conn.Src.Addr().AsSlice()); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := WriteData(writer, conn.Dst.Addr().AsSlice()); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := WriteU16(writer, conn.Src.Port()); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := WriteU16(writer, conn.Dst.Port()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if w.V4 != nil {
|
|
||||||
if err := WriteU64(writer, REDIRECT_FLOW_4_FOOTER_ID_OLD); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err := WriteU32(writer, w.V6.Flow); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := WriteU64(writer, REDIRECT_FLOW_6_FOOTER_ID); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func FromTailUdpFlow(slice []byte) (*UdpFlow, uint64, error) {
|
|
||||||
if len(slice) < 8 {
|
|
||||||
return nil, 0, fmt.Errorf("not space to footer")
|
|
||||||
}
|
|
||||||
footer := binary.BigEndian.Uint64(slice[len(slice)-8:])
|
|
||||||
switch footer {
|
|
||||||
case REDIRECT_FLOW_4_FOOTER_ID | REDIRECT_FLOW_4_FOOTER_ID_OLD:
|
|
||||||
if len(slice) < V4_LEN {
|
|
||||||
return nil, 0, fmt.Errorf("v4 not have space")
|
|
||||||
}
|
|
||||||
slice = slice[len(slice)-V4_LEN:]
|
|
||||||
src_ip, _ := ReadBuffN(bytes.NewReader(slice), 4)
|
|
||||||
srcIP, _ := netip.AddrFromSlice(src_ip)
|
|
||||||
dst_ip, _ := ReadBuffN(bytes.NewReader(slice), 4)
|
|
||||||
dstIP, _ := netip.AddrFromSlice(dst_ip)
|
|
||||||
src_port, dst_port := ReadU16(bytes.NewReader(slice)), ReadU16(bytes.NewReader(slice))
|
|
||||||
|
|
||||||
return &UdpFlow{
|
|
||||||
V4: &UdpFlowBase{
|
|
||||||
Src: netip.AddrPortFrom(srcIP, src_port),
|
|
||||||
Dst: netip.AddrPortFrom(dstIP, dst_port),
|
|
||||||
},
|
|
||||||
}, 0, nil
|
|
||||||
case REDIRECT_FLOW_6_FOOTER_ID:
|
|
||||||
if len(slice) < V6_LEN {
|
|
||||||
return nil, footer, fmt.Errorf("v6 not have space")
|
|
||||||
}
|
|
||||||
slice = slice[len(slice)-V6_LEN:]
|
|
||||||
src_ip, _ := ReadBuffN(bytes.NewReader(slice), 16)
|
|
||||||
srcIP, _ := netip.AddrFromSlice(src_ip)
|
|
||||||
dst_ip, _ := ReadBuffN(bytes.NewReader(slice), 16)
|
|
||||||
dstIP, _ := netip.AddrFromSlice(dst_ip)
|
|
||||||
src_port, dst_port := ReadU16(bytes.NewReader(slice)), ReadU16(bytes.NewReader(slice))
|
|
||||||
flow := ReadU32(bytes.NewReader(slice))
|
|
||||||
|
|
||||||
return &UdpFlow{
|
|
||||||
V6: &struct {
|
|
||||||
UdpFlowBase
|
|
||||||
Flow uint32
|
|
||||||
}{
|
|
||||||
UdpFlowBase{
|
|
||||||
Src: netip.AddrPortFrom(srcIP, src_port),
|
|
||||||
Dst: netip.AddrPortFrom(dstIP, dst_port),
|
|
||||||
},
|
|
||||||
flow,
|
|
||||||
},
|
|
||||||
}, 0, nil
|
|
||||||
}
|
|
||||||
return nil, footer, nil
|
|
||||||
}
|
|
@ -1,225 +0,0 @@
|
|||||||
package tunnel
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"net/netip"
|
|
||||||
"slices"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"sirherobrine23.org/playit-cloud/go-playit/tunnel/rwlock"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UdpTunnel struct {
|
|
||||||
Udp4 *net.UDPConn
|
|
||||||
Udp6 *net.UDPConn
|
|
||||||
Details rwlock.Rwlock[ChannelDetails]
|
|
||||||
LastConfirm atomic.Uint32
|
|
||||||
LastSend atomic.Uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type ChannelDetails struct {
|
|
||||||
Udp *UdpChannelDetails
|
|
||||||
AddrHistory []netip.AddrPort
|
|
||||||
}
|
|
||||||
|
|
||||||
func AssignUdpTunnel(tunUdp *UdpTunnel) error {
|
|
||||||
LogDebug.Println("Assign UDP Tunnel IPv4")
|
|
||||||
udp4, err := net.ListenUDP("udp4", nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
tunUdp.Udp4 = udp4
|
|
||||||
// IPv6 opcional
|
|
||||||
LogDebug.Println("Assign UDP Tunnel IPv6")
|
|
||||||
if tunUdp.Udp6, err = net.ListenUDP("udp6", nil); err != nil {
|
|
||||||
LogDebug.Println("Cannot listen IPv6 Udp Tunnel")
|
|
||||||
tunUdp.Udp6 = nil
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
tunUdp.Details = rwlock.Rwlock[ChannelDetails]{Value: ChannelDetails{
|
|
||||||
AddrHistory: []netip.AddrPort{},
|
|
||||||
Udp: nil,
|
|
||||||
}}
|
|
||||||
|
|
||||||
tunUdp.LastConfirm = atomic.Uint32{}
|
|
||||||
tunUdp.LastSend = atomic.Uint32{}
|
|
||||||
tunUdp.LastConfirm.Store(0)
|
|
||||||
tunUdp.LastSend.Store(0)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (udp *UdpTunnel) IsSetup() bool {
|
|
||||||
data, unlock := udp.Details.Read()
|
|
||||||
defer unlock()
|
|
||||||
return data.Udp != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (udp *UdpTunnel) InvalidateSession() {
|
|
||||||
udp.LastConfirm.Store(0)
|
|
||||||
udp.LastSend.Store(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func now_sec() uint32 {
|
|
||||||
return uint32(time.Now().UnixMilli()) / 1_000
|
|
||||||
}
|
|
||||||
|
|
||||||
func (udp *UdpTunnel) RequireResend() bool {
|
|
||||||
last_confirm := udp.LastConfirm.Load()
|
|
||||||
/* send token every 10 seconds */
|
|
||||||
return 10 < now_sec()-last_confirm
|
|
||||||
}
|
|
||||||
|
|
||||||
func (udp *UdpTunnel) RequiresAuth() bool {
|
|
||||||
lastConf, lastSend := udp.LastConfirm.Load(), udp.LastSend.Load()
|
|
||||||
if lastSend < lastConf {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return 5 < now_sec()-lastSend
|
|
||||||
}
|
|
||||||
|
|
||||||
func (udp *UdpTunnel) SetUdpTunnel(details UdpChannelDetails) error {
|
|
||||||
LogDebug.Println("Updating Udp Tunnel")
|
|
||||||
lock, unlock := udp.Details.Write()
|
|
||||||
|
|
||||||
if lock.Udp != nil {
|
|
||||||
current := lock.Udp
|
|
||||||
if bytes.Equal(current.Token, details.Token) && current.TunnelAddr.Compare(details.TunnelAddr.AddrPort) == 0 {
|
|
||||||
unlock()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if current.TunnelAddr.Compare(details.TunnelAddr.AddrPort) != 0 {
|
|
||||||
LogDebug.Println("changed udp tunner addr")
|
|
||||||
oldAddr := current.TunnelAddr
|
|
||||||
lock.AddrHistory = append(lock.AddrHistory, oldAddr.AddrPort)
|
|
||||||
}
|
|
||||||
lock.Udp = &details
|
|
||||||
}
|
|
||||||
|
|
||||||
unlock()
|
|
||||||
return udp.SendToken(&details)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (udp *UdpTunnel) ResendToken() (bool, error) {
|
|
||||||
lock, unlock := udp.Details.Read()
|
|
||||||
defer unlock()
|
|
||||||
if lock.Udp == nil {
|
|
||||||
return false, nil
|
|
||||||
} else if err := udp.SendToken(lock.Udp); err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (udp *UdpTunnel) SendToken(details *UdpChannelDetails) error {
|
|
||||||
if details.TunnelAddr.Addr().Is4() {
|
|
||||||
udp.Udp4.WriteToUDPAddrPort(details.Token, details.TunnelAddr.AddrPort)
|
|
||||||
} else {
|
|
||||||
if udp.Udp6 == nil {
|
|
||||||
return fmt.Errorf("ipv6 not supported")
|
|
||||||
}
|
|
||||||
udp.Udp6.WriteToUDPAddrPort(details.Token, details.TunnelAddr.AddrPort)
|
|
||||||
}
|
|
||||||
LogDebug.Printf("send udp session token (len=%d) to %s\n", len(details.Token), details.TunnelAddr.AddrPort.String())
|
|
||||||
udp.LastSend.Store(now_sec())
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (udp *UdpTunnel) GetSock() (*net.UDPConn, *netip.AddrPort, error) {
|
|
||||||
lock, unlock := udp.Details.Read()
|
|
||||||
defer unlock()
|
|
||||||
if lock.Udp == nil {
|
|
||||||
LogDebug.Println("udp tunnel not connected")
|
|
||||||
return nil, nil, fmt.Errorf("udp tunnel not connected")
|
|
||||||
} else if lock.Udp.TunnelAddr.Addr().Is4() {
|
|
||||||
return udp.Udp4, &lock.Udp.TunnelAddr.AddrPort, nil
|
|
||||||
} else if udp.Udp6 == nil {
|
|
||||||
LogDebug.Println("ipv6 not setup")
|
|
||||||
return nil, nil, fmt.Errorf("ipv6 not setup")
|
|
||||||
}
|
|
||||||
return udp.Udp6, &lock.Udp.TunnelAddr.AddrPort, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Udp *UdpTunnel) Send(data []byte, Flow UdpFlow) (int, error) {
|
|
||||||
buff := bytes.NewBuffer([]byte{})
|
|
||||||
if err := Flow.WriteTo(buff); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
socket, addr, err := Udp.GetSock()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return socket.WriteToUDPAddrPort(append(data, buff.Bytes()...), *addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Udp *UdpTunnel) GetToken() ([]byte, error) {
|
|
||||||
lock, unlock := Udp.Details.Read()
|
|
||||||
defer unlock()
|
|
||||||
if lock.Udp == nil {
|
|
||||||
return nil, fmt.Errorf("udp tunnel not connected")
|
|
||||||
}
|
|
||||||
return lock.Udp.Token[:], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type UdpTunnelRx struct {
|
|
||||||
ConfirmerdConnection bool
|
|
||||||
ReceivedPacket *struct {
|
|
||||||
Bytes uint64
|
|
||||||
Flow UdpFlow
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Udp *UdpTunnel) ReceiveFrom(buff []byte) (*UdpTunnelRx, error) {
|
|
||||||
udp, tunnelAddr, err := Udp.GetSock()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
byteSize, remote, err := udp.ReadFromUDPAddrPort(buff)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if tunnelAddr.Compare(remote) != 0 {
|
|
||||||
lock, unlock := Udp.Details.Read()
|
|
||||||
defer unlock()
|
|
||||||
if !slices.ContainsFunc(lock.AddrHistory, func(a netip.AddrPort) bool {
|
|
||||||
return a.Compare(remote) == 0
|
|
||||||
}) {
|
|
||||||
return nil, fmt.Errorf("got data from other source")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
token, err := Udp.GetToken()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
LogDebug.Println("Check token")
|
|
||||||
LogDebug.Println(buff)
|
|
||||||
LogDebug.Println(token)
|
|
||||||
LogDebug.Println("end check token")
|
|
||||||
if bytes.Equal(buff[:byteSize], token) {
|
|
||||||
LogDebug.Println("udp session confirmed")
|
|
||||||
Udp.LastConfirm.Store(now_sec())
|
|
||||||
return &UdpTunnelRx{ConfirmerdConnection: true}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(buff) + V6_LEN < byteSize {
|
|
||||||
return nil, fmt.Errorf("receive buffer too small")
|
|
||||||
}
|
|
||||||
|
|
||||||
footer, footerInt, err := FromTailUdpFlow(buff[byteSize:])
|
|
||||||
if err != nil {
|
|
||||||
if footerInt == UDP_CHANNEL_ESTABLISH_ID {
|
|
||||||
actual := hex.EncodeToString(buff[byteSize:]);
|
|
||||||
expected := hex.EncodeToString(token);
|
|
||||||
return nil, fmt.Errorf("unexpected UDP establish packet, actual: %s, expected: %s", actual, expected)
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("failed to extract udp footer: %s, err: %s", hex.EncodeToString(buff[byteSize:]), err.Error())
|
|
||||||
}
|
|
||||||
return &UdpTunnelRx{ReceivedPacket: &struct{Bytes uint64; Flow UdpFlow}{uint64(byteSize) - uint64(footer.Len()), *footer}}, nil
|
|
||||||
}
|
|
Reference in New Issue
Block a user