//go:build android
// +build android

package Android

import (
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"net"
	"os"
)

type NewTun struct {
	IsRunning         bool
	ProxyPort         uint16
	tun               *os.File
	handleTCPCallback func(net.Conn)
	handleUDPCallback func(Type int, Theoni int64, pid uint32, LocalAddress, RemoteAddress string, data []byte) []byte
}

func (n *NewTun) OnTunCreated(fd int) {
	tun := os.NewFile(uintptr(fd), "tun0")
	defer func() {
		_ = tun.Close()
	}()
	n.tun = tun
	buf := make([]byte, 65535)
	for {
		nBytes, err := tun.Read(buf)
		if err != nil || !n.IsRunning {
			_ = tun.Close()
			break
		}
		var packet []byte
		packet = append(packet, buf[:nBytes]...)
		go func() {
			// 解析包（判断方向、类型）
			n.parsePacket(packet)
			//_, _ = tun.Write(n.parsePacket(data))
		}()
	}
}
func (n *NewTun) Send(packetData []byte) {
	_, _ = n.tun.Write(packetData)
}
func (n *NewTun) parsePacket(packetData []byte) {
	first := packetData[0] >> 4
	var packet gopacket.Packet
	if first == 4 {
		packet = gopacket.NewPacket(packetData, layers.LayerTypeIPv4, gopacket.Default)
	} else if first == 6 {
		packet = gopacket.NewPacket(packetData, layers.LayerTypeIPv6, gopacket.Default)
	} else {
		n.Send(packetData)
		return
	}
	if ipv4 := packet.Layer(layers.LayerTypeIPv4); ipv4 != nil {
		ip := ipv4.(*layers.IPv4)
		switch ip.Protocol {
		case layers.IPProtocolTCP:
			if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
				tcp := tcpLayer.(*layers.TCP)
				n.handleTCP4(ip, tcp)
			}
		case layers.IPProtocolUDP:
			if udpLayer := packet.Layer(layers.LayerTypeUDP); udpLayer != nil {
				udp := udpLayer.(*layers.UDP)
				n.handleUDP(ip.SrcIP, ip.DstIP, udp, true)
			}
		}
	} else if ipv6 := packet.Layer(layers.LayerTypeIPv6); ipv6 != nil {
		ip := ipv6.(*layers.IPv6)
		switch ip.NextHeader {
		case layers.IPProtocolTCP:
			if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
				tcp := tcpLayer.(*layers.TCP)
				n.handleTCP6(ip, tcp)
			}
		case layers.IPProtocolUDP:
			if udpLayer := packet.Layer(layers.LayerTypeUDP); udpLayer != nil {
				udp := udpLayer.(*layers.UDP)
				n.handleUDP(ip.SrcIP, ip.DstIP, udp, false)
			}
		}
	}
	return
}
