package transport import ( "context" "fmt" "net/http" "net/url" "time" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/requests" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/types" "github.com/gorilla/websocket" ) func (tr *FoundryTransport) InitWebSocketConnection() error { if !tr.IsAuth { return ErrorNotAuth } query := url.Values{} query.Add("session", tr.Http.SessionID) query.Add("EIO", "4") query.Add("transport", "websocket") u := url.URL{Scheme: "ws", Host: tr.Http.Host, Path: fmt.Sprintf("%s/", requests.SocketPath), RawQuery: query.Encode()} wsHeader := http.Header{} wsHeader.Set("Cookie", fmt.Sprintf("session=%s", tr.Http.SessionID)) wsConn, _, err := websocket.DefaultDialer.Dial(u.String(), wsHeader) if err != nil { return err } tr.WsConn = wsConn tr.CurrWsId = 0 tr.Logger.Info("Successefully connected to Foundry Websocket") return nil } func (tr *FoundryTransport) HandleWebsocketRequest(msg *types.WsMessage) ([]byte, error) { err := tr.WsConn.WriteMessage(websocket.TextMessage, msg.ToByteSlice()) if err != nil { return nil, err } data, err := tr.ReceiveMessage(msg.Id) if err != nil { return nil, err } return data, nil } func (tr *FoundryTransport) ReceiveMessage(id int) ([]byte, error) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() for { select { case msg, ok := <-tr.ExchangeChan.Msgs[id]: if !ok { time.Sleep(5 * time.Microsecond) continue } tr.CloseMsgChannel(id, 0) return msg, nil case <-ctx.Done(): err := ctx.Err() if err != nil { return nil, err } return nil, ErrorTimeout default: time.Sleep(5 * time.Microsecond) } } } func (tr *FoundryTransport) ListenWebSocket() { for { _, message, err := tr.WsConn.ReadMessage() if err != nil { tr.ReadChan.Err() <- &types.FoundryError{Direction: types.ReaderCode, Err: err, Type: types.WebSocketCode} return } data, err := types.ParseWsRespMessage(string(message), types.RequestCodes) if err != nil { tr.ReadChan.Err() <- &types.FoundryError{Direction: types.ReaderCode, Err: err, Type: types.WebSocketCode} continue } tr.ReadChan.Msg() <- data } } func (tr *FoundryTransport) SendOnlyCodeRequest(code string) error { tr.Logger.Debug("WS: Data has been send\n", "msg", types.CodesRespToReq[code]) return tr.WsConn.WriteMessage(websocket.TextMessage, []byte(types.CodesRespToReq[code])) } func (tr *FoundryTransport) GetJsonData(stateType string) ([]byte, error) { msg := types.NewWsMessageByPage(stateType, tr.CurrWsId) tr.CurrWsId++ return tr.HandleWebsocketRequest(msg) } func (tr *FoundryTransport) CloseWebSocketConn() { tr.Logger.Debug("Websocket has been closed") tr.WsConn.Close() }