[PD1] Cleaned up protocol,database and receiving multiple messageInfos

This commit is contained in:
Afonso Franco 2024-04-20 17:16:52 +01:00
parent 4c141bbc6e
commit f3cf9cfc40
Signed by: afonso
SSH key fingerprint: SHA256:aiLbdlPwXKJS5wMnghdtod0SPy8imZjlVvCyUX9DJNk
6 changed files with 347 additions and 231 deletions

View file

@ -30,52 +30,46 @@ func Run() {
panic("Insufficient arguments for 'send' command. Usage: send <UID> <SUBJECT>")
}
uid := flag.Arg(1)
subject := flag.Arg(2)
messageBody := readMessageBody()
plainSubject := flag.Arg(2)
plainBody := readStdin("Enter message content (limited to 1000 bytes):")
//Turn content to bytes
marshaledSubject := Marshal(subject)
marshaledBody := Marshal(messageBody)
plainSubjectBytes := Marshal(plainSubject)
plainBodyBytes := Marshal(plainBody)
cl := networking.NewClient[protocol.Packet](&clientKeyStore)
defer cl.Connection.Conn.Close()
uidCert := getUserCert(cl, uid)
if uidCert == nil {
receiverCert := getUserCert(cl, uid)
if receiverCert == nil {
return
}
encryptedSubject := clientKeyStore.EncryptMessageContent(uidCert, marshaledSubject)
encryptedBody := clientKeyStore.EncryptMessageContent(uidCert, marshaledBody)
submitMessage := protocol.NewSubmitMessagePacket(uid, encryptedSubject, encryptedBody)
if !cl.Connection.Send(submitMessage) {
subject := clientKeyStore.EncryptMessageContent(receiverCert, plainSubjectBytes)
body := clientKeyStore.EncryptMessageContent(receiverCert, plainBodyBytes)
sendMsgPacket := protocol.NewSendMsgPacket(uid, subject, body)
if !cl.Connection.Send(sendMsgPacket) {
return
}
cl.Connection.Conn.Close()
case "askqueue":
cl := networking.NewClient[protocol.Packet](&clientKeyStore)
defer cl.Connection.Conn.Close()
requestUnreadMsgsQueuePacket := protocol.NewRequestUnreadMsgsQueuePacket()
if !cl.Connection.Send(requestUnreadMsgsQueuePacket) {
return
}
serverMessagePackets, certificates := getManyMessagesInfo(cl)
var clientMessages []ClientMessageInfo
for _, message := range serverMessagePackets {
senderCert, ok := certificates[message.FromUID]
if ok {
decryptedSubjectBytes := clientKeyStore.DecryptMessageContent(senderCert, message.Subject)
subject := Unmarshal(decryptedSubjectBytes)
clientMessage := newClientMessageInfo(message.Num, message.FromUID, subject, message.Timestamp)
clientMessages = append(clientMessages, clientMessage)
pageInput := flag.Arg(1)
page := 1
if pageInput != "" {
if val, err := strconv.Atoi(pageInput); err == nil {
page = max(1, val)
}
}
pageSizeInput := flag.Arg(2)
pageSize := 5
if pageSizeInput != "" {
if val, err := strconv.Atoi(pageSizeInput); err == nil {
pageSize = max(1, val)
}
}
//Sort the messages
sort.Slice(clientMessages, func(i, j int) bool {
return clientMessages[i].Num > clientMessages[j].Num
})
showMessagesInfo(clientMessages)
cl := networking.NewClient[protocol.Packet](&clientKeyStore)
defer cl.Connection.Conn.Close()
askQueue(cl,clientKeyStore, page, pageSize)
case "getmsg":
if flag.NArg() < 2 {
@ -84,26 +78,26 @@ func Run() {
numString := flag.Arg(1)
cl := networking.NewClient[protocol.Packet](&clientKeyStore)
defer cl.Connection.Conn.Close()
num,err :=strconv.Atoi(numString)
if err!=nil{
log.Panicln("NUM argument provided is not a number")
}
packet := protocol.NewRequestMsgPacket(num)
cl.Connection.Send(packet)
num, err := strconv.Atoi(numString)
if err != nil {
log.Panicln("NUM argument provided is not a number")
}
packet := protocol.NewGetMsgPacket(num)
cl.Connection.Send(packet)
receivedMsgPacket, active := cl.Connection.Receive()
if !active {
return
}
answerGetMsg := protocol.UnmarshalAnswerGetMsg(receivedMsgPacket.Body)
senderCert := getUserCert(cl, answerGetMsg.FromUID)
decSubjectBytes := clientKeyStore.DecryptMessageContent(senderCert, answerGetMsg.Subject)
decBodyBytes := clientKeyStore.DecryptMessageContent(senderCert, answerGetMsg.Body)
subject := Unmarshal(decSubjectBytes)
body := Unmarshal(decBodyBytes)
message := newClientMessage(answerGetMsg.FromUID, answerGetMsg.ToUID, subject, body, answerGetMsg.Timestamp)
showMessage(message)
receivedMsgPacket,active := cl.Connection.Receive()
if !active{
return
}
serverMessagePacket := protocol.UnmarshalServerMessagePacket(receivedMsgPacket.Body)
senderCert := getUserCert(cl, serverMessagePacket.FromUID)
decryptedSubjectBytes := clientKeyStore.DecryptMessageContent(senderCert, serverMessagePacket.Subject)
decryptedBodyBytes := clientKeyStore.DecryptMessageContent(senderCert, serverMessagePacket.Body)
subject := Unmarshal(decryptedSubjectBytes)
body := Unmarshal(decryptedBodyBytes)
message := newClientMessage(serverMessagePacket.FromUID, serverMessagePacket.ToUID, subject, body, serverMessagePacket.Timestamp)
showMessage(message)
case "help":
showHelp()
@ -114,43 +108,33 @@ func Run() {
}
func getUserCert(cl networking.Client[protocol.Packet], uid string) *x509.Certificate {
certRequestPacket := protocol.NewRequestUserCertPacket(uid)
if !cl.Connection.Send(certRequestPacket) {
getUserCertPacket := protocol.NewGetUserCertPacket(uid)
if !cl.Connection.Send(getUserCertPacket) {
return nil
}
var certPacket *protocol.Packet
certPacket, active := cl.Connection.Receive()
var answerGetUserCertPacket *protocol.Packet
answerGetUserCertPacket, active := cl.Connection.Receive()
if !active {
return nil
}
uidCertInBytes := protocol.UnmarshalSendUserCertPacket(certPacket.Body)
uidCert, err := x509.ParseCertificate(uidCertInBytes.Certificate)
answerGetUserCert := protocol.UnmarshalAnswerGetUserCert(answerGetUserCertPacket.Body)
userCert, err := x509.ParseCertificate(answerGetUserCert.Certificate)
if err != nil {
return nil
}
return uidCert
return userCert
}
func getManyMessagesInfo(cl networking.Client[protocol.Packet]) ([]protocol.ServerMessageInfoPacket, map[string]*x509.Certificate) {
//Create the slice to hold the incoming messages before decrypting
//Create the map to hold the sender certificates
//Create sync mutexes
serverMessageInfoPackets := []protocol.ServerMessageInfoPacket{}
//Run while message isn't the last one
msg := protocol.ServerMessageInfoPacket{}
for !msg.Last {
sendMsgPacket, active := cl.Connection.Receive()
if !active {
return nil, nil
}
msg = protocol.UnmarshalServerMessageInfoPacket(sendMsgPacket.Body)
//Lock and append
serverMessageInfoPackets = append(serverMessageInfoPackets, msg)
func getManyMessagesInfo(cl networking.Client[protocol.Packet]) (protocol.AnswerGetUnreadMsgsInfo, map[string]*x509.Certificate) {
answerGetUnreadMsgsInfoPacket, active := cl.Connection.Receive()
if !active {
return protocol.NewAnswerGetUnreadMsgsInfo(0, 0, nil), nil
}
answerGetUnreadMsgsInfo := protocol.UnmarshalAnswerGetUnreadMsgsInfo(answerGetUnreadMsgsInfoPacket.Body)
//Create Set of needed certificates
senderSet := map[string]bool{}
for _, messageInfo := range serverMessageInfoPackets {
for _, messageInfo := range answerGetUnreadMsgsInfo.MessagesInfo {
senderSet[messageInfo.FromUID] = true
}
certificatesMap := map[string]*x509.Certificate{}
@ -159,5 +143,37 @@ func getManyMessagesInfo(cl networking.Client[protocol.Packet]) ([]protocol.Serv
senderCert := getUserCert(cl, senderUID)
certificatesMap[senderUID] = senderCert
}
return serverMessageInfoPackets, certificatesMap
return answerGetUnreadMsgsInfo, certificatesMap
}
func askQueue(cl networking.Client[protocol.Packet],clientKeyStore cryptoUtils.KeyStore, page int, pageSize int) {
requestUnreadMsgsQueuePacket := protocol.NewGetUnreadMsgsInfoPacket(page, pageSize)
if !cl.Connection.Send(requestUnreadMsgsQueuePacket) {
return
}
unreadMsgsInfo, certificates := getManyMessagesInfo(cl)
var clientMessages []ClientMessageInfo
for _, message := range unreadMsgsInfo.MessagesInfo {
senderCert, ok := certificates[message.FromUID]
if ok {
decryptedSubjectBytes := clientKeyStore.DecryptMessageContent(senderCert, message.Subject)
subject := Unmarshal(decryptedSubjectBytes)
clientMessage := newClientMessageInfo(message.Num, message.FromUID, subject, message.Timestamp)
clientMessages = append(clientMessages, clientMessage)
}
}
//Sort the messages
sort.Slice(clientMessages, func(i, j int) bool {
return clientMessages[i].Num > clientMessages[j].Num
})
action := showMessagesInfo(unreadMsgsInfo.Page, unreadMsgsInfo.NumPages, clientMessages)
switch action {
case -1:
askQueue(cl, clientKeyStore , max(1,unreadMsgsInfo.Page-1) , pageSize)
case 0:
return
case 1:
askQueue(cl, clientKeyStore , max(1,unreadMsgsInfo.Page+1) , pageSize)
}
}

View file

@ -4,10 +4,11 @@ import (
"bufio"
"fmt"
"os"
"strings"
)
func readMessageBody() string {
fmt.Println("Enter message content (limited to 1000 bytes):")
func readStdin(message string) string {
fmt.Println(message)
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
// FIX: make sure this doesnt die
@ -36,15 +37,63 @@ func showHelp() {
fmt.Println("help: Imprime instruções de uso do programa.")
}
func showMessagesInfo(messages []ClientMessageInfo) {
func showMessagesInfo(page int, numPages int, messages []ClientMessageInfo) int {
if messages == nil {
fmt.Println("No unread messages in the queue")
return 0
}
for _, message := range messages {
fmt.Printf("%v:%v:%v:%v\n", message.Num, message.FromUID, message.Timestamp, message.Subject)
}
fmt.Printf("Page %v/%v\n",page,numPages)
return messagesInfoPageNavigation(page, numPages)
}
func showMessage(message ClientMessage) {
fmt.Printf("From:%v\n", message.FromUID)
fmt.Printf("To:%v\n", message.ToUID)
fmt.Printf("Subject:%v\n", message.Subject)
fmt.Printf("Body:%v\n", message.Body)
func messagesInfoPageNavigation(page int, numPages int) int {
var action string
switch page {
case 1:
if page == numPages {
action = readStdin("Actions: quit")
} else {
action = readStdin("Actions: quit/next")
}
case numPages:
action = readStdin("Actions: prev/quit")
default:
action = readStdin("prev/quit/next")
}
switch strings.ToLower(action) {
case "prev":
if page == 1 {
fmt.Println("Unavailable action: Already in first page")
messagesInfoPageNavigation(page, numPages)
} else {
return -1
}
case "quit":
return 0
case "next":
if page == numPages {
fmt.Println("Unavailable action: Already in last page")
messagesInfoPageNavigation(page, numPages)
} else {
return 1
}
default:
fmt.Println("Unknown action")
messagesInfoPageNavigation(page, numPages)
}
return 0
}
func showMessage(message ClientMessage) {
fmt.Printf("From: %s\n", message.FromUID)
fmt.Printf("To: %s\n", message.ToUID)
fmt.Printf("Subject: %s\n", message.Subject)
fmt.Printf("Body: %s\n", message.Body)
}