gortc / stun

Fast RFC 5389 STUN implementation in go

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

how set username and credential

hktalent opened this issue · comments

commented

how test,in client

{'urls':'stun:webrtcweb.com:4455?transport=udp','credential':'muazkh','username':'muazkh'},
{'urls':'stun:webrtcweb.com:8877?transport=udp','credential':'muazkh','username':'muazkh'},

#29

Hi, currently there is no automatic method to do it, so it will be pretty verbose.

At first, you should get nonce and realm from server via unauthorized request.
Then you can make authorized requests.

package main

import (
	"fmt"
	"log"

	"github.com/gortc/stun"
)

func main() {
	client, err := stun.Dial("udp", "webrtcweb.com:4455")
	if err != nil {
		log.Fatalln("failed to dial", err)
	}
	var (
		nonce stun.Nonce
		realm stun.Realm
	)
	// Making unauthorized binding request.
	// Response will be CodeUnauthorized, but will contain nonce with realm.
	request, err := stun.Build(stun.BindingRequest, stun.TransactionID, stun.Fingerprint)
	if err != nil {
		log.Fatalln("failed to build:", err)
	}
	if err = client.Do(request, func(event stun.Event) {
		if event.Error != nil {
			log.Fatalln("got event with error:", event.Error)
		}
		response := event.Message
		if response.Type != stun.BindingError {
			log.Fatalln("bad message", response)
		}
		var errCode stun.ErrorCodeAttribute
		if codeErr := errCode.GetFrom(response); codeErr != nil {
			log.Fatalln("failed to get error code:", codeErr)
		}
		if errCode.Code != stun.CodeUnauthorized {
			log.Fatalln("unexpected error code:", errCode)
		}
		if parseErr := response.Parse(&nonce, &realm); parseErr != nil {
			log.Fatalln("failed to parse:", parseErr)
		}
		fmt.Println("got nonce", nonce, "and realm", realm)
	}); err != nil {
		log.Fatalln("failed to Do:", err)
	}
	// Now we can authenticate requests to stun server.
	// For example, binding request.
	const (
		username = "muazkh"
		password = "muazkh"
	)
	request, err = stun.Build(stun.TransactionID, stun.BindingRequest,
		stun.NewUsername(username), nonce, realm,
		stun.NewLongTermIntegrity(username, realm.String(), password),
		stun.Fingerprint,
	)
	if err != nil {
		log.Fatalln(err)
	}
	if err = client.Do(request, func(event stun.Event) {
		if event.Error != nil {
			log.Fatalln("got event with error:", event.Error)
		}
		response := event.Message
		if response.Type != stun.BindingSuccess {
			var errCode stun.ErrorCodeAttribute
			if codeErr := errCode.GetFrom(response); codeErr != nil {
				log.Fatalln("failed to get error code:", codeErr)
			}
			log.Fatalln("bad message", response, errCode)
		}
		var xorMapped stun.XORMappedAddress
		if err = response.Parse(&xorMapped); err != nil {
			log.Fatalln("failed to parse xor mapped address:", err)
		}
		fmt.Println("OK", response, "GOT", xorMapped)
	}); err != nil {
		log.Fatalln("failed to Do:", err)
	}
	if err := client.Close(); err != nil {
		log.Fatalln("failed to close client:", err)
	}
}
commented

@ernado thanks