[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)
}
}