Connect to another server #96
Replies: 4 comments 4 replies
-
Yes, but it's inefficient. |
Beta Was this translation helpful? Give feedback.
0 replies
-
I need to do it anyways as I have to relay to another websocket which is unfortunately in python. Please share a snippet. |
Beta Was this translation helpful? Give feedback.
3 replies
-
package main
import (
"github.com/lxzan/gws"
"net/http"
)
const (
protocol = "ws"
addr = "127.0.0.1:9001"
)
func GetValueFromSession[T any](session gws.SessionStorage, key string) (value T) {
if v, ok := session.Load(key); ok {
value = v.(T)
}
return value
}
func main() {
upgrader := gws.NewUpgrader(new(ServerHandler), &gws.ServerOption{
PermessageDeflate: gws.PermessageDeflate{
Enabled: true,
ServerContextTakeover: true,
ClientContextTakeover: true,
},
})
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
sock, err := upgrader.Upgrade(w, r)
if err != nil {
return
}
url := r.URL
url.Scheme, url.Host = protocol, addr
sock.Session().Store("dst", url.String())
sock.ReadLoop()
})
_ = http.ListenAndServe(":9000", nil)
}
type ServerHandler struct{}
func (c *ServerHandler) OnOpen(sock *gws.Conn) {
client, _, err := gws.NewClient(new(ClientHandler), &gws.ClientOption{
Addr: GetValueFromSession[string](sock.Session(), "dst"),
PermessageDeflate: gws.PermessageDeflate{
Enabled: true,
ServerContextTakeover: true,
ClientContextTakeover: true,
},
})
if err != nil {
sock.WriteClose(1000, nil)
return
}
sock.Session().Store("peer", client)
client.Session().Store("peer", sock)
go client.ReadLoop()
}
func (c *ServerHandler) OnClose(sock *gws.Conn, err error) {
code, reason := uint16(1000), []byte(nil)
if v, ok := err.(*gws.CloseError); ok {
code, reason = v.Code, v.Reason
}
if client := GetValueFromSession[*gws.Conn](sock.Session(), "peer"); client != nil {
client.WriteClose(code, reason)
}
}
func (c *ServerHandler) OnPing(sock *gws.Conn, payload []byte) {
_ = GetValueFromSession[*gws.Conn](sock.Session(), "peer").WritePing(payload)
}
func (c *ServerHandler) OnPong(sock *gws.Conn, payload []byte) {
_ = GetValueFromSession[*gws.Conn](sock.Session(), "peer").WritePong(payload)
}
func (c *ServerHandler) OnMessage(sock *gws.Conn, message *gws.Message) {
_ = GetValueFromSession[*gws.Conn](sock.Session(), "peer").WriteMessage(message.Opcode, message.Bytes())
}
type ClientHandler struct{}
func (c *ClientHandler) OnOpen(sock *gws.Conn) {}
func (c *ClientHandler) OnClose(sock *gws.Conn, err error) {
code, reason := uint16(1000), []byte(nil)
if v, ok := err.(*gws.CloseError); ok {
code, reason = v.Code, v.Reason
}
GetValueFromSession[*gws.Conn](sock.Session(), "peer").WriteClose(code, reason)
}
func (c *ClientHandler) OnPing(sock *gws.Conn, payload []byte) {
_ = GetValueFromSession[*gws.Conn](sock.Session(), "peer").WritePing(payload)
}
func (c *ClientHandler) OnPong(sock *gws.Conn, payload []byte) {
_ = GetValueFromSession[*gws.Conn](sock.Session(), "peer").WritePong(payload)
}
func (c *ClientHandler) OnMessage(sock *gws.Conn, message *gws.Message) {
_ = GetValueFromSession[*gws.Conn](sock.Session(), "peer").WriteMessage(message.Opcode, message.Bytes())
} |
Beta Was this translation helpful? Give feedback.
0 replies
Answer selected by
lxzan
-
package main
import (
"bufio"
"context"
"github.com/lxzan/gws"
"io"
"net/http"
"reflect"
)
const addr = "ws://localhost:9001" // target
func main() {
pd := gws.PermessageDeflate{Enabled: false}
upgrader := gws.NewUpgrader(new(gws.BuiltinEventHandler), &gws.ServerOption{
PermessageDeflate: pd,
})
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
var proxy, app *gws.Conn
var err error
var ctx, cancel = context.WithCancel(context.Background())
defer func() {
if proxy != nil {
_ = proxy.NetConn().Close()
}
if app != nil {
_ = app.NetConn().Close()
}
cancel()
}()
if proxy, err = upgrader.Upgrade(w, r); err != nil {
return
}
if app, _, err = gws.NewClient(new(gws.BuiltinEventHandler), &gws.ClientOption{
Addr: addr + r.URL.RequestURI(),
PermessageDeflate: pd,
}); err != nil {
return
}
proxyReader := (*bufio.Reader)(reflect.ValueOf(proxy).Elem().FieldByName("br").UnsafePointer())
appReader := (*bufio.Reader)(reflect.ValueOf(app).Elem().FieldByName("br").UnsafePointer())
go func() {
for {
if _, err := io.Copy(app.NetConn(), proxyReader); err != nil {
cancel()
return
}
}
}()
go func() {
for {
if _, err := io.Copy(proxy.NetConn(), appReader); err != nil {
cancel()
return
}
}
}()
<-ctx.Done()
})
_ = http.ListenAndServe(":8000", nil)
} |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Is there a way to connect to another server and relay the currently received message?
Beta Was this translation helpful? Give feedback.
All reactions