### Uri String Method Example Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-message.md Demonstrates how to use the String() method of the Uri type to get the full URI string, including user, host, and port. ```go uri := sip.Uri{ User: "bob", Host: "example.com", Port: 5060, } fmt.Println(uri.String()) // Output: sip:bob@example.com:5060 ``` -------------------------------- ### Example FromHeader Creation Source: https://github.com/emiago/sipgo/blob/main/_autodocs/types.md Demonstrates creating a FromHeader instance and adding parameters. ```go from := &sip.FromHeader{ DisplayName: "Alice", Address: sip.Uri{User: "alice", Host: "example.com"}, } from.Params.Add("tag", "12345") ``` -------------------------------- ### Start Listening for Incoming Requests Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/server.md Starts a SIP server listener on the specified network and address. Use context for cancellation. Multiple listeners can be started for different protocols. ```go go srv.ListenAndServe(ctx, "udp", "127.0.0.1:5060") go srv.ListenAndServe(ctx, "tcp", "127.0.0.1:5061") go srv.ListenAndServe(ctx, "ws", "127.0.0.1:5080") ``` -------------------------------- ### Example CSeqHeader Creation Source: https://github.com/emiago/sipgo/blob/main/_autodocs/types.md Demonstrates creating a CSeqHeader instance. ```go cseq := &sip.CSeqHeader{ SeqNo: 1, MethodName: sip.INVITE, } ``` -------------------------------- ### Start SIP Server Listener (WebSocket) Source: https://github.com/emiago/sipgo/blob/main/_autodocs/README.md Starts a SIP server listener over WebSocket. Requires a context and the listening address. ```go ListenAndServe(ctx, "ws", ":5080") ``` -------------------------------- ### Example ViaHeader Creation Source: https://github.com/emiago/sipgo/blob/main/_autodocs/types.md Demonstrates creating a ViaHeader instance and adding parameters. ```go via := &sip.ViaHeader{ ProtocolName: "SIP", ProtocolVersion: "2.0", Transport: "UDP", Host: "192.168.1.100", Port: 5060, } via.Params.Add("branch", "z9hG4bK-123") ``` -------------------------------- ### Example ContactHeader Creation Source: https://github.com/emiago/sipgo/blob/main/_autodocs/types.md Demonstrates creating a ContactHeader instance. ```go contact := &sip.ContactHeader{ DisplayName: "Alice's Phone", Address: sip.Uri{User: "alice", Host: "192.168.1.100", Port: 5060}, } ``` -------------------------------- ### Start SIP Server Listener (Secure WebSocket) Source: https://github.com/emiago/sipgo/blob/main/_autodocs/README.md Starts a SIP server listener over secure WebSocket (WSS). Requires a context, the listening address, and TLS configuration. ```go ListenAndServeTLS(ctx, "ws", ":5081", tlsConf) ``` -------------------------------- ### Start SIP Server Listener (TLS) Source: https://github.com/emiago/sipgo/blob/main/_autodocs/README.md Starts a SIP server listener over TLS on TCP. Requires a context, the listening address, and TLS configuration. ```go ListenAndServeTLS(ctx, "tcp", ":5061", tlsConf) ``` -------------------------------- ### Simple UAC Call Example Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialogs.md A practical example demonstrating a simple UAC call flow. ```APIDOC ## Simple UAC Call ### Description Example demonstrating the creation and management of a UAC dialog for a simple call. ### Code Example ```go dialogUA := sipgo.NewDialogClientCache(client, contactHDR) dialog, err := dialogUA.Invite(ctx, recipientURI, sdpOffer) if err != nil { log.Fatal(err) } defer dialog.Close() err = dialog.WaitAnswer(ctx, sipgo.AnswerOptions{}) if err != nil { log.Fatal(err) } dialog.Ack(ctx) // Dialog is established select { case <-time.After(30*time.Second): dialog.Bye(ctx) case <-dialog.Context().Done(): // Remote party hung up } ``` ``` -------------------------------- ### Start SIP Server Listener (UDP) Source: https://github.com/emiago/sipgo/blob/main/_autodocs/README.md Starts a SIP server listener on the UDP transport protocol. Requires a context and the listening address. ```go ListenAndServe(ctx, "udp", ":5060") ``` -------------------------------- ### Start SIP Server Listener (TCP) Source: https://github.com/emiago/sipgo/blob/main/_autodocs/README.md Starts a SIP server listener on the TCP transport protocol. Requires a context and the listening address. ```go ListenAndServe(ctx, "tcp", ":5061") ``` -------------------------------- ### Uri Addr Method Example Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-message.md Shows how to use the Addr() method to retrieve the SIP URI without parameters and headers. ```go fmt.Println(uri.Addr()) // Output: sip:bob@example.com:5060 ``` -------------------------------- ### Start OpenSIPS Docker Container Source: https://github.com/emiago/sipgo/blob/main/example/proxysip/docker/opensips/README.md Execute this command to start the OpenSIPS Docker container after the image has been built. ```bash make start ``` -------------------------------- ### Start SIP Server Listeners Source: https://github.com/emiago/sipgo/blob/main/_autodocs/README.md Starts the SIP server to listen for incoming requests on specified network protocols and addresses. Uses background goroutines. ```go // 4. Start listeners (Server) ctx := context.Background() go srv.ListenAndServe(ctx, "udp", ":5060") go srv.ListenAndServe(ctx, "tcp", ":5061") ``` -------------------------------- ### Basic TLS Server Setup Source: https://github.com/emiago/sipgo/blob/main/_autodocs/configuration.md Configure a TLS server with certificates and optional client certificate validation. Use this for secure SIP communication over TLS. ```go import ( "crypto/tls" "crypto/x509" ) // Load certificate and key cert, err := tls.LoadX509KeyPair("server.crt", "server.key") if err != nil { log.Fatal(err) } // Optional: Load root CAs for client validation roots := x509.NewCertPool() rootPEM, _ := os.ReadFile("ca.pem") roots.AppendCertsFromPEM(rootPEM) tlsConf := &tls.Config{ Certificates: []tls.Certificate{cert}, RootCAs: roots, ClientCAs: roots, MinVersion: tls.VersionTLS12, } ua, _ := sipgo.NewUA(sipgo.WithUserAgenTLSConfig(tlsConf)) // Listen on TCP port 5061 server, _ := sipgo.NewServer(ua) go server.ListenAndServeTLS(ctx, "tcp", "127.0.0.1:5061", tlsConf) // Listen on WebSocket port 5081 go server.ListenAndServeTLS(ctx, "ws", "127.0.0.1:5081", tlsConf) ``` -------------------------------- ### Start Listening with TLS/WSS Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/server.md Starts a SIP server listener for encrypted connections (TLS or WSS) using a provided TLS configuration. Supports TCP and WS transports. ```go tlsConf := &tls.Config{ Certificates: []tls.Certificate{cert}, } go srv.ListenAndServeTLS(ctx, "tcp", "127.0.0.1:5061", tlsConf) go srv.ListenAndServeTLS(ctx, "ws", "127.0.0.1:5081", tlsConf) ``` -------------------------------- ### Plain WebSocket Server Source: https://github.com/emiago/sipgo/blob/main/_autodocs/configuration.md Start a plain WebSocket server. This is suitable for non-encrypted WebSocket connections. ```go // Plain WebSocket go srv.ListenAndServe(ctx, "ws", "127.0.0.1:5080") ``` -------------------------------- ### Get SIP Response Start Line Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-message.md The StartLine method returns only the status line of the SIP response, formatted as 'SIP/2.0 STATUS REASON'. ```go func (res *Response) StartLine() string ``` ```go fmt.Println(res.StartLine()) // Output: SIP/2.0 200 OK ``` -------------------------------- ### Example SIP Debug Output Source: https://github.com/emiago/sipgo/blob/main/README.md An example of the detailed SIP message logging output when `sip.SIPDebug` is enabled. This shows a typical 100 Trying response with all relevant headers. ```text Feb 24 23:32:26.493191 DBG UDP read 10.10.0.10:5060 <- 10.10.0.100:5060: SIP/2.0 100 Trying Via: SIP/2.0/UDP 10.10.0.10:5060;rport=5060;received=10.10.0.10;branch=z9hG4bK.G3nCwpXAKJQ0T2oZUII70wuQx9NeXc61;alias Via: SIP/2.0/UDP 10.10.0.10:5060;branch=z9hG4bK-1-1-0 Record-Route: Call-ID: 1-1@10.10.0.10 From: "sipp" ;tag=1SIPpTag001 To: "uac" CSeq: 1 INVITE Server: Asterisk PBX 18.16.0 Content-Length: 0 ``` -------------------------------- ### Request StartLine Method Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-message.md Retrieves only the request's start line, which includes the method, URI, and SIP version. ```go func (req *Request) StartLine() string ``` ```go fmt.Println(req.StartLine()) // Output: INVITE sip:bob@example.com SIP/2.0 ``` -------------------------------- ### Create and Append Max-Forwards Header Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md Example of creating a Max-Forwards header with a hop count limit and appending it to a request. The recommended starting value is 70, and it's decremented by each proxy. ```go maxfwd := sip.MaxForwardsHeader(70) req.AppendHeader(&maxfwd) ``` -------------------------------- ### Build INVITE Request Example Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-message.md Provides a common pattern for constructing an INVITE SIP request using sip.NewRequest and setting the destination URI. The Content-Length header is automatically set when the body is provided. ```go req := sip.NewRequest(sip.INVITE, sip.Uri{ User: "bob", Host: "example.com", }) req.SetBody(sdpOffer) // Sets Content-Length automatically client.Do(ctx, req) ``` -------------------------------- ### Create and Append Referred-By Header Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md Example of creating a Referred-By Header and appending it to a request. This header identifies the referrer. ```go referredBy := &sip.ReferredByHeader{ Address: sip.Uri{ User: "alice", Host: "atlanta.com", }, } req.AppendHeader(referredBy) ``` -------------------------------- ### ListenAndServe Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/server.md Starts listening for incoming requests on the specified network and address. ```APIDOC ## ListenAndServe ### Description Starts listening for incoming requests on the specified network and address. ### Method func (srv *Server) ListenAndServe(ctx context.Context, network string, addr string) error ### Parameters #### Path Parameters - **ctx** (context.Context) - Required - Context for cancellation - **network** (string) - Required - Transport protocol: "udp", "udp4", "udp6", "tcp", "tcp4", "tcp6", "ws", "ws4", "ws6" - **addr** (string) - Required - Local address to bind to (format: "host:port") ### Return Value - `error`: error if listener fails to start or exits ### Example ```go go srv.ListenAndServe(ctx, "udp", "127.0.0.1:5060") go srv.ListenAndServe(ctx, "tcp", "127.0.0.1:5061") go srv.ListenAndServe(ctx, "ws", "127.0.0.1:5080") ``` ``` -------------------------------- ### Create and Add Via Header Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md Example of creating a ViaHeader instance with protocol, transport, host, and port, adding a 'branch' parameter, and prepending it to a request. This is crucial for transaction identification. ```go via := &sip.ViaHeader{ ProtocolName: "SIP", ProtocolVersion: "2.0", Transport: "UDP", Host: "192.168.1.100", Port: 5060, } via.Params.Add("branch", "z9hG4bK-123") req.PrependHeader(via) ``` -------------------------------- ### Create Authorization Header Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md Example of creating an Authorization header for basic and digest authentication. This header is typically set by a DoDigestAuth() function. ```go // Set by DoDigestAuth() authHeader := sip.NewHeader("Authorization", "Digest username=..., realm=..., nonce=...") req.AppendHeader(authHeader) ``` -------------------------------- ### UAC Dialog Handling Source: https://github.com/emiago/sipgo/blob/main/README.md Example of setting up a User Agent Client (UAC) to manage SIP dialogs. This includes creating a dialog client cache, attaching handlers for incoming BYE requests, initiating an INVITE, waiting for an answer, sending an ACK, and terminating the call with BYE. ```go ua, _ := sipgo.NewUA() // Build user agent srv, _ := sipgo.NewServer(ua) // Creating server handle client, _ := sipgo.NewClient(ua) // Creating client handle contactHDR := sip.ContactHeader{ Address: sip.Uri{User: "test", Host: "127.0.0.200", Port: 5088}, } dialogCli := sipgo.NewDialogClientCache(client, contactHDR) // Attach Bye handling for dialog srv.OnBye(func(req *sip.Request, tx sip.ServerTransaction) { err := dialogCli.ReadBye(req, tx) //handle error }) // Create dialog session dialog, err := dialogCli.Invite(ctx, recipientURI, nil) defer dialog.Close() // Cleans up from dialog pool // Wait for answer err = dialog.WaitAnswer(ctx, AnswerOptions{}) // Check dialog response dialog.InviteResponse (SDP) and return ACK err = dialog.Ack(ctx) // Send BYE to terminate call err = dialog.Bye(ctx) ``` -------------------------------- ### DialogClientCache Constructor Example Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialogs.md Creates a dialog cache for UAC dialogs. Requires a client handle and a default Contact header. ```go contact := sip.ContactHeader{ Address: sip.Uri{User: "alice", Host: "192.168.1.100", Port: 5060}, } cache := sipgo.NewDialogClientCache(client, contact) ``` -------------------------------- ### Send Simple SIP Request Source: https://github.com/emiago/sipgo/blob/main/_autodocs/configuration.md Sends a SIP request using the client. This example demonstrates a simple request where most headers are automatically built by the client. ```go // Simple request - auto-builds headers res, _ := client.Do(ctx, req) ``` -------------------------------- ### Stateful Proxy Request Forwarding Source: https://github.com/emiago/sipgo/blob/main/README.md Example of building a stateful proxy using sipgo. This involves setting up both server and client handles that share the same User Agent. Incoming requests are modified and then relayed using `client.TransactionRequest`, ensuring Via and Record-Route headers are added. ```go ua, _ := sipgo.NewUA() // Build user agent srv, _ := sipgo.NewServer(ua) // Creating server handle client, _ := sipgo.NewClient(ua) // Creating client handle srv.OnInvite(func(req *sip.Request, tx sip.ServerTransaction) { ctx := context.Background() req.SetDestination("10.1.2.3") // Change sip.Request destination // Start client transaction and relay our request. Add Via and Record-Route header clTx, err := client.TransactionRequest(ctx, req, sipgo.ClientRequestAddVia, sipgo.ClientRequestAddRecordRoute) // Send back response res := <-cltx.Responses() tx.Respond(res) }) ``` -------------------------------- ### Create and Append Refer-To Header Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md Example of creating a Refer-To Header and appending it to a request. The 'method' parameter can be added to specify the method for the referral. ```go referTo := &sip.ReferToHeader{ Address: sip.Uri{ User: "carol", Host: "chicago.com", }, } referTo.Params.Add("method", "INVITE") req.AppendHeader(referTo) ``` -------------------------------- ### Uri Endpoint Method Example Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-message.md Illustrates using the Endpoint() method to extract only the user@host[:port] portion of the URI. ```go fmt.Println(uri.Endpoint()) // Output: bob@example.com:5060 ``` -------------------------------- ### Build INVITE request Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-message.md Example of constructing an INVITE request using sip.NewRequest and setting the request body, which automatically updates the Content-Length header. ```APIDOC ## Common Patterns ### Build INVITE request ```go req := sip.NewRequest(sip.INVITE, sip.Uri{ User: "bob", Host: "example.com", }) req.SetBody(sdpOffer) // Sets Content-Length automatically client.Do(ctx, req) ``` ``` -------------------------------- ### Request.StartLine Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-message.md Retrieves only the request start line, which includes the method, request-URI, and SIP version. ```APIDOC ## Request.StartLine ### Description Retrieves only the request start line, which includes the method, request-URI, and SIP version. ### Method func (req *Request) StartLine() string ### Return Start line string ### Example ```go fmt.Println(req.StartLine()) // Output: INVITE sip:bob@example.com SIP/2.0 ``` ``` -------------------------------- ### Create and Append Content-Type Header Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md Example of creating a Content-Type header and appending it to a request, followed by setting the message body. Common values include 'application/sdp'. ```go ct := sip.ContentTypeHeader("application/sdp") req.AppendHeader(&ct) req.SetBody(sdpOffer) ``` -------------------------------- ### Create Generic SIP Header Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md Example of creating a generic SIP header for custom headers not specifically defined in the library. Use sip.NewHeader to create a new header with a name and value. ```go customHeader := sip.NewHeader("X-Custom", "value") req.AppendHeader(customHeader) ``` -------------------------------- ### Secure WebSocket (WSS) Server Source: https://github.com/emiago/sipgo/blob/main/_autodocs/configuration.md Start a secure WebSocket (WSS) server using TLS configuration. This is for encrypted WebSocket connections. ```go // WebSocket Secure (WSS) tlsConf := &tls.Config{Certificates: []tls.Certificate{cert}} go srv.ListenAndServeTLS(ctx, "ws", "127.0.0.1:5081", tlsConf) ``` -------------------------------- ### Create WWW-Authenticate Header Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md Example of creating a WWW-Authenticate header, which is a server challenge for user authentication. Similar to Proxy-Authenticate, it includes realm and nonce for Digest authentication. ```go authChallenge := sip.NewHeader("WWW-Authenticate", "Digest realm=..., nonce=...") res.AppendHeader(authChallenge) ``` -------------------------------- ### DialogServerCache Constructor Example Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialogs.md Creates a dialog cache for UAS dialogs. Requires a client handle for sending BYE and a default Contact header. ```go contact := sip.ContactHeader{ Address: sip.Uri{User: "bob", Host: "192.168.1.101", Port: 5061}, } cache := sipgo.NewDialogServerCache(client, contact) ``` -------------------------------- ### UAS Dialog Handling Source: https://github.com/emiago/sipgo/blob/main/README.md Example of setting up a User Agent Server (UAS) to manage SIP dialogs. This involves creating a dialog server cache, handling incoming INVITE requests, responding to them, and managing dialog lifecycle. It also shows how to handle ACK and BYE requests within the dialog. ```go ua, _ := sipgo.NewUA() // Build user agent srv, _ := sipgo.NewServer(ua) // Creating server handle client, _ := sipgo.NewClient(ua) // Creating client handle uasContact := sip.ContactHeader{ Address: sip.Uri{User: "test", Host: "127.0.0.200", Port: 5099}, } dialogSrv := sipgo.NewDialogServerCache(client, uasContact) srv.OnInvite(func(req *sip.Request, tx sip.ServerTransaction) { dlg, err := dialogSrv.ReadInvite(req, tx) if err != nil { return err } defer dlg.Close() // Close for cleanup from cache // handle error dlg.Respond(sip.StatusTrying, "Trying", nil) dlg.Respond(sip.StatusOK, "OK", nil) // Instead Done also dlg.State() can be used for granular state checking <-dlg.Context().Done() }) srv.OnAck(func(req *sip.Request, tx sip.ServerTransaction) { dialogSrv.ReadAck(req, tx) }) srv.OnBye(func(req *sip.Request, tx sip.ServerTransaction) { dialogSrv.ReadBye(req, tx) }) ``` -------------------------------- ### HeaderParams Type Usage Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md Demonstrates common operations on the HeaderParams type, including adding, getting, checking existence, and retrieving all parameters. ```go // Add parameter params.Add("key", "value") params.Add("branch", "z9hG4bK-123") // Get parameter value, exists := params.Get("branch") // Check existence if params.Has("transport") { // ... } // Get all allParams := params.Length() ``` -------------------------------- ### Register INVITE Request Handler Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/server.md Registers a specific handler for incoming INVITE requests. This example demonstrates sending a '100 Trying' response, followed by a '200 OK' with SDP, and waiting for the ACK. ```go srv.OnInvite(func(req *sip.Request, tx sip.ServerTransaction) { // Send 100 Trying res := sip.NewResponseFromRequest(req, 100, "Trying", nil) tx.Respond(res) // Send 200 OK with SDP body res = sip.NewResponseFromRequest(req, 200, "OK", sdpBody) tx.Respond(res) // Wait for ACK select { case <-tx.Acks(): // ACK received case <-tx.Done(): return } }) ``` -------------------------------- ### Build User Agent and Client/Server Source: https://github.com/emiago/sipgo/blob/main/README.md Demonstrates how to create a User Agent and then initialize a client and server. The client can be configured with a specific hostname and port. ```go ua, _ := sipgo.NewUA() // Build user agent default ua.Close() client, _ := sipgo.NewClient(ua, sipgo.WithClientHostname("127.0.0.1"), sipgo.WithClientPort(5060)) server, _ := sipgo.NewServer(ua) ``` -------------------------------- ### Create Proxy-Authenticate Header Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md Example of creating a Proxy-Authenticate header, which is a server challenge for proxy authentication. It typically includes realm and nonce information for Digest authentication. ```go authChallenge := sip.NewHeader("Proxy-Authenticate", "Digest realm=..., nonce=...") res.AppendHeader(authChallenge) ``` -------------------------------- ### DialogClientSession WaitAnswer Example Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialogs.md Waits for the final response to an INVITE request and processes it. Use this after initiating an INVITE to handle the server's response and establish the dialog. ```go dialog, _ := dialogUA.Invite(ctx, recipientURI, sdpOffer) err := dialog.WaitAnswer(ctx, sipgo.AnswerOptions{}) if err != nil { log.Fatal(err) } // Now dialog is established ``` -------------------------------- ### Initialize sipgo User Agent and Server/Client Source: https://github.com/emiago/sipgo/blob/main/_autodocs/README.md Sets up the core sipgo User Agent, and then initializes a server and/or client instance. Includes error handling and deferred closing. ```go // 1. Create User Agent ua, err := sipgo.NewUA(options...) if err != nil { log.Fatal(err) } deffer ua.Close() // 2. Create Server and/or Client srv, _ := sipgo.NewServer(ua, options...) client, _ := sipgo.NewClient(ua, options...) ``` -------------------------------- ### Create and Append CSeq Header Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md Example of creating a CSeq header with a sequence number and method, then appending it to a request. The sequence number must be incremented for each new transaction within a dialog. ```go cseq := &sip.CSeqHeader{ SeqNo: 314159, MethodName: sip.INVITE, } req.AppendHeader(cseq) ``` -------------------------------- ### Create and Append Contact Header Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md Example of creating a Contact header with display name, address, and parameters, then appending it to a request. The 'expires' parameter is commonly used with REGISTER requests. ```go contact := &sip.ContactHeader{ DisplayName: "Alice's Phone", Address: sip.Uri{ User: "alice", Host: "pc33.atlanta.com", Port: 5060, }, } contact.Params.Add("expires", "3600") req.AppendHeader(contact) ``` -------------------------------- ### Handle Incoming INVITE with Dialog Server Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialogs.md This snippet shows how to set up a dialog server to handle incoming INVITE requests. It demonstrates creating a dialog, responding with provisional and final responses, and managing the dialog lifecycle. ```go contact := sip.ContactHeader{Address: myURI} dialogUA := sipgo.NewDialogServerCache(client, contact) srv.OnInvite(func(req *sip.Request, tx sip.ServerTransaction) { dialog, err := dialogUA.ReadInvite(req, tx) if err != nil { tx.Respond(sip.NewResponseFromRequest(req, 400, "Bad Request", nil)) return } defer dialog.Close() dialog.Respond(100, "Trying", nil) dialog.Respond(180, "Ringing", nil) dialog.Respond(200, "OK", sdpAnswer) <-dialog.Context().Done() }) ``` -------------------------------- ### Basic SIP Server Source: https://github.com/emiago/sipgo/blob/main/_autodocs/README.md Sets up a basic SIP server that listens on UDP and TCP. It handles incoming INVITE requests, responding with 100 Trying and then 200 OK. ```go package main import ( "context" "github.com/emiago/sipgo" "github.com/emiago/sipgo/sip" ) func main() { ua, _ := sipgo.NewUA() defer ua.Close() srv, _ := sipgo.NewServer(ua) srv.OnInvite(func(req *sip.Request, tx sip.ServerTransaction) { res := sip.NewResponseFromRequest(req, 100, "Trying", nil) tx.Respond(res) res = sip.NewResponseFromRequest(req, 200, "OK", nil) tx.Respond(res) }) ctx := context.Background() go srv.ListenAndServe(ctx, "udp", "127.0.0.1:5060") go srv.ListenAndServe(ctx, "tcp", "127.0.0.1:5061") <-ctx.Done() } ``` -------------------------------- ### Get SIP Headers from Request Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md Demonstrates how to retrieve specific SIP headers (e.g., From, To, Via, CSeq) or all headers with a given name from a Request object. Useful for parsing incoming SIP messages. ```go // Get first occurrence of header from := req.From() // *FromHeader to := req.To() // *ToHeader via := req.Via() // *ViaHeader (topmost) cseq := req.CSeq() // *CSeqHeader callid := req.CallID() // *CallIDHeader contact := req.Contact() // *ContactHeader maxfwd := req.MaxForwards() // *MaxForwardsHeader route := req.Route() // *RouteHeader rroute := req.RecordRoute() // *RecordRouteHeader cl := req.ContentLength() // *ContentLengthHeader ct := req.ContentType() // *ContentTypeHeader // Get all headers with name (case-insensitive) allVias := req.GetHeaders("via") allRoutes := req.GetHeaders("route") // Get first header with name authHeader := req.GetHeader("authorization") ``` -------------------------------- ### Test SIP Call Failure with Busy Status Source: https://github.com/emiago/sipgo/wiki/E2E-testing This example demonstrates how to test for a specific non-200 SIP response, such as 'Busy Here', when a call fails. It checks if the returned error is of type `sipgox.DialResponseError` and verifies the status code. ```go func TestBusyCall(t *testing.T) { // ... _, err := phone.Dial(...) e, ok := err.(*sipgox.DialResponseError) assert.True(t, ok) assert.Equal(t, sip.StatusBusyHere, e.StatusCode()) } ``` -------------------------------- ### DialogClientSession Do Example Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialogs.md Sends a subsequent request within an established dialog and waits for a response. This method automatically sets necessary dialog headers like From, To, CSeq, and Call-ID, and increments the CSeq number. ```go infoReq := sip.NewRequest(sip.INFO, sip.Uri{Host: "example.com"}) res, _ := dialog.Do(ctx, infoReq) ``` -------------------------------- ### Configure User Agent with Options Source: https://github.com/emiago/sipgo/blob/main/_autodocs/configuration.md Sets up a new User Agent instance using functional options for customization. Includes options for User Agent name, hostname, DNS resolver, TLS configuration, and transport layer settings. ```go ua, err := sipgo.NewUA( sipgo.WithUserAgent("MyApp/1.0"), sipgo.WithUserAgentHostname("sip.example.com"), sipgo.WithUserAgentDNSResolver(customResolver), sipgo.WithUserAgenTLSConfig(tlsConf), sipgo.WithUserAgentTransactionLayerOptions(txOpts...), sipgo.WithUserAgentTransportLayerOptions(tpOpts...), ) ``` -------------------------------- ### Create and Use a UAC for Simple SIP Call Source: https://github.com/emiago/sipgo/wiki/E2E-testing This snippet shows how to set up a User Agent Client (UAC) using sipgo and sipgox to initiate a simple SIP call. It demonstrates dialing a recipient and handling the call's completion or hangup. ```go import ( "context" "testing" "time" "github.com/emiago/sipgo" "github.com/emiago/sipgo/sip" "github.com/emiago/sipgox" "github.com/stretchr/testify/require" ) func TestSimpleCall(t *testing.T) { ctx, _ := context.WithTimeout(context.Background(), 32*time.Second) // First create our user agent uac, _ := sipgo.NewUA(sipgo.WithUserAgent("TestUAC")) defer uac.Close() // Using sipgox attach user agent to Phone uacPhone := sipgox.NewPhone(uac) // Start dial on sip:123456789@asterisk.xy:5060 // We use context to control duration of dialin recipient := sip.Uri{User: "123456789", Host: "asterisk.xy", Port: 5060} dialog, err := uacPhone.Dial( ctx, recipient, sipgox.DialOptions{}, ) require.NoError(t, err) t.Log("UAC answered") select { case <-dialog.Done(): // Other side hanguped case <-time.After(3 * time.Second): // After 3 second we hangup dialog.Hangup(ctx) } } ``` -------------------------------- ### Configure Client with Options Source: https://github.com/emiago/sipgo/blob/main/_autodocs/configuration.md Initializes a new SIP client with options for hostname, port, NAT awareness, and a custom logger. This configures the client's default behavior for outgoing requests. ```go client, err := sipgo.NewClient(ua, sipgo.WithClientHostname("192.168.1.100"), sipgo.WithClientPort(5060), sipgo.WithClientNAT(), sipgo.WithClientLogger(logger), ) ``` -------------------------------- ### DialogClientSession Bye Example Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialogs.md Sends a BYE request to terminate the dialog. This method should be called when the call needs to be ended from the client side. The example also shows how to wait for the dialog context to be done, indicating the dialog has ended. ```go dialog.Bye(ctx) <-dialog.Context().Done() ``` -------------------------------- ### Configure Server with Logger Option Source: https://github.com/emiago/sipgo/blob/main/_autodocs/configuration.md Initializes a new SIP server instance with a custom logger. The logger option allows for detailed logging of server activities. ```go srv, err := sipgo.NewServer(ua, sipgo.WithServerLogger(logger), ) ``` -------------------------------- ### ListenAndServeTLS Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/server.md Starts listening for encrypted connections (TLS or WSS) on the specified address. ```APIDOC ## ListenAndServeTLS ### Description Starts listening for encrypted connections (TLS or WSS) on the specified address. ### Method func (srv *Server) ListenAndServeTLS(ctx context.Context, network string, addr string, conf *tls.Config) error ### Parameters #### Path Parameters - **ctx** (context.Context) - Required - Context for cancellation - **network** (string) - Required - Transport protocol: "tcp", "tcp4", "tcp6", "ws" (converted to "tls" or "wss") - **addr** (string) - Required - Local address to bind to (format: "host:port") - **conf** (*tls.Config) - Required - TLS configuration with certificates ### Return Value - `error`: error if listener fails to start or exits ### Example ```go tlsConf := &tls.Config{ Certificates: []tls.Certificate{cert}, } go srv.ListenAndServeTLS(ctx, "tcp", "127.0.0.1:5061", tlsConf) go srv.ListenAndServeTLS(ctx, "ws", "127.0.0.1:5081", tlsConf) ``` ``` -------------------------------- ### Send SIP Requests with Client Source: https://github.com/emiago/sipgo/blob/main/_autodocs/README.md Initiates a SIP request using the client instance. Includes creating the request and sending it, with basic error checking. ```go // 5. Send requests (Client) req := sip.NewRequest(sip.INVITE, uri) res, err := client.Do(ctx, req) ``` -------------------------------- ### Basic SIP Client Source: https://github.com/emiago/sipgo/blob/main/_autodocs/README.md Creates a basic SIP client that sends an INVITE request to a specified destination and prints the status code of the response. ```go package main import ( "context" "github.com/emiago/sipgo" "github.com/emiago/sipgo/sip" ) func main() { ua, _ := sipgo.NewUA() defer ua.Close() client, _ := sipgo.NewClient(ua) req := sip.NewRequest(sip.INVITE, sip.Uri{ User: "bob", Host: "example.com", }) res, _ := client.Do(context.Background(), req) println(res.StatusCode) } ``` -------------------------------- ### Create and Manage Client Transaction Source: https://github.com/emiago/sipgo/blob/main/README.md Demonstrates creating a client transaction, sending a request, and then handling responses or transaction termination. Remember to terminate the client transaction for cleanup. ```go ctx := context.Background() client, _ := sipgo.NewClient(ua) // Creating client handle req := sip.NewRequest(sip.INVITE, sip.Uri{User:"bob", Host: "example.com"}) tx, err := client.TransactionRequest(ctx, req) // Send request and get client transaction handle defer tx.Terminate() // Client Transaction must be terminated for cleanup ... select { case res := <-tx.Responses(): // Handle responses case <-tx.Done(): // Wait for termination return } ``` -------------------------------- ### Get SIP RequestMethod as String Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-message.md The String method for RequestMethod returns the method name as a string. ```go func (r RequestMethod) String() string ``` -------------------------------- ### Run SIP Server Source: https://github.com/emiago/sipgo/blob/main/example/register/README.md Configure the list of username:password with the -u parameter. The server listens on the specified IP and port. ```sh go run ./server -u "alice:alice,bob:bob" -ip 127.0.0.10:5060 ``` -------------------------------- ### Create and Configure a New SIP Server Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/server.md Creates a new SIP server handle and registers handlers for incoming requests. Ensure UserAgent is closed separately after the server. ```go ua, _ := sipgo.NewUA() defers ua.Close() srv, _ := sipgo.NewServer(ua) // Register handlers ``` ```go srv.OnInvite(func(req *sip.Request, tx sip.ServerTransaction) { res := sip.NewResponseFromRequest(req, sip.StatusTrying, "Trying", nil) tx.Respond(res) }) srv.OnAck(func(req *sip.Request, tx sip.ServerTransaction) { // Handle ACK }) // Start listening ctx := context.Background() go srv.ListenAndServe(ctx, "udp", "127.0.0.1:5060") ``` -------------------------------- ### Digest Authentication Retry Source: https://github.com/emiago/sipgo/blob/main/_autodocs/errors.md Example of retrying a request using Digest Authentication if an unauthorized response is received. ```go res, err := client.Do(ctx, req) if res != nil && res.StatusCode == sip.StatusUnauthorized { res, err = client.DoDigestAuth(ctx, req, res, sipgo.DigestAuth{ Username: "user", Password: "pass", }) } ``` -------------------------------- ### Wrapping Transaction Errors Source: https://github.com/emiago/sipgo/blob/main/_autodocs/errors.md Provides examples of wrapping transaction errors with additional context for transport and timeout issues. ```go func wrapTransportError(err error) error { return fmt.Errorf("%s. %w", err.Error(), ErrTransactionTransport) } func wrapTimeoutError(err error) error { return fmt.Errorf("%s. %w", err.Error(), ErrTransactionTimeout) } ``` -------------------------------- ### HeaderParams Type Source: https://github.com/emiago/sipgo/blob/main/_autodocs/types.md A container for header and URI parameters, supporting methods for adding, getting, and checking the number of parameters. ```go type HeaderParams []struct { Key string Value string } ``` -------------------------------- ### DialogClientSession.Ack Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialogs.md Sends an ACK request to acknowledge the final response of an INVITE transaction, completing the call setup process. ```APIDOC ## DialogClientSession.Ack ### Description Sends ACK to complete INVITE transaction. ### Method (Implicitly called after successful WaitAnswer) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```go dialog.Ack(ctx) ``` ### Response #### Success Response (ACK is typically a transactional message with no significant response body) #### Response Example (Not applicable) ERROR HANDLING: - Returns error if ACK send fails ``` -------------------------------- ### Build User Agent and Server/Client Handles Source: https://github.com/emiago/sipgo/blob/main/README.md Build a user agent and create server or client handles for managing SIP requests and responses. The server handle listens for incoming requests, while the client handle initiates outgoing requests. Supports UDP, TCP, and WS transports. ```go ua, _ := sipgo.NewUA() // Build user agent srv, _ := sipgo.NewServer(ua) // Creating server handle for ua client, _ := sipgo.NewClient(ua) // Creating client handle for ua srv.OnInvite(inviteHandler) srv.OnAck(ackHandler) srv.OnBye(byeHandler) // For registrars // srv.OnRegister(registerHandler) ctx, _ := signal.NotifyContext(ctx, os.Interrupt) go srv.ListenAndServe(ctx, "udp", "127.0.0.1:5060") go srv.ListenAndServe(ctx, "tcp", "127.0.0.1:5061") go srv.ListenAndServe(ctx, "ws", "127.0.0.1:5080") <-ctx.Done() ``` -------------------------------- ### Handle Incoming INVITE Request Source: https://github.com/emiago/sipgo/blob/main/README.md Shows how to handle an incoming INVITE request on the server. It includes sending a provisional response (100 Trying) and a final response (200 OK), and waiting for transaction termination. ```go // Incoming request srv.OnInvite(func(req *sip.Request, tx sip.ServerTransaction) { // Send provisional res := sip.NewResponseFromRequest(req, 100, "Trying", nil) tx.Respond(res) // Send OK. TODO: some body like SDP res := sip.NewResponseFromRequest(req, 200, "OK", body) tx.Respond(res) // Wait transaction termination. select { case m := <-tx.Acks(): // Handle ACK for response . ACKs on 2xx are send as different request case <-tx.Done(): // Signal transaction is done. // Check any errors with tx.Err() to have more info why terminated return } // terminating handler terminates Server transaction automaticaly }) ``` -------------------------------- ### Get SIP Response as String Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-message.md The String method returns the full SIP response formatted according to RFC 3261. ```go func (res *Response) String() string ``` -------------------------------- ### Create and Add From Header Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md Illustrates creating a FromHeader with a display name and SIP address, adding a 'tag' parameter, and appending it to a request. The 'tag' is mandatory for responses and in-dialog requests. ```go from := &sip.FromHeader{ DisplayName: "Alice ", Address: sip.Uri{ User: "alice", Host: "atlanta.com", }, } from.Params.Add("tag", "1928301774") req.AppendHeader(from) ``` -------------------------------- ### Create a new SIP Client Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/client.md Use NewClient to create a SIP client handle. It can be configured with a fixed hostname and port for connection reuse, or operate in stateless mode. ```go func NewClient(ua *UserAgent, options ...ClientOption) (*Client, error) ``` ```go ua, _ := sipgo.NewUA() defer ua.Close() // Basic client client, _ := sipgo.NewClient(ua) // Client with fixed address (connection reuse) client, _ := sipgo.NewClient(ua, sipgo.WithClientHostname("192.168.1.100"), sipgo.WithClientPort(5060), ) // Send INVITE req := sip.NewRequest(sip.INVITE, sip.Uri{User: "bob", Host: "example.com"}) res, err := client.Do(context.Background(), req) ``` -------------------------------- ### HeaderParams Type Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md A container for header parameters and URI parameters, providing methods to add, get, check existence, and retrieve all parameters. ```APIDOC ## HeaderParams Type ### Description Container for header parameters and URI parameters: ### Methods - **Add(key, value)**: Adds a parameter. - **Get(key)**: Retrieves the value of a parameter. - **Has(key)**: Checks if a parameter exists. - **Length()**: Returns the number of parameters. ### Example ```go // Add parameter params.Add("key", "value") params.Add("branch", "z9hG4bK-123") // Get parameter value, exists := params.Get("branch") // Check existence if params.Has("transport") { // ... } // Get all allParams := params.Length() ``` ``` -------------------------------- ### Get Transaction Termination Error Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/server.md Retrieves any error that caused the server transaction to terminate. Returns nil if the transaction terminated cleanly. ```go func (tx sip.ServerTransaction) Err() error ``` -------------------------------- ### Handle INVITE Transaction (2xx Responses) Source: https://github.com/emiago/sipgo/blob/main/_autodocs/README.md Demonstrates how to process responses from an INVITE transaction, distinguishing between provisional (1xx) and success (200) responses, and handling transaction completion. ```go select { case res := <-tx.Responses(): if res.IsProvisional() { // 1xx - continue } else if res.IsSuccess() { // 200 - send ACK } case <-tx.Done(): // Transaction ended } ``` -------------------------------- ### Create and Append Record-Route Header Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md Example of creating a Record-Route Header and appending it to a request. The 'lr' parameter indicates a loose routing proxy. ```go rrh := &sip.RecordRouteHeader{ Address: sip.Uri{ Host: "proxy.example.com", Port: 5060, UriParams: sip.HeaderParams{ {"transport", "udp"}, {"lr", ""}, }, }, } req.AppendHeader(rrh) ``` -------------------------------- ### Create and Append Route Header Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md Example of creating a Route Header and appending it to a request. The 'lr' parameter indicates a loose routing proxy. ```go route := &sip.RouteHeader{ Address: sip.Uri{ Host: "proxy.example.com", UriParams: sip.HeaderParams{ {"transport", "tcp"}, {"lr", ""}, // Loose routing }, }, } req.AppendHeader(route) ``` -------------------------------- ### Run SIP Client Source: https://github.com/emiago/sipgo/blob/main/example/register/README.md Run the client with specified username, password, and server address. Supports multiple client registrations. ```sh go run ./client -u alice -p alice -srv 127.0.0.10:5060 ``` ```sh go run ./client -u bob -p bob -srv 127.0.0.10:5060 ``` -------------------------------- ### DialogClientSession Ack Example Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialogs.md Sends an ACK request to complete the INVITE transaction. This is typically called after receiving a successful final response to an INVITE. ```go dialog.Ack(ctx) ``` -------------------------------- ### Simple UAC Call Flow Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialogs.md Demonstrates the typical lifecycle for a User Agent Client (UAC) initiating a call. Ensure proper error handling and resource cleanup with defer. ```go dialogUA := sipgo.NewDialogClientCache(client, contactHDR) dialog, err := dialogUA.Invite(ctx, recipientURI, sdpOffer) if err != nil { log.Fatal(err) } defer dialog.Close() err = dialog.WaitAnswer(ctx, sipgo.AnswerOptions{}) if err != nil { log.Fatal(err) } dialog.Ack(ctx) // Dialog is established select { case <-time.After(30*time.Second): dialog.Bye(ctx) case <-dialog.Context().Done(): // Remote party hung up } ``` -------------------------------- ### Get SIP Response Transport Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-message.md The Transport method returns the transport protocol (e.g., UDP, TCP, TLS) specified in the Via header of the response. ```go func (res *Response) Transport() string ``` -------------------------------- ### Dialog.Context: Get Cancellable Context Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialogs.md Returns a context that is automatically cancelled when the dialog ends. Useful for managing goroutines tied to the dialog's lifecycle. ```go func (d *Dialog) Context() context.Context ``` ```go select { case <-dialog.Context().Done(): // Dialog ended case <-time.After(60*time.Second): // Timeout } ``` -------------------------------- ### Create a New User Agent Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/user-agent.md Creates a new User Agent, initializing transport and transaction layers. Can be configured with variadic options. ```go ctx := context.Background() // Create a basic User Agent ua, err := sipgo.NewUA() if err != nil { log.Fatal(err) } defer ua.Close() // Create with custom options ua, err := sipgo.NewUA( sipgo.WithUserAgent("MyApp/1.0"), sipgo.WithUserAgentHostname("sip.example.com"), ) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Request Source Method Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-message.md Returns the source address in 'host:port' format, obtained from the Via header or set via SetSource(). ```go func (req *Request) Source() string ``` -------------------------------- ### Basic SIP Request Creation Source: https://github.com/emiago/sipgo/blob/main/_autodocs/errors.md Illustrates the creation of a new SIP request, often a precursor to operations that might involve parsing errors. ```go req := sip.NewRequest(sip.INVITE, sip.Uri{ User: "bob", Host: "example.com", }) // Errors from parsing typically occur in transport layer // when receiving messages from network ``` -------------------------------- ### Create and Append Expires Header Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md Example of creating an Expires header with a duration in seconds and appending it to a REGISTER request. The default value is 3600 seconds if not explicitly set. ```go expires := sip.ExpiresHeader(3600) // 1 hour req.AppendHeader(&expires) ``` -------------------------------- ### DialogClientSession TransactionRequest Example Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialogs.md Sends a subsequent request within a dialog and returns the client transaction for advanced control. Use this when you need to manage the transaction lifecycle explicitly, such as terminating it. ```go req := sip.NewRequest(sip.INFO, uri) tx, _ := dialog.TransactionRequest(ctx, req) defer tx.Terminate() ```