stun.go 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. package stun
  2. import (
  3. "fmt"
  4. "log"
  5. "net"
  6. "strconv"
  7. "strings"
  8. "gortc.io/stun"
  9. )
  10. type HostInfo struct {
  11. PublicIp net.IP
  12. PrivIp net.IP
  13. PubPort int
  14. PrivPort int
  15. }
  16. var Host HostInfo
  17. func GetHostInfo() (info HostInfo) {
  18. s, err := net.ResolveUDPAddr("udp", "stun.nm.134.209.115.146.nip.io:3478")
  19. if err != nil {
  20. log.Fatal("Resolve: ", err)
  21. }
  22. l := &net.UDPAddr{
  23. IP: net.ParseIP(""),
  24. Port: 51722,
  25. }
  26. conn, err := net.DialUDP("udp", l, s)
  27. if err != nil {
  28. log.Fatal(err)
  29. }
  30. defer conn.Close()
  31. fmt.Printf("%+v\n", conn.LocalAddr())
  32. c, err := stun.NewClient(conn)
  33. if err != nil {
  34. panic(err)
  35. }
  36. defer c.Close()
  37. re := strings.Split(conn.LocalAddr().String(), ":")
  38. info.PrivIp = net.ParseIP(re[0])
  39. info.PrivPort, _ = strconv.Atoi(re[1])
  40. // Building binding request with random transaction id.
  41. message := stun.MustBuild(stun.TransactionID, stun.BindingRequest)
  42. //fmt.Printf("MESG: %+v\n", message)
  43. // Sending request to STUN server, waiting for response message.
  44. if err := c.Do(message, func(res stun.Event) {
  45. //fmt.Printf("RESP: %+v\n", res)
  46. if res.Error != nil {
  47. panic(res.Error)
  48. }
  49. // Decoding XOR-MAPPED-ADDRESS attribute from message.
  50. var xorAddr stun.XORMappedAddress
  51. if err := xorAddr.GetFrom(res.Message); err != nil {
  52. panic(err)
  53. }
  54. info.PublicIp = xorAddr.IP
  55. info.PubPort = xorAddr.Port
  56. }); err != nil {
  57. panic(err)
  58. }
  59. return
  60. }