package client import ( "fmt" "time" "forge.redroom.link/yves/meowlib" "github.com/google/uuid" "google.golang.org/protobuf/proto" ) type InternalServer struct { ServerData meowlib.Server `json:"server_data,omitempty"` Presence bool `json:"presence,omitempty"` LastCheck time.Time `json:"last_check,omitempty"` Uptime time.Duration `json:"uptime,omitempty"` Login string `json:"login,omitempty"` Password string `json:"password,omitempty"` Me meowlib.KeyPair `json:"me,omitempty"` Country string `json:"country,omitempty"` AllowedDelay int `json:"allowed_delay,omitempty"` } type InternalServerList struct { Name string Servers []InternalServer } func InternalServerFromUrl(url string) *InternalServer { var is InternalServer is.ServerData.Url = url return &is } func InternalServerFromServer(server *meowlib.Server) *InternalServer { var is InternalServer is.ServerData = *server is.Me = meowlib.NewKeyPair() return &is } func (sl *InternalServerList) AddUrls(urls []string) { for _, url := range urls { sl.Servers = append(sl.Servers, *InternalServerFromUrl(url)) } } // AsymEncryptMessage prepares a message to send to a specific internal server func (ints *InternalServer) AsymEncryptMessage(Message []byte) (*meowlib.EncryptedMessage, error) { var enc *meowlib.EncryptedMessage enc, err := meowlib.AsymEncryptAndSign(ints.ServerData.PublicKey, ints.Me.Private, Message) if err != nil { fmt.Println(err.Error()) return nil, err } return enc, err } // AsymDecryptMessage reads a message from a specific internal server func (ints *InternalServer) AsymDecryptMessage(Message []byte, Signature []byte) (DecryptedMessage []byte, err error) { DecryptedMessage, err = meowlib.AsymDecryptAndCheck(ints.Me.Private, ints.ServerData.PublicKey, Message, Signature) if err != nil { fmt.Println(err.Error()) return nil, err } return DecryptedMessage, err } // Creates a basic message to server from a single packed user message and returns it as protobuf serialized byte array func (ints *InternalServer) BuildToServerMessageFromUserMessage(usermsg *meowlib.PackedUserMessage) *meowlib.ToServerMessage { var msg meowlib.ToServerMessage msg.Uuid = uuid.New().String() msg.Type = "1" msg.From = ints.Me.Public msg.Messages = append(msg.Messages, usermsg) return &msg } // Creates a basic message to server from a single packed user message and returns it as protobuf serialized byte array func (ints *InternalServer) BuildMessageSendingMessage(usermsg *meowlib.PackedUserMessage) ([]byte, error) { msg := ints.BuildToServerMessageFromUserMessage(usermsg) out, err := proto.Marshal(msg) if err != nil { return nil, err } return out, nil } // Creates a basic message to server from a single packed user message and returns it as protobuf serialized byte array func (ints *InternalServer) BuildMessageRequestMessage(lookupKeys []string) ([]byte, error) { var msg meowlib.ToServerMessage msg.Uuid = uuid.New().String() msg.Type = "1" msg.From = ints.Me.Public out, err := proto.Marshal(&msg) if err != nil { return nil, err } return out, nil } // Creates a basic message to server from a single packed user message and returns it as protobuf serialized byte array func (ints *InternalServer) BuildToServerMessageInvitation(invitation *meowlib.ContactCard, password string, timeout int, urllen int) (*meowlib.ToServerMessage, error) { var msg meowlib.ToServerMessage var inv meowlib.Invitation payload, err := invitation.Compress() if err != nil { return nil, err } msg.Type = "1" msg.From = ints.Me.Public inv.Password = password inv.Timeout = int32(timeout) inv.Idlen = int32(urllen) inv.Payload = payload msg.Invitation = &inv return &msg, nil } func (ints *InternalServer) PackServerMessage(payload []byte, signature []byte) (protoPackedMessage []byte, err error) { var msg meowlib.PackedServerMessage msg.From = ints.Me.Public msg.Payload = payload msg.Signature = signature out, err := proto.Marshal(&msg) if err != nil { return nil, err } return out, nil } func (ints *InternalServer) UnPackServerMessage(protoPackedMessage []byte) (payload []byte, signature []byte, err error) { msg := &meowlib.PackedServerMessage{} if err := proto.Unmarshal(protoPackedMessage, msg); err != nil { return nil, nil, err } return msg.Payload, msg.Signature, nil } func (srv *InternalServer) ProcessOutboundMessage(toServerMessage *meowlib.ToServerMessage) ([]byte, error) { byteToServerMessage, err := proto.Marshal(toServerMessage) if err != nil { return nil, err } // Encrypting it encToServer, err := srv.AsymEncryptMessage(byteToServerMessage) if err != nil { return nil, err } // Packing it protoPackedServerMsg, err := srv.PackServerMessage(encToServer.Data, encToServer.Signature) if err != nil { return nil, err } return protoPackedServerMsg, nil } func (srv *InternalServer) ProcessInboundServerResponse(msg []byte) (*meowlib.FromServerMessage, error) { fsmsg := &meowlib.FromServerMessage{} payload, signature, err := srv.UnPackServerMessage(msg) if err != nil { return nil, err } decrypted, err := srv.AsymDecryptMessage(payload, signature) if err != nil { return nil, err } if err := proto.Unmarshal(decrypted, fsmsg); err != nil { return nil, err } return fsmsg, nil }