nodertc / stun

Low-level Session Traversal Utilities for NAT (STUN) client and server
MIT License
160 stars 29 forks source link

Cannot destructure property 'address' of 'res.getXorAddress(...)' as it is undefined #32

Closed JabinGP closed 3 years ago

JabinGP commented 3 years ago

Description: Address in some responses is undefined. OS: 10.15.6 (19G73) Node.js: v14.4.0 Stun: 2.1.0

const stun = require('stun');

const freeStunServers = [
    // google
    "stun1.l.google.com:19302",
    "stun2.l.google.com:19302",
    "stun3.l.google.com:19302",
    "stun4.l.google.com:19302",

    // others
    "stun.ekiga.net:3478",
    "stun.schlund.de:3478",
    "stun.xten.com:3478",
]
freeStunServers.forEach( stunURL => {
    stun.request(stunURL, (err, res) => {
        if (err) {
          console.error(err);
        } else {
          let add = res.getXorAddress();
          if (add) {
            const { address, port } = res.getXorAddress();
            console.log(`Res from ${stunURL} : Your IP is ${address} PORT is ${port}.`);
          }else{
            console.log(`Res from ${stunURL} : address is undefined.`);
          }
        }
      });
})

Output:

Res from stun1.l.google.com:19302 : Your IP is 120.236.163.98 PORT is 12422.
Res from stun2.l.google.com:19302 : Your IP is 120.236.163.98 PORT is 8165.
Res from stun.ekiga.net:3478 : address is undefined.
Res from stun.xten.com:3478 : address is undefined.
Res from stun4.l.google.com:19302 : Your IP is 202.116.36.83 PORT is 12715.
Res from stun3.l.google.com:19302 : Your IP is 120.236.163.98 PORT is 8166.
Res from stun.schlund.de:3478 : Your IP is 120.236.163.98 PORT is 5170.
JabinGP commented 3 years ago

While request the same servers using go and github.com/pion/stun.

package main

import (
    "fmt"
    "log"
    "sync"

    "github.com/pion/stun"
)

var wg sync.WaitGroup

func request(url string) {
    defer func() {
        wg.Done()
    }()
    // Creating a "connection" to STUN server.
    c, err := stun.Dial("udp", url)
    if err != nil {
        log.Println(err)
        return
    }
    // Building binding request with random transaction id.
    message := stun.MustBuild(stun.TransactionID, stun.BindingRequest)
    // Sending request to STUN server, waiting for response message.
    if err := c.Do(message, func(res stun.Event) {
        if res.Error != nil {
            log.Println(res.Error)
            return
        }
        // Decoding XOR-MAPPED-ADDRESS attribute from message.
        var xorAddr stun.XORMappedAddress
        if err := xorAddr.GetFrom(res.Message); err != nil {
            log.Println(err)
            return
        }
        fmt.Printf("Res from %s : Your IP is %d PORT is %d.\n", url, xorAddr.IP, xorAddr.Port)
    }); err != nil {
        log.Println(err)
        return
    }
}

func main() {
    freeStunServers := []string{
        // google
        "stun1.l.google.com:19302",
        "stun2.l.google.com:19302",
        "stun3.l.google.com:19302",
        "stun4.l.google.com:19302",

        // others
        "stun.ekiga.net:3478",
        "stun.schlund.de:3478",
        "stun.xten.com:3478",
    }
    for _, stun := range freeStunServers {
        wg.Add(1)
        go request(stun)
    }

    wg.Wait()
}

Output:

Res from stun2.l.google.com:19302: Your IP is [120 236 163 98], PORT is 11732.
Res from stun.xten.com:3478: Your IP is [120 236 163 98], PORT is 11735.
Res from stun.ekiga.net:3478: Your IP is [120 236 163 98], PORT is 11734.
Res from stun4.l.google.com:19302: Your IP is [202 116 36 83], PORT is 12765.
Res from stun1.l.google.com:19302: Your IP is [120 236 163 98], PORT is 7958.
Res from stun.schlund.de:3478: Your IP is [120 236 163 98], PORT is 7959.
Res from stun3.l.google.com:19302: Your IP is [120 236 163 98], PORT is 11733.
reklatsmasters commented 3 years ago

I got this response from stun.ekiga.net:3478:

StunResponse {
  [Symbol(kMessageType)]: 257,
  [Symbol(kTransctionId)]: <Buffer 02 39 8e bd b1 ae 4c 9d cd ca 87 1a>,
  [Symbol(kCookie)]: 554869826,
  [Symbol(kAttributes)]: [
    StunAddressAttribute {
      [Symbol(kAttributeType)]: 1,
      [Symbol(kPort)]: 53581,
      [Symbol(kAddress)]: '(my ip)',
      [Symbol(kFamily)]: 'IPv4'
    },
    StunUnknownAttribute {
      [Symbol(kAttributeType)]: 4,
      [Symbol(kValue)]: <Buffer 00 01 0d 96 d8 5d f6 12>
    },
    StunUnknownAttribute {
      [Symbol(kAttributeType)]: 5,
      [Symbol(kValue)]: <Buffer 00 01 0d 97 d8 5d f6 0f>
    },
    StunUnknownAttribute {
      [Symbol(kAttributeType)]: 32800,
      [Symbol(kValue)]: <Buffer 00 01 f0 5f 24 b4 07 f2>
    },
    StunByteStringAttribute {
      [Symbol(kAttributeType)]: 32802,
      [Symbol(kValue)]: <Buffer 56 6f 76 69 64 61 2e 6f 72 67 20 30 2e 39 38 2d 43 50 43 00>
    }
  ]
}

I may throw an exception when you try to read non-existed attribute.

JabinGP commented 3 years ago

@reklatsmasters Thanks for your reply, I solved my problem by using let { address, port } = res.getXorAddress() || res.getAddress();.