package rpc import ( "context" "encoding/json" "fmt" "github.com/google/uuid" "nhooyr.io/websocket" ) func (s *server) Call(ctx context.Context, c *websocket.Conn, method string, params, result any) (*Response, error) { id := uuid.New().String() resp := make(chan *Response, 1) var dataParams []byte var err error if params != nil { dataParams, err = json.Marshal(params) if err != nil { return nil, fmt.Errorf("Error Marshalling Params: %w", err) } } rawParams := json.RawMessage(dataParams) req := Request{ ID: id, Method: method, Params: &rawParams, } reqData, err := json.Marshal(req) if err != nil { return nil, fmt.Errorf("Error Marshalling Request: %w", err) } // Add Call to Request Map func() { s.requestMutex.Lock() defer s.requestMutex.Unlock() s.requests[id] = resp }() // Remove Call from Request map defer func() { s.requestMutex.Lock() defer s.requestMutex.Unlock() delete(s.requests, id) }() // Write Request err = c.Write(ctx, websocket.MessageText, reqData) if err != nil { return nil, fmt.Errorf("Error Writing Request: %w", err) } // Wait for Response, TODO add Select Timeout response := <-resp if response.Error != nil { return response, fmt.Errorf("Call Error: %w", err) } if result == nil { return response, nil } if response.Result == nil { return response, fmt.Errorf("Got Empty Result") } err = json.Unmarshal(*response.Result, &result) if err != nil { return response, fmt.Errorf("Error Parsing Result: %w", err) } return response, nil } // TODO Call with Multiple Response (Chunked file upload)