### Start OpenSIPS Docker image Source: https://github.com/emiago/sipgo/blob/main/example/proxysip/docker/opensips/README.md Starts the OpenSIPS Docker image. ```bash make start ``` -------------------------------- ### ServeTLS Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-transport.md Starts serving TLS on the provided listener. ```APIDOC ## ServeTLS ### Description Starts serving TLS on the provided listener. ### Signature func (l *TransportLayer) ServeTLS(c net.Listener) error ### Parameters - **c** (net.Listener) - Required - The TLS listener to serve on. ### Returns - **error** - An error if serving fails. ``` -------------------------------- ### Init Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-transaction.md Initializes the server transaction, starting timers and selecting the appropriate FSM state. ```APIDOC ## Init ### Description Starts the G/I/J timers for unreliable transports and, for INVITEs, a Timer_1xx (200 ms) that auto-sends 100 Trying via NewResponseFromRequest. Selects FSM (INVITE → inviteStateProcceeding, else stateTrying). ### Method Init ### Signature func (tx *ServerTx) Init() error ### Returns - error - An error if initialization fails. ``` -------------------------------- ### UAS example: handle INVITE, ACK, and BYE with DialogServerSession Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialog-server.md UAS example from the README showing how to handle INVITE, ACK, and BYE requests using a DialogServerSession. It reads the invite, responds with Trying and OK, waits for the dialog context to be done, and then reads ACK and BYE requests. ```go srv.OnInvite(func(req *sip.Request, tx sip.ServerTransaction) { dlg, err := dialogSrv.ReadInvite(req, tx) if err != nil { return err } defer dlg.Close() dlg.Respond(sip.StatusTrying, "Trying", nil) dlg.Respond(sip.StatusOK, "OK", nil) <-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) }) ``` -------------------------------- ### ServeTCP Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-transport.md Starts serving TCP on the provided listener. ```APIDOC ## ServeTCP ### Description Starts serving TCP on the provided listener. ### Signature func (l *TransportLayer) ServeTCP(c net.Listener) error ### Parameters - **c** (net.Listener) - Required - The TCP listener to serve on. ### Returns - **error** - An error if serving fails. ``` -------------------------------- ### ServeWSS Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-transport.md Starts serving WebSocket Secure (WSS) on the provided listener. ```APIDOC ## ServeWSS ### Description Starts serving WebSocket Secure (WSS) on the provided listener. ### Signature func (l *TransportLayer) ServeWSS(c net.Listener) error ### Parameters - **c** (net.Listener) - Required - The WSS listener to serve on. ### Returns - **error** - An error if serving fails. ``` -------------------------------- ### ServeWS Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-transport.md Starts serving WebSocket (WS) on the provided listener. ```APIDOC ## ServeWS ### Description Starts serving WebSocket (WS) on the provided listener. ### Signature func (l *TransportLayer) ServeWS(c net.Listener) error ### Parameters - **c** (net.Listener) - Required - The WebSocket listener to serve on. ### Returns - **error** - An error if serving fails. ``` -------------------------------- ### Add and get sip.HeaderParams Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-header-params.md Shows how to add parameters to headers and URI params, including value-less parameters (rport) and retrieving a value with Get. ```go contact := &sip.ContactHeader{ Address: sip.Uri{User: "test", Host: "127.0.0.200", Port: 5088}, } contact.Params.Add("expires", "3600") via := inviteReq.Via() via.Params.Add("rport", "") // value-less param via.Params.Add("branch", sip.GenerateBranchN(16)) if transport, ok := recipient.UriParams.Get("transport"); ok { req.SetTransport(transport) } ``` -------------------------------- ### Create UserAgent, Client, and Server Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/user-agent.md Usage example from the README showing how to create a UserAgent with NewUA, then create a Client and Server that share the same UserAgent. The UserAgent is closed with defer ua.Close(). ```go ua, _ := sipgo.NewUA() // Build user agent defer ua.Close() client, _ := sipgo.NewClient(ua, sipgo.WithClientHostname("127.0.0.1"), sipgo.WithClientPort(5060)) srv, _ := sipgo.NewServer(ua) ``` -------------------------------- ### UAC example: Invite, WaitAnswer, Ack, Bye with DialogClientCache Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialog-client.md Shows a typical UAC flow: create a UA and client, set up a dialog client cache, handle incoming BYE with ReadBye, then send INVITE, wait for answer, send ACK, and terminate with BYE. ```go ua, _ := sipgo.NewUA() client, _ := sipgo.NewClient(ua) contactHDR := sip.ContactHeader{Address: sip.Uri{User: "test", Host: "127.0.0.200", Port: 5088}} dialogCli := sipgo.NewDialogClientCache(client, contactHDR) srv.OnBye(func(req *sip.Request, tx sip.ServerTransaction) { err := dialogCli.ReadBye(req, tx) }) dialog, err := dialogCli.Invite(ctx, recipientURI, nil) defer dialog.Close() err = dialog.WaitAnswer(ctx, sipgo.AnswerOptions{}) err = dialog.Ack(ctx) err = dialog.Bye(ctx) ``` -------------------------------- ### Proxy forwarding with ClientRequestAddVia and ClientRequestAddRecordRoute Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/client.md Proxy forwarding example from README / example/proxysip. It changes the request destination, then sends it via TransactionRequest with ClientRequestAddVia and ClientRequestAddRecordRoute options, and forwards the response back. ```go srv.OnInvite(func(req *sip.Request, tx sip.ServerTransaction) { ctx := context.Background() req.SetDestination("10.1.2.3") // Change sip.Request destination clTx, err := client.TransactionRequest(ctx, req, sipgo.ClientRequestAddVia, sipgo.ClientRequestAddRecordRoute) ... res := <-clTx.Responses() tx.Respond(res) }) ``` -------------------------------- ### Build UAS/UAC with server and client handles Source: https://github.com/emiago/sipgo/blob/main/README.md Build a user agent with server and client handles, register handlers for INVITE, ACK, and BYE (or REGISTER for registrars), and start listeners on UDP, TCP, and WebSocket transports. The server handle reacts to incoming requests and the client handle creates transaction requests. ```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() ``` -------------------------------- ### Server transaction usage example Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-transaction.md Shows how to handle an INVITE request using a ServerTransaction: respond with 100 Trying and 200 OK, then wait for the ACK or transaction done. ```go 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", body) tx.Respond(res) select { case m := <-tx.Acks(): // ACK for 2xx comes as a different request case <-tx.Done(): return } }) ``` -------------------------------- ### ServeUDP Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-transport.md Starts serving UDP on the provided PacketConn and adds the port to the listenPorts list for UDP. ```APIDOC ## ServeUDP ### Description Listen + add port to listenPorts["udp"]. ### Signature func (l *TransportLayer) ServeUDP(c net.PacketConn) error ### Parameters - **c** (net.PacketConn) - Required - The UDP packet connection to serve on. ### Returns - **error** - An error if serving fails. ``` -------------------------------- ### ParseSIP usage example Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-parser.md Shows how to create a new Parser and parse raw SIP bytes with ParseSIP. Handles errors such as ErrMessageTooLarge, ErrParseEOF, and other parse errors. ```go parser := sip.NewParser() msg, err := parser.ParseSIP(rawBytes) if err != nil { // handle ErrMessageTooLarge / ErrParseEOF / parse errors } ``` -------------------------------- ### Run SIP registration server Source: https://github.com/emiago/sipgo/blob/main/example/register/README.md Starts the SIP registration server with a list of username:password pairs configured via the -u parameter. The -ip flag sets the server's IP address and port. ```sh go run ./server -u "alice:alice,bob:bob" -ip 127.0.0.10:5060 ``` -------------------------------- ### Server Transaction Usage Example Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-transaction.md Example of using a server transaction in a SIP server handler. ```APIDOC ## Server Transaction Usage Example ### Description Example of using a server transaction in a SIP server handler. ### Code ```go 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", body) tx.Respond(res) select { case m := <-tx.Acks(): // ACK for 2xx comes as a different request case <-tx.Done(): return } }) ``` ``` -------------------------------- ### Customize UserAgent with DNS and connection reuse options Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/user-agent.md Shows how to create a new UserAgent with custom name, hostname, and transport layer options for connection reuse and SRV DNS lookup. The example logs an error and returns if NewUA fails. ```go ua, err := sipgo.NewUA( sipgo.WithUserAgent("SIPGO"), sipgo.WithUserAgentHostname("sip.example.com"), sipgo.WithUserAgentTransportLayerOptions( sip.WithTransportLayerConnectionReuse(true), sip.WithTransportLayerDNSLookupSRV(true), ), ) if err != nil { log.Error("Fail to setup user agent", "error", err) return } ``` -------------------------------- ### Build stateful SIP proxy with sipgo Source: https://github.com/emiago/sipgo/blob/main/README.md Builds a stateful SIP proxy by combining a server and client handle that share the same user agent (ua). The OnInvite handler changes the request destination, starts a client transaction with Via and Record-Route headers, and relays the response back to the server transaction. ```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) }) ``` -------------------------------- ### Client.TransactionRequest Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/client.md Starts a client transaction and returns the transaction handle. Adds missing headers automatically unless options are provided. ```APIDOC ## Client.TransactionRequest ### Description Starts a client transaction and returns the `sip.ClientTransaction` handle. With no options, `ClientRequestBuild` behavior is applied implicitly; otherwise each option in `options` runs `o(c, req)`. If `c.TxRequester != nil` it is used instead of the transaction layer. Warns (log only) when `sip.IsReliable(req.Transport())` and `req.ContentLength() == nil`. ### Method `func (c *Client) TransactionRequest(ctx context.Context, req *sip.Request, options ...ClientRequestOption) (sip.ClientTransaction, error)` ### Parameters - `ctx` (context.Context) - Required - The context for the transaction. - `req` (*sip.Request) - Required - The SIP request to send. - `options` (...ClientRequestOption) - Optional - Client request options. ### Returns - (sip.ClientTransaction, error) - The client transaction handle or an error. ### Errors - Returns `nil, fmt.Errorf("ACK request must be sent directly through transport. Use WriteRequest")` if `req.IsAck()`. ### Notes - Missing headers added for you (unless options are passed): `Via` (from `clientRequestCreateVia`), `From` (+ random `tag`), `To`, `Call-ID` (random UUID), `CSeq` (random 1..32767), `Max-Forwards: 70`. If `c.connAddr.IP != nil` the local address is copied to `req.Laddr`. - By default the request is **not** cloned and is populated with missing headers — call `req.Clone()` first when you need to retry with a pristine request. ``` -------------------------------- ### Get Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-header-params.md Returns the value of the first matching key and a boolean indicating existence. ```APIDOC ## Get ### Description Returns the value of the first matching key and true if found, otherwise empty string and false. ### Method Signature `func (hp HeaderParams) Get(key string) (string, bool)` ### Parameters - **key** (string) - Required - The key to look up. ### Returns - **string** - The value of the first matching key. - **bool** - True if the key exists, false otherwise. ### Example ```go params := sip.NewParams() params.Add("transport", "udp") if val, ok := params.Get("transport"); ok { // val == "udp" } ``` ``` -------------------------------- ### Send SIP request with Client.Do Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/client.md Sends a SIP request using the Client.Do method, which returns the first non-provisional response. The example shows how to handle errors and inspect the final response status code. ```go req := sip.NewRequest(sip.INVITE, sip.Uri{User: "bob", Host: "example.com"}) res, err := client.Do(ctx, req) if err != nil { // transaction done with error, or context canceled } switch res.StatusCode { case sip.StatusOK: case sip.StatusBusyHere: } ``` -------------------------------- ### Do method example: sending INFO request within dialog Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialog-client.md Shows how to use the Do method to send an HTTP-like request/response within the dialog. It calls TransactionRequest and returns the first non-provisional response. Note that it does not provide INVITE CANCEL as it could be REINVITE; use WaitAnswer when creating initial INVITE to have CANCEL sending. ```go req := sip.NewRequest(sip.INFO, recipient) res, err := dialog.Do(ctx, req) ``` -------------------------------- ### SIPDebugTracer Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-core.md Installs a custom SIP tracer that replaces the default stderr dump for raw SIP message logging. ```APIDOC ## SIPDebugTracer ### Description Installs a custom tracer; when set it replaces the stderr dump in logSIPRead/logSIPWrite. ### Function Signature `func SIPDebugTracer(t SIPTracer)` ### Parameters - **t** (SIPTracer) - Required - The custom tracer to install. ### Related Types - **SIPTracer** interface with methods: - `SIPTraceRead(transport string, laddr string, raddr string, sipmsg []byte)` - `SIPTraceWrite(transport string, laddr string, raddr string, sipmsg []byte)` ``` -------------------------------- ### ListenAndServeTLS with tls.Config Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/server.md Configures a TLS listener for the server. The network must be tcp, ws, tcp4, ws4, tcp6, or ws6; otherwise sip.ErrTransportNotSuported is returned. The conf is a *tls.Config, and the example shows setting Certificates and RootCAs. ```go conf := &tls.Config{ Certificates: []tls.Certificate{cert}, RootCAs: roots, } srv.ListenAndServeTLS(ctx, "tcp", "127.0.0.1:5061", conf) ``` -------------------------------- ### ParseUri example for SIP URI parsing (parse_uri.go:15) Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-uri.md Parses a SIP URI string into a Uri value. Returns an error for empty strings (errors.New("empty URI")) or parse failures from the FSM; wildcard '*' in a request line is rejected at the request-line level (parser.go:415). After parsing, fields like User, Host, and Port are populated as shown. ```go uri := sip.Uri{} if err := sip.ParseUri("sip:alice@example.com:5060;transport=tcp", &uri); err != nil { return err } // uri.User == "alice", uri.Host == "example.com", uri.Port == 5060 ``` -------------------------------- ### Creating a Client with options Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/client.md Creates a new Client with options to set the hostname, port, and enable NAT support (rport parameter). ```go client, err := sipgo.NewClient(ua, sipgo.WithClientHostname("127.0.0.1"), sipgo.WithClientPort(5060), sipgo.WithClientNAT(), ) ``` -------------------------------- ### Create server and register INVITE handler Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/server.md Shows how to create a server with a custom logger and register an INVITE handler. The server is wired to the transaction layer via OnRequest, and the noRouteHandler defaults to responding 405 Method Not Allowed. ```go ua, _ := sipgo.NewUA() srv, err := sipgo.NewServer(ua, sipgo.WithServerLogger(myLogger)) if err != nil { return err } srv.OnInvite(func(req *sip.Request, tx sip.ServerTransaction) { // handle }) ``` -------------------------------- ### WriteMsg Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-transport.md Sends a message using the transport and destination specified in the message. Requests get a client connection, responses get a server connection. ```APIDOC ## WriteMsg ### Description Send using msg.Transport()/msg.Destination(); requests get a client connection, responses get a server connection. ### Signature func (l *TransportLayer) WriteMsg(msg Message) error ### Parameters - **msg** (Message) - Required - The SIP message to send. ### Returns - **error** - An error if sending fails. ``` -------------------------------- ### Using DialogUA.Invite to create a client session Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialog-ua.md Shows how to create a DialogClientSession by sending an INVITE to a recipient, then waiting for the answer. The session is closed with defer. ```go dialogUA := &sipgo.DialogUA{Client: client, ContactHDR: uasContact} dlg, err := dialogUA.Invite(ctx, sip.Uri{User: "bob", Host: "example.com"}, nil) if err != nil { return err } defer dlg.Close() err = dlg.WaitAnswer(ctx, sipgo.AnswerOptions{}) ``` -------------------------------- ### Run tests with go test ./... Source: https://github.com/emiago/sipgo/blob/main/README.md Run the full test suite for the library. The project currently focuses more on benchmarking than on test coverage. ```bash go test ./... ``` -------------------------------- ### Parser.ParseHeaders Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-parser.md Parses only the start line and headers from raw data. ```APIDOC ## `func (p *Parser) ParseHeaders(data []byte, stream bool) (Message, int, error)` ### Description Parses only the start line and headers. The data must contain the full header section including the trailing double CRLF. Returns the message and the number of bytes read. ### Method Function ### Signature `func (p *Parser) ParseHeaders(data []byte, stream bool) (Message, int, error)` ### Parameters - **data** ([]byte) - Required - Raw data containing start line and headers. - **stream** (bool) - Required - Indicates stream mode. ### Returns - **Message** - Parsed message. - **int** - Number of bytes read. - **error** - `io.ErrUnexpectedEOF` on truncated data, `ErrParseLineNoCRLF` for a naked CR. ### Example ```go msg, n, err := parser.ParseHeaders(data, false) ``` ``` -------------------------------- ### transport interface definition Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-transport.md Defines the transport interface with methods for getting, creating, and closing connections. ```go type transport interface { // GetConnection returns connection from transport // addr must be resolved to IP:port GetConnection(addr string) Connection CreateConnection(ctx context.Context, laddr Addr, raddr Addr, handler MessageHandler) (Connection, error) Close() error } ``` -------------------------------- ### Init() Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/client.md Initializes the UUID random pool for the sipgo package. ```APIDOC ## [FUNCTION] Init ### Description Initializes the UUID random pool by calling `uuid.EnableRandPool()`. This is called automatically by the module's `init` function, but exists for explicit initialization. ### Signature `func Init()` ### Parameters None ### Returns None ``` -------------------------------- ### Handling ErrDialogResponse from WaitAnswer Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialog.md Shows how to catch ErrDialogResponse using a type assertion after WaitAnswer returns an error. The example logs the response status code when an INVITE fails. ```go err = dlg.WaitAnswer(ctx, sipgo.AnswerOptions{}) if dlgResp, ok := err.(*sipgo.ErrDialogResponse); ok { log.Error("INVITE failed", "status", dlgResp.Res.StatusCode) } ``` -------------------------------- ### ErrDialogResponse struct (dialog.go:19) Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialog.md Defines the error type returned when an INVITE fails with a non-2xx response or when a BYE does not return 200. The Error method formats the response start line. ```go type ErrDialogResponse struct { Res *sip.Response } ``` -------------------------------- ### NewServer Source: https://github.com/emiago/sipgo/blob/main/_autodocs/configuration.md Documentation for the NewServer constructor and its options. ```APIDOC ## NewServer ### Description Creates a new Server with configurable options. ### Method NewServer ### Signature func NewServer(ua *UserAgent, options ...ServerOption) (*Server, error) ### Parameters - **ua** (*UserAgent) - Required - The UserAgent to associate with the server. - **options** (...ServerOption) - Optional - Server configuration options. ### Options - **WithServerLogger(logger *slog.Logger)** (*slog.Logger) - Optional - Default: `sip.DefaultLogger().With("caller", "Server")` - Server logger. ### Behavioral Defaults - `noRouteHandler` = 405-responder - `requestMiddlewares` empty - Registers itself on `tx.OnRequest` ### Returns - (*Server, error) ``` -------------------------------- ### Direct construction of DialogUA Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialog-ua.md Shows how to create a DialogUA instance directly with a Client and a ContactHDR, typically used when not using the cache constructors. ```go ua := &sipgo.DialogUA{ Client: client, ContactHDR: sip.ContactHeader{Address: sip.Uri{User: "test", Host: "127.0.0.200", Port: 5088}}, } ``` -------------------------------- ### NewServer Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/server.md Creates a new Server instance and wires it into the transaction layer. ```APIDOC ## NewServer ### Description Creates a new Server instance and wires it into the transaction layer. It registers the server's request handler with the transaction layer so that incoming requests are routed to the server's middleware and method handlers. ### Method NewServer ### Signature func NewServer(ua *UserAgent, options ...ServerOption) (*Server, error) ### Parameters - **ua** (*UserAgent) - Required - The UserAgent instance to associate with the server. - **options** (...ServerOption) - Optional - Server options to configure the server (e.g., logger). ### Returns - **(*Server, error)** - The created Server and an error if creation fails. ### Example ```go ua, _ := sipgo.NewUA() srv, err := sipgo.NewServer(ua, sipgo.WithServerLogger(myLogger)) if err != nil { return err } ``` ``` -------------------------------- ### Set and get default logger Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-core.md Functions to set and retrieve the default logger. DefaultLogger returns the fallback logger used across all layers, wrapping it with a "caller" attribute. ```go func SetDefaultLogger(l *slog.Logger) // logger.go:11 — must be called before any usage ``` ```go func DefaultLogger() *slog.Logger // logger.go:15 — returns defLogger or slog.Default() ``` -------------------------------- ### Perform digest authentication with Client.DoDigestAuth Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/client.md Performs digest authentication by first sending a request, then retrying with credentials if the response is 401 Unauthorized. The example shows the typical flow for handling authentication challenges. ```go res, err := client.Do(ctx, req) // first attempt -> 401 if res.StatusCode == sip.StatusUnauthorized { res, err = client.DoDigestAuth(ctx, req, res, sipgo.DigestAuth{ Username: "alice", Password: "secret", }) } ``` -------------------------------- ### serveRequest middleware registration Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/server.md Registers a request middleware that runs on every incoming request before handler dispatch. Middlewares execute in registration order. This example uppercases the transport string if a Call-ID header is present. ```go srv.serveRequest(func(r *sip.Request) { if r.CallID() != nil { r.SetTransport(strings.ToUpper(r.Transport())) } }) ``` -------------------------------- ### Create a new response with NewResponse Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-response.md Creates an empty response with SipVersion = "SIP/2.0", no headers, no body. Then appends a Content-Type header. ```go res := sip.NewResponse(sip.StatusOK, "OK") res.AppendHeader(sip.NewHeader("Content-Type", "application/sdp")) ``` -------------------------------- ### Run SIP registration client Source: https://github.com/emiago/sipgo/blob/main/example/register/README.md Runs the SIP client to register with the server. The -u and -p flags specify the username and password, and -srv points to the server address. Two clients are shown for different users. ```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 ``` -------------------------------- ### Header interface definition Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md Defines the core Header interface for all SIP headers. It requires methods for getting the name, value, string representation, writing to a buffer, cloning, and writing the value. Use this as the base for implementing custom headers. ```go type Header interface { // Name returns underlying header name. Name() string Value() string String() string // StringWrite is better way to reuse single buffer StringWrite(w io.StringWriter) // Next() Header headerClone() Header valueStringWrite(w io.StringWriter) } ``` -------------------------------- ### Building a request URI with sip.Uri and sip.NewRequest Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-uri.md Builds a request URI for a SIP INVITE by constructing a Uri with scheme, user, host, port, and transport parameter, then passing it to sip.NewRequest as the recipient. Use this pattern to create request URIs for outgoing SIP requests. ```go recipient := sip.Uri{ Scheme: "sip", User: "bob", Host: "example.com", Port: 5060, UriParams: sip.HeaderParams{ {"transport", "tcp"}, }, } req := sip.NewRequest(sip.INVITE, recipient) ``` -------------------------------- ### SIP package variables and RFC3261BranchMagicCookie Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-core.md Defines the RFC 3261 branch magic cookie constant and package-level variables for SIP debugging and tracing. SIPDebug enables raw SIP message dumps to stderr when true, unless a custom tracer is installed. ```go const ( RFC3261BranchMagicCookie = "z9hG4bK" ) var ( SIPDebug bool siptracer SIPTracer ) ``` -------------------------------- ### ListenReadyCtxKey constants and types Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/server.md Defines the context key and value types used to signal when a listener is ready. The key is a string constant, and the value can be a channel or a callback function. Used primarily for testing. ```go // Used only for testing, better way is to pass listener with Serve{Transport} ListenReadyCtxKey = "ListenReadyCtxKey" type ListenReadyCtxValue chan struct{} type ListenReadyFuncCtxValue func(network string, addr string) ``` -------------------------------- ### Test simple SIP call with sipgox Source: https://github.com/emiago/sipgo/wiki/E2E-testing Creates a UAC phone with sipgox, dials a SIP URI, and verifies the call is answered. Uses a context timeout to control dial duration and hangs up after 3 seconds if the other side does not hang up first. ```go import ( "context" "testing" "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(ctx, 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(ua) // 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 TLS transports with ListenAndServeTLS Source: https://github.com/emiago/sipgo/blob/main/README.md Enable TLS for TCP and WebSocket listeners by generating a tls.Config from certificate files and optional root PEMs. The helper function loads the key pair and returns an error if the root certificate or key pair is invalid. ```go // TLS conf := generateTLSConfig(certFile, keyFile, rootPems) srv.ListenAndServeTLS(ctx, "tcp", "127.0.0.1:5061", conf) srv.ListenAndServeTLS(ctx, "ws", "127.0.0.1:5081", conf) func generateTLSConfig(certFile string, keyFile string, rootPems []byte) (*tls.Config, error) { roots := x509.NewCertPool() if rootPems != nil { ok := roots.AppendCertsFromPEM(rootPems) if !ok { return nil, fmt.Errorf("failed to parse root certificate") } } cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { return nil, fmt.Errorf("fail to load cert. err=%w", err) } conf := &tls.Config{ Certificates: []tls.Certificate{cert}, RootCAs: roots, } return conf, nil } ``` -------------------------------- ### Create a new SIP request with NewRequest Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-request.md Creates a new SIP INVITE request with no headers and sets the body. The SipVersion defaults to "SIP/2.0" and the URI's parameters and headers are cloned. AppendHeader should be called to add headers, and SetBody sets the ContentLength header. ```go req := sip.NewRequest(sip.INVITE, sip.Uri{User: "bob", Host: "example.com"}) req.SetBody(sdp) ``` -------------------------------- ### Build OpenSIPS Docker image with MySQL support Source: https://github.com/emiago/sipgo/blob/main/example/proxysip/docker/opensips/README.md Builds a Docker image with MySQL support by setting the OPENSIPS_EXTRA_MODULES variable. ```bash OPENSIPS_EXTRA_MODULES=opensips-mysql-module make build ``` -------------------------------- ### Client Do Request Source: https://github.com/emiago/sipgo/blob/main/README.md Perform a client request and wait for the final response, following the standard http package pattern. This is simpler than managing a client transaction manually. ```go req := sip.NewRequest(sip.INVITE, sip.Uri{User:"bob", Host: "example.com"}) res, err := client.Do(req) ``` -------------------------------- ### NewUA Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/user-agent.md Creates a UserAgent, applies the given options in order, then builds the transport and transaction layers. ```APIDOC ## NewUA ### Description Creates a UserAgent, applies the given options in order, then builds the transport and transaction layers. ### Method NewUA ### Signature func NewUA(options ...UserAgentOption) (*UserAgent, error) ### Parameters - **options** (UserAgentOption) - Optional - Options to configure the UserAgent. ### Returns - **ua** (*UserAgent) - The created UserAgent. - **err** (error) - Error if any option fails. ### Defaults | Field | Default | |---|---| | `name` | `"sipgo"` | | `hostname` | `"localhost"` | | `dnsResolver` | `net.DefaultResolver` | | `parser` | `sip.NewParser()` | | `txOptions` / `tpOptions` | empty | ### Example ```go ua, _ := sipgo.NewUA() // Build user agent defer ua.Close() client, _ := sipgo.NewClient(ua, sipgo.WithClientHostname("127.0.0.1"), sipgo.WithClientPort(5060)) srv, _ := sipgo.NewServer(ua) ``` ``` -------------------------------- ### Client.Hostname Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/client.md Returns the client's configured hostname. ```APIDOC ## Client.Hostname ### Description Returns `c.host` (option-set default hostname). ### Method `func (c *Client) Hostname() string` ### Returns - string - The configured hostname. ``` -------------------------------- ### Build OpenSIPS Docker image Source: https://github.com/emiago/sipgo/blob/main/example/proxysip/docker/opensips/README.md Builds a Docker image with the OpenSIPS master version from the git repository. ```bash make build ``` -------------------------------- ### Uri.String() string Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-uri.md Returns the full string form of the URI. The scheme defaults to 'sip' if not set, and IPv6 hosts are bracketed. ```APIDOC ## Uri.String() string ### Description Returns the full string form of the URI. The scheme defaults to `sip` if not set, and IPv6 hosts are bracketed. ### Returns - **string** - The string representation of the URI. ### Example ```go uri := &sip.Uri{Scheme: "sip", User: "alice", Host: "example.com", Port: 5060} str := uri.String() // "sip:alice@example.com:5060" ``` ``` -------------------------------- ### Build response from request with NewResponseFromRequest Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-response.md Standard way to build a response to an incoming request. Copies Record-Route, Via, From, To, Call-ID, CSeq headers, fills rport/received if needed, adds a tag to To for non-100 statuses, sets body and destination. ```go res := sip.NewResponseFromRequest(req, 100, "Trying", nil) tx.Respond(res) ``` -------------------------------- ### sip.NewParser Source: https://github.com/emiago/sipgo/blob/main/_autodocs/configuration.md Constructor for creating a SIP parser with configurable header parsers. ```APIDOC ## `sip.NewParser(options ...ParserOption) *Parser` ### Description Creates a new SIP message parser with configurable header parsers. ### Method Constructor ### Parameters #### Options - **WithHeadersParsers(m map[string]HeaderParser)** (map[string]HeaderParser) - Optional - Replace the header parser map (smaller map = faster). Default: `DefaultHeadersParser()`. ### Returns - **\*Parser** - A new parser instance with fields `headersParsers` and `MaxMessageLength` (default `ParseMaxMessageLength` = 65535). ``` -------------------------------- ### UAC-first with client hostname and port Source: https://github.com/emiago/sipgo/blob/main/README.md Act as a client first by specifying the host and port for the client handle, which reuses that connection until the UA is closed. The server handle still processes incoming requests, such as a BYE received on the configured address. ```go ua, _ := sipgo.NewUA() // Build user agent defer ua.Close() client, _ := sipgo.NewClient(ua, sipgo.WithClientHostname("127.0.0.1"), sipgo.WithClientPort(5060)) server, _ := sipgo.NewServer(ua) srv.OnBye(func(req *sip.Request, tx sip.ServerTransaction)) { // This will be received on 127.0.0.1:5060 } tx, err := client.TransactionRequest(ctx, sip.NewRequest(sip.INVITE, recipient)) ``` -------------------------------- ### Tune SIP module variables (UDPMTUSize, SIPDebug, SetDefaultLogger, SetTimers) Source: https://github.com/emiago/sipgo/blob/main/_autodocs/configuration.md Shows how to tune module-level SIP variables: raise the UDP MTU size, enable SIP debug via an environment variable, set a custom default logger, and adjust transaction timers with SetTimers. ```go sip.UDPMTUSize = 10000 // from example/proxysip sip.SIPDebug = os.Getenv("SIP_DEBUG") != "" sip.SetDefaultLogger(log) sip.SetTimers(300*time.Millisecond, 4*time.Second, 5*time.Second) ``` -------------------------------- ### Test call with both UAS and UAC using sipgox Source: https://github.com/emiago/sipgo/wiki/E2E-testing Sets up both a UAS and a UAC in the same test. The UAS listens on UDP 127.0.0.1:5088, answers the call, and verifies a custom SIP header (X-Test-Call) is received. The UAC dials with that header and hangs up after 3 seconds if not already done. ```go func TestCallBothParties(t *testing.T) { ctx, _ := context.WithTimeout(ctx, 32*time.Second) // First setup our UAS uas, _ := sipgo.NewUA(sipgo.WithUserAgent("TestUAS")) defer uas.Close() uasPhone := sipgox.NewPhone(usa, sipgox.WithPhoneListenAddr(sipgox.ListenAddr{ Network: "udp", Addr: "127.0.0.1:5088", }), ) // Run UAS in background go func() { // Wait for answer dialog, err := uasPhone.Answer(ctx, sipgox.AnswerOptions{}) require.NoError(t, err) // No error so we have answered a call // Lets check did we recevie some header hdr := dialog.InviteRequest.GetHeader("X-Test-Call") assert.NotEmpty(t, hdr) // Wait for call/dialog to be completed t.Log("UAS answered") <-dialog.Done() return }() // First create our user agent uac, _ := sipgo.NewUA(sipgo.WithUserAgent("TestUAC")) defer uac.Close() uacPhone := sipgox.NewPhone(ua) // Start dial on sip:123456789@asterisk.xy:5060 recipient := sip.Uri{User: "123456789", Host: "asterisk.xy", Port: 5060}, dialog, err := uacPhone.Dial( ctx, recipient, sipgox.DialOptions{ SipHeaders: []sip.Header{ sip.NewHeader("X-Test-Call", "true"), // Pass some custom sip header }, }, ) 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) } } ``` -------------------------------- ### Uri.HostPort() string Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-uri.md Returns the host:port part of the URI. ```APIDOC ## Uri.HostPort() string ### Description Returns the `host:port` part of the URI. ### Returns - **string** - The host and port string. ### Example ```go uri := &sip.Uri{Host: "example.com", Port: 5060} hp := uri.HostPort() // "example.com:5060" ``` ``` -------------------------------- ### Create and append untyped SIP headers with sip.NewHeader Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-headers.md Creates untyped SIP headers from raw strings and appends them to a request. Useful for custom or authorization headers when no typed header exists. ```go req.AppendHeader(sip.NewHeader("X-Custom", "value")) req.AppendHeader(sip.NewHeader("Authorization", cred.String())) ``` -------------------------------- ### func (ua *DialogUA) Invite(ctx context.Context, recipient sip.Uri, body []byte, headers ...sip.Header) (*DialogClientSession, error) Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/dialog-ua.md Builds an INVITE request and sends it, returning a DialogClientSession. ```APIDOC ## func (ua *DialogUA) Invite(ctx context.Context, recipient sip.Uri, body []byte, headers ...sip.Header) (*DialogClientSession, error) ### Description Builds an INVITE request (optionally with body and extra headers), and if the recipient URI carries a `transport` URI parameter it calls `req.SetTransport(tran)`. Then delegates to `WriteInvite`. ### Parameters - **ctx** (context.Context) - Required - Context for the request. - **recipient** (sip.Uri) - Required - The recipient URI. - **body** ([]byte) - Optional - Request body. - **headers** (...sip.Header) - Optional - Additional headers. ### Returns - **session** (*DialogClientSession) - The created dialog client session. - **error** - Error if sending fails. ### Example ```go dialogUA := &sipgo.DialogUA{Client: client, ContactHDR: uasContact} dlg, err := dialogUA.Invite(ctx, sip.Uri{User: "bob", Host: "example.com"}, nil) if err != nil { return err } defer dlg.Close() err = dlg.WaitAnswer(ctx, sipgo.AnswerOptions{}) ``` ``` -------------------------------- ### NewParser Source: https://github.com/emiago/sipgo/blob/main/_autodocs/api-reference/sip-parser.md Constructor for creating a new Parser instance with configurable options. ```APIDOC ## NewParser ### Description Creates a new Parser instance with default headers parsers and maximum message length, then applies the provided options. ### Method Constructor ### Signature `func NewParser(options ...ParserOption) *Parser` ### Parameters - **options** (...ParserOption) - Optional - A variadic list of parser options to customize the parser. ### Returns - **\*Parser** - A new Parser instance. ### Example ```go parser := sip.NewParser(sip.WithHeadersParsers(customParsers)) ``` ```