emiago / sipgo

SIP library for writing fast SIP services in GO
BSD 2-Clause "Simplified" License
570 stars 76 forks source link

sipgo ws integarted in webserver #130

Open wnke opened 2 months ago

wnke commented 2 months ago

Hello!

Is is possible to integrate sipgo ws on a http server? In particular I am using Labstack Echo and trying to understand how to go about having /ws using SIPGO and the rest as a simple webserver.

I am asking because all transports on sipgo start their own listener and that would not fit this presuppose.

package main

import (
    "fmt"

    "github.com/labstack/echo/v4"
    "github.com/labstack/echo/v4/middleware"
    "golang.org/x/net/websocket"
)

func hello(c echo.Context) error {
    websocket.Handler(func(ws *websocket.Conn) {
        defer ws.Close()

                // use sipgo here
        for {
            // Write
            err := websocket.Message.Send(ws, "Hello, Client!")
            if err != nil {
                c.Logger().Error(err)
            }

            // Read
            msg := ""
            err = websocket.Message.Receive(ws, &msg)
            if err != nil {
                c.Logger().Error(err)
            }
            fmt.Printf("%s\n", msg)
        }
    }).ServeHTTP(c.Response(), c.Request())
    return nil
}

func main() {
    e := echo.New()
    e.Use(middleware.Logger())
    e.Use(middleware.Recover())
    e.Static("/", "../public")
    e.GET("/ws", hello)
    e.Logger.Fatal(e.Start(":1323"))
}
emiago commented 2 months ago

not currently, but normally what you want is to have this as separate service behind your ingress. This is how I am doing for webrtc with diago. What is your use case? It is needd to inject this connection on transport layer, which could be missing for listeners.

wnke commented 2 months ago

I was looking into having a single service without the need of a ingress proxy and I also want to share session state between the ws endpoint and remaining http endpoints for authentication and such.

One possibility would be having the transportLayer expose the WS tramport and making InitConnection public, but haven't tried it yet:

func hello(c echo.Context) error {
    websocket.Handler(func(ws *websocket.Conn) {
           defer ws.Close()
               srv.TransportLayer().WS.InitConnection(ws, ....)

    }).ServeHTTP(c.Response(), c.Request())
    return nil
}
emiago commented 2 months ago

yes that could be one of solution. Still I would like to have this on transport layer instead going down to transport it self. Reason is to avoid some breaking changes, and some of things you may need still from layer. So srv.TransportLayer().ServeConnectionWS()

I think this should work

wnke commented 2 months ago

Hello again! Thank you for your response!

emiago commented 2 months ago

Would that be added to the Transport interface? It will impact other transports as well?

hi @wnke it may not be needed, as you want to go to exact transport.

Following this I would still need to be listening for websockets even if I am passing the connections via ServeConnectionWS?

I see no problem with this?

wnke commented 2 months ago

We can always limit to listen on local host only, but feels like a security risk leaving an unused port open. As far as creating a PR, I will try to get around it next week and we can further discuss then :)