github.com/anycable/anycable-go@v1.5.1/protocol/protocol.go (about)

     1  package protocol
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  
     7  	"github.com/anycable/anycable-go/common"
     8  
     9  	pb "github.com/anycable/anycable-go/protos"
    10  )
    11  
    12  // NewConnectMessage builds a connect RPC payload from the session env
    13  func NewConnectMessage(env *common.SessionEnv) *pb.ConnectionRequest {
    14  	return &pb.ConnectionRequest{
    15  		Env: buildEnv(env),
    16  	}
    17  }
    18  
    19  // NewCommandMessage builds a command RPC payload from the session env, command and channel names,
    20  // and connection identifiers
    21  func NewCommandMessage(env *common.SessionEnv, command string, channel string, identifiers string, data string) *pb.CommandMessage {
    22  	msg := pb.CommandMessage{
    23  		Command:               command,
    24  		Env:                   buildChannelEnv(channel, env),
    25  		Identifier:            channel,
    26  		ConnectionIdentifiers: identifiers,
    27  	}
    28  
    29  	if data != "" {
    30  		msg.Data = data
    31  	}
    32  
    33  	return &msg
    34  }
    35  
    36  // NewDisconnectMessage builds a disconnect RPC payload from the session env, connection identifiers and
    37  // subscriptions
    38  func NewDisconnectMessage(env *common.SessionEnv, identifiers string, subscriptions []string) *pb.DisconnectRequest {
    39  	return &pb.DisconnectRequest{
    40  		Identifiers:   identifiers,
    41  		Subscriptions: subscriptions,
    42  		Env:           buildDisconnectEnv(env),
    43  	}
    44  }
    45  
    46  // ParseConnectResponse takes protobuf ConnectionResponse struct and converts into common.ConnectResult and/or error
    47  func ParseConnectResponse(response *pb.ConnectionResponse) (*common.ConnectResult, error) {
    48  	reply := common.ConnectResult{Transmissions: response.Transmissions}
    49  
    50  	if response.Env != nil {
    51  		reply.CState = response.Env.Cstate
    52  	}
    53  
    54  	if response.Status.String() == "SUCCESS" {
    55  		reply.Identifier = response.Identifiers
    56  		reply.Status = common.SUCCESS
    57  		return &reply, nil
    58  	}
    59  
    60  	if response.Status.String() == "FAILURE" {
    61  		reply.Status = common.FAILURE
    62  		return &reply, nil
    63  	}
    64  
    65  	reply.Status = common.ERROR
    66  	return &reply, fmt.Errorf("Application error: %s", response.ErrorMsg)
    67  }
    68  
    69  // ParseCommandResponse takes protobuf CommandResponse struct and converts into common.CommandResult and/or error
    70  func ParseCommandResponse(response *pb.CommandResponse) (*common.CommandResult, error) {
    71  	res := &common.CommandResult{
    72  		Disconnect:     response.Disconnect,
    73  		StopAllStreams: response.StopStreams,
    74  		Streams:        response.Streams,
    75  		StoppedStreams: response.StoppedStreams,
    76  		Transmissions:  response.Transmissions,
    77  	}
    78  
    79  	if response.Env != nil {
    80  		res.CState = response.Env.Cstate
    81  		res.IState = response.Env.Istate
    82  	}
    83  
    84  	if response.Status.String() == "SUCCESS" {
    85  		res.Status = common.SUCCESS
    86  		return res, nil
    87  	}
    88  
    89  	if response.Status.String() == "FAILURE" {
    90  		res.Status = common.FAILURE
    91  		return res, nil
    92  	}
    93  
    94  	res.Status = common.ERROR
    95  	return res, fmt.Errorf("Application error: %s", response.ErrorMsg)
    96  }
    97  
    98  // ParseDisconnectResponse takes protobuf DisconnectResponse struct and return error if any
    99  func ParseDisconnectResponse(response *pb.DisconnectResponse) error {
   100  	if response.Status.String() != "ERROR" {
   101  		return nil
   102  	}
   103  
   104  	return fmt.Errorf("Application error: %s", response.ErrorMsg)
   105  }
   106  
   107  func buildEnv(env *common.SessionEnv) *pb.Env {
   108  	protoEnv := pb.Env{Url: env.URL, Headers: *env.Headers}
   109  	if env.ConnectionState != nil {
   110  		protoEnv.Cstate = *env.ConnectionState
   111  	}
   112  	return &protoEnv
   113  }
   114  
   115  func buildDisconnectEnv(env *common.SessionEnv) *pb.Env {
   116  	protoEnv := *buildEnv(env)
   117  
   118  	if env.ChannelStates == nil {
   119  		return &protoEnv
   120  	}
   121  
   122  	states := make(map[string]string)
   123  
   124  	for id, state := range *env.ChannelStates {
   125  		encodedState, _ := json.Marshal(state)
   126  
   127  		states[id] = string(encodedState)
   128  	}
   129  
   130  	protoEnv.Istate = states
   131  
   132  	return &protoEnv
   133  }
   134  
   135  func buildChannelEnv(id string, env *common.SessionEnv) *pb.Env {
   136  	protoEnv := *buildEnv(env)
   137  
   138  	if env.ChannelStates == nil {
   139  		return &protoEnv
   140  	}
   141  
   142  	if _, ok := (*env.ChannelStates)[id]; ok {
   143  		protoEnv.Istate = (*env.ChannelStates)[id]
   144  	}
   145  	return &protoEnv
   146  }