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
-
Is there a way to connect to another server and relay the currently received message?
Beta Was this translation helpful? Give feedback.
All reactions