package test import ( "context" "fmt" "github.com/emiago/sipgo" "github.com/emiago/sipgo/sip" "github.com/icholy/digest" "os" "os/signal" "testing" "time" ) func TestClient(t *testing.T) { sip.SIPDebug = true ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) ua, _ := sipgo.NewUA( sipgo.WithUserAgentHostname("44050100002000000002@10.10.10.20:5099")) srv, _ := sipgo.NewServer(ua) // Creating server handle client, _ := sipgo.NewClient(ua, sipgo.WithClientPort(5099), sipgo.WithClientHostname("10.10.10.20")) target := sip.Uri{ User: "44050100002000000003", Host: "10.10.10.20", Port: 5060, Headers: sip.NewParams(), } uri := sip.Uri{User: "44050100002000000002", Host: "10.10.10.20", Port: 5099} req := sip.NewRequest(sip.REGISTER, target) req.AppendHeader(sip.NewHeader("X-GB-Ver", "2.0")) req.AppendHeader(sip.NewHeader("Contact", uri.String())) req.AppendHeader(sip.NewHeader("Expires", "3600")) //req.Contact = uasContact err := sipgo.ClientRequestBuild(client, req) if err != nil { t.Fatal(err) } quit := make(chan os.Signal) go func() { err = srv.ListenAndServe(ctx, "udp", ":5099") if err != nil { t.Fatal(err) } }() go func() { defer func() { cancel() quit <- os.Interrupt }() //for { select { case <-ctx.Done(): break default: tx, err := client.TransactionRequest(ctx, req) if err != nil { t.Fatal(err) } resp, err := getResponse(tx) tx.Terminate() headers := resp.Headers() for _, h := range headers { t.Log(h.Name(), "=>", h.Value()) } t.Log(resp.String()) if resp.StatusCode == 401 { wwwAuth := resp.GetHeader("WWW-Authenticate") chal, err := digest.ParseChallenge(wwwAuth.Value()) if err != nil { t.Fatal(err, "Fail to parse challenge") } // Reply with digest cred, _ := digest.Digest(chal, digest.Options{ Method: req.Method.String(), Username: "44050100002000000002", URI: target.String(), Password: "123456", }) newReq := req.Clone() newReq.RemoveHeader("Via") // Must be regenerated by tranport layer newReq.AppendHeader(sip.NewHeader("Authorization", cred.String())) ctx := context.Background() tx, err := client.TransactionRequest(ctx, newReq, sipgo.ClientRequestAddVia) if err != nil { t.Fatal("Fail to create transaction") } resp, err = getResponse(tx) tx.Terminate() if err != nil { t.Fatal("Fail to get response") } if resp.StatusCode != 403 { headers := resp.Headers() for _, h := range headers { t.Log(h.Name(), "=>", h.Value()) } tx.Done() //break } t.Log(resp.String()) } } //} }() signal.Notify(quit, os.Interrupt) <-quit } func getResponse(tx sip.ClientTransaction) (*sip.Response, error) { select { case <-tx.Done(): return nil, fmt.Errorf("transaction died") case res := <-tx.Responses(): return res, nil } }