2022-09-06 09:30:45 +02:00
package client
import (
"fmt"
2024-03-26 14:12:32 +01:00
"strings"
2022-09-06 09:30:45 +02:00
"time"
"forge.redroom.link/yves/meowlib"
2022-09-19 20:16:57 +02:00
"github.com/google/uuid"
2022-09-18 18:09:27 +02:00
"google.golang.org/protobuf/proto"
2022-09-06 09:30:45 +02:00
)
2023-11-08 22:01:44 +01:00
// Server manages server related operations
2023-11-08 21:52:09 +01:00
// - Sending messages for server usage
// - Two first steps of an invitation
2023-12-09 20:01:19 +01:00
// - User message sending with UserKp identification
2023-11-08 21:52:09 +01:00
// - Messages lookup requests
// - Utility functions for packing/unpacking, encrypting/decrypting messages for server communication
2023-12-09 20:01:19 +01:00
// - Server remote management if ManagerKp is available for that server
2023-11-08 22:01:44 +01:00
type Server struct {
2024-02-07 16:08:24 +01:00
//ServerCard meowlib.ServerCard `json:"server_data,omitempty"`
Name string ` json:"name,omitempty" `
Description string ` json:"description,omitempty" `
PublicKey string ` json:"public_key,omitempty" `
Url string ` json:"url,omitempty" `
Login string ` json:"login,omitempty" `
Password string ` json:"password,omitempty" `
Presence bool ` json:"presence,omitempty" `
LastCheck time . Time ` json:"last_check,omitempty" `
Uptime time . Duration ` json:"uptime,omitempty" `
UserKp meowlib . KeyPair ` json:"user_kp,omitempty" `
ManagerKp meowlib . KeyPair ` json:"manager_kp,omitempty" `
Country string ` json:"country,omitempty" `
AllowedDelay int ` json:"allowed_delay,omitempty" `
Backup bool ` json:"backup,omitempty" `
2022-09-06 09:30:45 +02:00
}
2023-11-09 22:46:39 +01:00
// CreateServerFromUrl creates a server from a basic url, ex : https://my.meowserver.example:8443/meow/
func CreateServerFromUrl ( url string ) * Server {
2023-11-08 22:01:44 +01:00
var is Server
2024-02-07 16:08:24 +01:00
is . Url = url
2022-09-06 09:30:45 +02:00
return & is
}
2024-03-26 14:12:32 +01:00
// CreateServerFromUid creates a server from a uid string, ex : mylogin:mypassword@https://my.meowserver.example:8443/meow/
func CreateServerFromUid ( uid string ) * Server {
var is Server
2024-03-26 15:23:24 +01:00
uidTable := strings . Split ( uid , "@" ) //! Weak test, use regexp
if len ( uidTable ) == 2 {
loginpw := strings . Split ( uidTable [ 0 ] , ":" )
is . Url = uidTable [ 1 ]
is . Login = loginpw [ 0 ]
is . Password = loginpw [ 1 ]
} else {
is . Url = uidTable [ 0 ]
}
2024-03-26 14:12:32 +01:00
return & is
}
2024-03-26 14:57:33 +01:00
// CreateServerFromMeowUrl creates a server from a meow url, ex : meow://mylogin:mypassword@https://my.meowserver.example:8443/meow/
func CreateServerFromMeowUrl ( meowurl string ) * Server {
2024-04-12 14:37:20 +02:00
uid := strings . Replace ( meowurl [ 7 : ] , "//" , "://" , 1 )
2024-03-26 14:57:33 +01:00
return CreateServerFromUid ( uid )
}
2024-03-26 15:29:52 +01:00
// CreateServerFromInvitationLink creates a server from a meow url, ex : meow://mylogin:mypassword@https://my.meowserver.example:8443/meow?invitationCode
2024-03-26 14:57:33 +01:00
func CreateServerFromInvitationLink ( meowurl string ) * Server {
// remove the invitation code, last token after a /
2024-03-26 15:29:52 +01:00
meowurlTable := strings . Split ( meowurl , "?" )
2024-03-26 14:57:33 +01:00
// join all elements with / except the last one
2024-03-26 15:29:52 +01:00
meowSrvUrl := meowurlTable [ 0 ]
return CreateServerFromMeowUrl ( meowSrvUrl )
2024-03-26 14:57:33 +01:00
}
2024-02-07 16:08:24 +01:00
// GetServerCard returns a server card from a server
func ( ints * Server ) GetServerCard ( ) * meowlib . ServerCard {
var sc meowlib . ServerCard
sc . Name = ints . Name
sc . PublicKey = ints . PublicKey
sc . Description = ints . Description
sc . Url = ints . Url
sc . Login = ints . Login
sc . Password = ints . Password
return & sc
}
2024-02-08 22:17:16 +01:00
func ( sc * Server ) GetUid ( ) string {
if len ( sc . Login ) > 0 || len ( sc . Password ) > 0 {
return sc . Login + ":" + sc . Password + "@" + sc . Url
}
return sc . Url
}
2024-03-26 14:57:33 +01:00
func ( sc * Server ) GetMeowUrl ( ) string {
if len ( sc . Login ) > 0 || len ( sc . Password ) > 0 {
return sc . Login + ":" + sc . Password + "@" + sc . Url
}
return "meow://" + sc . Url
}
2023-11-09 22:46:39 +01:00
// Create a server from a server card
2023-11-08 22:01:44 +01:00
func CreateServerFromServerCard ( server * meowlib . ServerCard ) * Server {
var is Server
2024-02-07 16:08:24 +01:00
is . Name = server . Name
is . PublicKey = server . PublicKey
is . Description = server . Description
is . Url = server . Url
is . Login = server . Login
is . Password = server . Password
2023-12-09 20:01:19 +01:00
is . UserKp = meowlib . NewKeyPair ( )
2022-09-19 13:26:27 +02:00
return & is
}
2022-09-06 17:07:35 +02:00
// AsymEncryptMessage prepares a message to send to a specific internal server
2023-11-08 22:01:44 +01:00
func ( ints * Server ) AsymEncryptMessage ( Message [ ] byte ) ( * meowlib . EncryptedMessage , error ) {
2022-12-19 20:15:53 +01:00
var enc * meowlib . EncryptedMessage
2024-02-07 16:08:24 +01:00
enc , err := meowlib . AsymEncryptAndSign ( ints . PublicKey , ints . UserKp . Private , Message )
2022-09-06 09:30:45 +02:00
if err != nil {
fmt . Println ( err . Error ( ) )
2022-12-19 20:15:53 +01:00
return nil , err
2022-09-06 09:30:45 +02:00
}
2022-12-19 20:15:53 +01:00
return enc , err
2022-09-06 09:30:45 +02:00
}
2022-09-06 17:07:35 +02:00
// AsymDecryptMessage reads a message from a specific internal server
2023-11-08 22:01:44 +01:00
func ( ints * Server ) AsymDecryptMessage ( Message [ ] byte , Signature [ ] byte ) ( DecryptedMessage [ ] byte , err error ) {
2024-02-07 16:08:24 +01:00
DecryptedMessage , err = meowlib . AsymDecryptAndCheck ( ints . UserKp . Private , ints . PublicKey , Message , Signature )
2022-09-06 09:30:45 +02:00
if err != nil {
fmt . Println ( err . Error ( ) )
return nil , err
}
2022-09-06 17:07:35 +02:00
return DecryptedMessage , err
2022-09-06 09:30:45 +02:00
}
2022-09-18 18:09:27 +02:00
2023-11-06 22:44:21 +01:00
// BuildToServerMessageFromUserMessage creates a basic message to server from a single packed user message and returns a meowlib.ToServerMessage
2023-11-08 22:01:44 +01:00
func ( ints * Server ) BuildToServerMessageFromUserMessage ( usermsg * meowlib . PackedUserMessage ) * meowlib . ToServerMessage {
2022-09-18 18:09:27 +02:00
var msg meowlib . ToServerMessage
2022-09-19 20:16:57 +02:00
msg . Uuid = uuid . New ( ) . String ( )
2022-09-18 18:09:27 +02:00
msg . Type = "1"
2023-12-09 20:01:19 +01:00
msg . From = ints . UserKp . Public
2022-09-18 18:09:27 +02:00
msg . Messages = append ( msg . Messages , usermsg )
2022-12-18 20:37:26 +01:00
return & msg
}
2023-11-06 22:44:21 +01:00
// BuildMessageSendingMessage creates a basic message to server from a single packed user message and returns it as protobuf serialized byte array
2023-11-08 22:01:44 +01:00
func ( ints * Server ) BuildMessageSendingMessage ( usermsg * meowlib . PackedUserMessage ) ( [ ] byte , error ) {
2022-12-18 20:37:26 +01:00
msg := ints . BuildToServerMessageFromUserMessage ( usermsg )
out , err := proto . Marshal ( msg )
2022-09-18 18:09:27 +02:00
if err != nil {
return nil , err
}
return out , nil
}
2023-11-06 22:44:21 +01:00
// BuildMessageRequestMessage creates a message lookup message to server and returns it as protobuf serialized byte array
2023-11-08 22:01:44 +01:00
func ( ints * Server ) BuildMessageRequestMessage ( lookupKeys [ ] string ) ( [ ] byte , error ) {
2022-09-18 18:09:27 +02:00
var msg meowlib . ToServerMessage
2022-09-19 20:16:57 +02:00
msg . Uuid = uuid . New ( ) . String ( )
2022-09-18 18:09:27 +02:00
msg . Type = "1"
2023-12-09 20:01:19 +01:00
msg . From = ints . UserKp . Public
2022-09-18 18:09:27 +02:00
out , err := proto . Marshal ( & msg )
if err != nil {
return nil , err
}
return out , nil
}
2022-09-19 13:26:27 +02:00
2023-11-08 21:52:09 +01:00
// BuildToServerMessageInvitation creates an invitation message to server and returns it as a meowlib.ToServerMessage
2023-11-14 16:32:50 +01:00
// it takes as input a contactcard generated by Identity.InvitePeer
2024-03-31 18:22:17 +02:00
func ( ints * Server ) BuildToServerMessageInvitationCreation ( invitation * meowlib . ContactCard , password string , timeout int , shortCodeLen int ) ( * meowlib . ToServerMessage , error ) {
2023-08-29 23:40:30 +02:00
var msg meowlib . ToServerMessage
var inv meowlib . Invitation
payload , err := invitation . Compress ( )
if err != nil {
return nil , err
}
msg . Type = "1"
2023-12-09 20:01:19 +01:00
msg . From = ints . UserKp . Public
2023-11-08 21:52:09 +01:00
inv . Step = 1
2023-08-29 23:40:30 +02:00
inv . Password = password
inv . Timeout = int32 ( timeout )
2024-03-31 18:22:17 +02:00
inv . ShortcodeLen = int32 ( shortCodeLen )
2023-08-29 23:40:30 +02:00
inv . Payload = payload
msg . Invitation = & inv
return & msg , nil
}
2023-11-08 21:52:09 +01:00
// BuildToServerMessageInvitationRequest requests invitation with provided id from server and returns it as a meowlib.ToServerMessage
2023-11-14 16:32:50 +01:00
func ( ints * Server ) BuildToServerMessageInvitationRequest ( shortcode string , password string ) ( * meowlib . ToServerMessage , error ) {
2023-11-08 21:52:09 +01:00
var msg meowlib . ToServerMessage
var inv meowlib . Invitation
msg . Type = "1"
2023-12-09 20:01:19 +01:00
msg . From = ints . UserKp . Public
2023-11-08 21:52:09 +01:00
inv . Step = 2
inv . Password = password
2023-11-14 16:32:50 +01:00
inv . Shortcode = shortcode
2023-11-08 21:52:09 +01:00
msg . Invitation = & inv
return & msg , nil
}
2024-03-26 23:42:56 +01:00
// BuildToServerMessageInvitationAnswer creates an invitation answer to server and returns it as a meowlib.ToServerMessage
// it takes as input a contactcard generated by Identity.InvitePeer
2024-03-31 18:22:17 +02:00
func ( ints * Server ) BuildToServerMessageInvitationAnswer ( invitationAnswer * meowlib . PackedUserMessage , myPublicKeyForThatPeer string , invitation_id string , timeout int ) ( * meowlib . ToServerMessage , error ) {
2024-03-26 23:42:56 +01:00
var msg meowlib . ToServerMessage
var inv meowlib . Invitation
invitationPayload , err := proto . Marshal ( invitationAnswer )
if err != nil {
return nil , err
}
inv . Step = 3
2024-03-31 18:22:17 +02:00
inv . Uuid = invitation_id
2024-03-26 23:42:56 +01:00
msg . Type = "1"
msg . From = ints . UserKp . Public
inv . From = myPublicKeyForThatPeer
inv . Payload = invitationPayload
msg . Invitation = & inv
return & msg , nil
}
// BuildToServerMessageInvitationAnswerRequest requests invitation answer with provided id from server and returns it as a meowlib.ToServerMessage
func ( ints * Server ) BuildToServerMessageInvitationAnswerRequest ( invitationId string ) ( * meowlib . ToServerMessage , error ) {
var msg meowlib . ToServerMessage
var inv meowlib . Invitation
msg . Type = "1"
msg . From = ints . UserKp . Public
inv . Step = 4
inv . Uuid = invitationId
msg . Invitation = & inv
return & msg , nil
}
2023-11-09 22:46:39 +01:00
// PackServerMessage
2023-11-08 22:01:44 +01:00
func ( ints * Server ) PackServerMessage ( payload [ ] byte , signature [ ] byte ) ( protoPackedMessage [ ] byte , err error ) {
2022-09-19 13:26:27 +02:00
var msg meowlib . PackedServerMessage
2023-12-09 20:01:19 +01:00
msg . From = ints . UserKp . Public
2022-09-19 13:26:27 +02:00
msg . Payload = payload
msg . Signature = signature
out , err := proto . Marshal ( & msg )
if err != nil {
return nil , err
}
return out , nil
}
2022-10-22 14:41:48 +02:00
2023-11-08 22:01:44 +01:00
func ( ints * Server ) UnPackServerMessage ( protoPackedMessage [ ] byte ) ( payload [ ] byte , signature [ ] byte , err error ) {
2022-10-22 14:41:48 +02:00
msg := & meowlib . PackedServerMessage { }
if err := proto . Unmarshal ( protoPackedMessage , msg ) ; err != nil {
return nil , nil , err
}
return msg . Payload , msg . Signature , nil
}
2022-12-18 20:59:27 +01:00
2023-11-08 22:01:44 +01:00
func ( srv * Server ) ProcessOutboundMessage ( toServerMessage * meowlib . ToServerMessage ) ( [ ] byte , error ) {
2022-12-18 20:59:27 +01:00
byteToServerMessage , err := proto . Marshal ( toServerMessage )
if err != nil {
return nil , err
}
// Encrypting it
2022-12-19 20:15:53 +01:00
encToServer , err := srv . AsymEncryptMessage ( byteToServerMessage )
2022-12-18 20:59:27 +01:00
if err != nil {
return nil , err
}
// Packing it
2022-12-19 20:15:53 +01:00
protoPackedServerMsg , err := srv . PackServerMessage ( encToServer . Data , encToServer . Signature )
2022-12-18 20:59:27 +01:00
if err != nil {
return nil , err
}
return protoPackedServerMsg , nil
}
2023-11-08 22:01:44 +01:00
func ( srv * Server ) ProcessInboundServerResponse ( msg [ ] byte ) ( * meowlib . FromServerMessage , error ) {
2022-12-18 20:59:27 +01:00
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
}