Documentation ¶
Overview ¶
Package wslis allows a server to create connections to clients.
wslis allows a server to create connections to clients. For that, clients previously stablish a connection to the server through websockets. Once the connection arrives, the server and the clients, multiplex the stream so several connections can go through the same http stream.
History and Design Considerations ¶
wslis comes from the needs of delegatescreen.com that mainly display webpages in office dashboards. The most common operations are: Set the web page to display, and get a screenshot of the current page. This operations have to be syncronous, and completes as fast as possible.
This lead us to the following desing considerations:
- Request-Response paradigm.
- It works over http, so edges, load balancers and other network components work out of the box.
And this are the options considered.
- ZeroMq, Mqtt or most iot platforms are pub sub based. So even if most of them can work over http, we will need to abstract some kind of request/response ciclye.
- Signaling where the server sends a signal (kind of request) to the client, and the client initiates an http request. For signaling we considered: longpush, server-sent-events, http2 push . This option was discarded to remove the need of designing a signaling mecanish, and the added complication of matching signals to client/requests.
- connect the clients to vpns through wireguard. As clients can run on windows/mac/linux this will imply the automation of all the configuraiton in three ooss, and maintain that over time. Also a missconfiguration may brick the computer.
- ssh over http. This will give the server control over the clients to run any commands. Even if this might be flexible enough, a compromise server could infect a client and access client network.
Usage ¶
See Example for usage info.
Example ¶
result := make(chan (string)) // Server go ListenAndServe("localhost:9090", EndpointHandlerFunc(func(d *Dialer) { buf := make([]byte, 1024) id := d.Header.Get("DeviceId") if id != "123" { panic("We don't know you") } // We open a new connection to the client as soon as we get the connection conn, err := d.Dial() if err != nil { panic(err) } // We say hi conn.Write([]byte("hola")) // And we expect a hi back n, err := conn.Read(buf) if err != nil { panic(err) } result <- string(buf[:n]) })) // Client go func() { time.Sleep(time.Millisecond) // Lets give time to the server to start lis, err := DialAndListen("ws://localhost:9090", http.Header{"DeviceId": []string{"123"}}) if err != nil { panic(err) } // Let's have an echo server conn, err := lis.Accept() if err != nil { panic(err) } buf := make([]byte, 1024) n, err := conn.Read(buf) if err != nil { panic(err) } conn.Write(buf[:n]) conn.Close() }() fmt.Println(<-result)
Output: hola
Index ¶
- func DialAndListen(url string, header http.Header) (net.Listener, error)
- func ListenAndServe(addr string, handler EndpointHandler) error
- func ListenAndServeTLS(addr string, certFile, keyFile string, handler EndpointHandler) error
- type Client
- type Dialer
- type EndpointHandler
- type EndpointHandlerFunc
- type Server
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DialAndListen ¶
DialAndListen creates a client and connects to the given url
func ListenAndServe ¶
func ListenAndServe(addr string, handler EndpointHandler) error
ListenAndServe is a convenient function that starts a server in the given address and send all new clients to handler
func ListenAndServeTLS ¶
func ListenAndServeTLS(addr string, certFile, keyFile string, handler EndpointHandler) error
ListenAndServeTLS is the TLS version of ListenAndServe
Example ¶
result := make(chan (string)) // Server go ListenAndServeTLS("localhost:9443", "ssl.crt", "ssl.key", EndpointHandlerFunc(func(d *Dialer) { buf := make([]byte, 1024) id := d.Header.Get("DeviceId") if id != "123" { panic("We don't know you") } // We open a new connection to the client as soon as we get the connection conn, err := d.Dial() if err != nil { panic(err) } // We say hi conn.Write([]byte("hola")) // And we expect a hi back n, err := conn.Read(buf) if err != nil { panic(err) } result <- string(buf[:n]) })) // Client go func() { time.Sleep(time.Second * 2) // Wait for the server to start lis, err := DialAndListen("wss://localhost:9443", http.Header{"DeviceId": []string{"123"}}) if err != nil { panic(err) } // Let's have an echo server conn, err := lis.Accept() if err != nil { panic(err) } buf := make([]byte, 1024) n, err := conn.Read(buf) if err != nil { panic(err) } conn.Write(buf[:n]) conn.Close() }() fmt.Println(<-result)
Output: hola
Types ¶
type Client ¶
type Client struct { // URL of the server to connect. // It should be ws:// or wss:// protocol URL string // Headers to send to the server while opening a connection Header http.Header // HandshakeTimeout specifies the duration for the handshake to complete. HandshakeTimeout time.Duration }
A Client calls a server through websocket and waits for connections.
type EndpointHandler ¶
type EndpointHandler interface {
HandleEndpoint(*Dialer)
}
EndpointHandler responds to a new connection from a client
type EndpointHandlerFunc ¶
type EndpointHandlerFunc func(*Dialer)
The EndpointHandlerFunc type is an adapter to allow the use of ordinary functions as Endpoint Handlers.
func (EndpointHandlerFunc) HandleEndpoint ¶
func (f EndpointHandlerFunc) HandleEndpoint(d *Dialer)
HandleEndpoint calls f(d)
type Server ¶
type Server struct { // Addr to listen (only needed if started with ListenAndServe) Addr string // Handler called when a new connection is called. Handler EndpointHandler // contains filtered or unexported fields }
Server will waits for connections to arrives and then calls EndpointHandler It can be use directly with the ListenAndServe functions or indirectly as an http.Handler
func (*Server) ListenAndServe ¶
ListenAndServe will create a basic http server listening in the given address. If you need more control over the server, you can use the hole server as an http.Handler
func (*Server) ListenAndServeTLS ¶
ListenAndServeTLS is the TLS version of ListenAndServe