[PD1] Added SQLlite queries and minor protocol changes
This commit is contained in:
parent
1e12bcde6c
commit
23584e2901
6 changed files with 213 additions and 46 deletions
|
@ -3,6 +3,7 @@ module PD1
|
||||||
go 1.22.2
|
go 1.22.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
||||||
golang.org/x/crypto v0.11.0 // indirect
|
golang.org/x/crypto v0.11.0 // indirect
|
||||||
software.sslmate.com/src/go-pkcs12 v0.4.0 // indirect
|
software.sslmate.com/src/go-pkcs12 v0.4.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
|
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
|
||||||
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||||
software.sslmate.com/src/go-pkcs12 v0.4.0 h1:H2g08FrTvSFKUj+D309j1DPfk5APnIdAQAB8aEykJ5k=
|
software.sslmate.com/src/go-pkcs12 v0.4.0 h1:H2g08FrTvSFKUj+D309j1DPfk5APnIdAQAB8aEykJ5k=
|
||||||
|
|
|
@ -30,7 +30,7 @@ func Run() {
|
||||||
defer cl.Connection.Conn.Close()
|
defer cl.Connection.Conn.Close()
|
||||||
// TODO: getuserinfo client cert
|
// TODO: getuserinfo client cert
|
||||||
// TODO: ask server for the recieving client's cert
|
// TODO: ask server for the recieving client's cert
|
||||||
certRequestPacket := protocol.NewRequestPubKey()
|
certRequestPacket := protocol.NewRequestUserCertPacket(uid)
|
||||||
cl.Connection.Send(certRequestPacket)
|
cl.Connection.Send(certRequestPacket)
|
||||||
certPacket := cl.Connection.Receive()
|
certPacket := cl.Connection.Receive()
|
||||||
// TODO: cipherContent := cryptoUtils.encryptMessageContent()
|
// TODO: cipherContent := cryptoUtils.encryptMessageContent()
|
||||||
|
|
|
@ -7,12 +7,12 @@ import (
|
||||||
type PacketType int
|
type PacketType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ReqPK PacketType = iota
|
ReqUserCertPkt PacketType = iota
|
||||||
ReqAllMsg
|
ReqAllMsgPkt
|
||||||
ReqMsg
|
ReqMsgPkt
|
||||||
SubmitMsg
|
SubmitMsgPkt
|
||||||
SendPK
|
SendUserCertPkt
|
||||||
Msg
|
ServerMsgPkt
|
||||||
)
|
)
|
||||||
|
|
||||||
type PacketBody interface{}
|
type PacketBody interface{}
|
||||||
|
@ -22,91 +22,91 @@ type Packet struct {
|
||||||
Body PacketBody
|
Body PacketBody
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client --> Server: Ask for a user's public key
|
// Client --> Server: Ask for a user's certificate
|
||||||
type RequestPubKey struct {
|
type RequestUserCertPacket struct {
|
||||||
FromUID string
|
UID string
|
||||||
KeyUID string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRequestPubKey(fromUID, keyUID string) Packet {
|
func NewRequestUserCertPacket(UID string) Packet {
|
||||||
return Packet{
|
return Packet{
|
||||||
Flag: ReqPK,
|
Flag: ReqUserCertPkt,
|
||||||
Body: RequestPubKey{
|
Body: RequestUserCertPacket{
|
||||||
FromUID: fromUID,
|
UID: UID,
|
||||||
KeyUID: keyUID,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client --> Server: Ask for all the client's messages in the queue
|
// Client --> Server: Ask for all the client's messages in the queue
|
||||||
type RequestAllMsg struct {
|
type RequestAllMsgPacket struct {
|
||||||
FromUID string
|
FromUID string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRequestAllMsg(fromUID string) Packet {
|
func NewRequestAllMsgPacket(fromUID string) Packet {
|
||||||
return Packet{
|
return Packet{
|
||||||
Flag: ReqAllMsg,
|
Flag: ReqAllMsgPkt,
|
||||||
Body: RequestAllMsg{
|
Body: RequestAllMsgPacket{
|
||||||
FromUID: fromUID,
|
FromUID: fromUID,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client --> Server: Ask for a specific message in the queue
|
// Client --> Server: Ask for a specific message in the queue
|
||||||
type RequestMsg struct {
|
type RequestMsgPacket struct {
|
||||||
Num uint16
|
Num uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRequestMsg(num uint16) Packet {
|
func NewRequestMsgPacket(num uint16) Packet {
|
||||||
return Packet{
|
return Packet{
|
||||||
Flag: ReqMsg,
|
Flag: ReqMsgPkt,
|
||||||
Body: RequestMsg{
|
Body: RequestMsgPacket{
|
||||||
Num: num,
|
Num: num,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client --> Server: Send message from client to server
|
// Client --> Server: Send message from client to server
|
||||||
type SubmitMessage struct {
|
type SubmitMessagePacket struct {
|
||||||
ToUID string
|
ToUID string
|
||||||
Content []byte
|
Content []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSubmitMessage(toUID string, content []byte) Packet {
|
func NewSubmitMessagePacket(toUID string, content []byte) Packet {
|
||||||
return Packet{
|
return Packet{
|
||||||
Flag: SubmitMsg,
|
Flag: SubmitMsgPkt,
|
||||||
Body: SubmitMessage{
|
Body: SubmitMessagePacket{
|
||||||
ToUID: toUID,
|
ToUID: toUID,
|
||||||
Content: content},
|
Content: content},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server --> Client: Send the client the requested public key
|
// Server --> Client: Send the client the requested public key
|
||||||
type SendPubKey struct {
|
type SendUserCertPacket struct {
|
||||||
|
UID string
|
||||||
Key []byte
|
Key []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSendPubKey(key []byte) Packet {
|
func NewSendUserCertPacket(uid string, key []byte) Packet {
|
||||||
return Packet{
|
return Packet{
|
||||||
Flag: SendPK,
|
Flag: SendUserCertPkt,
|
||||||
Body: SendPubKey{
|
Body: SendUserCertPacket{
|
||||||
|
UID: uid,
|
||||||
Key: key,
|
Key: key,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server --> Client: Send the client a message
|
// Server --> Client: Send the client a message
|
||||||
type ServerMessage struct {
|
type ServerMessagePacket struct {
|
||||||
FromUID string
|
FromUID string
|
||||||
ToUID string
|
ToUID string
|
||||||
Content []byte
|
Content []byte
|
||||||
Timestamp time.Time
|
Timestamp time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMessage(fromUID, toUID string, content []byte, timestamp time.Time) Packet {
|
func NewMessagePacket(fromUID, toUID string, content []byte, timestamp time.Time) Packet {
|
||||||
return Packet{
|
return Packet{
|
||||||
Flag: Msg,
|
Flag: Msg,
|
||||||
Body: ServerMessage{
|
Body: ServerMessagePacket{
|
||||||
FromUID: fromUID,
|
FromUID: fromUID,
|
||||||
ToUID: toUID,
|
ToUID: toUID,
|
||||||
Content: content,
|
Content: content,
|
||||||
|
|
|
@ -1 +1,156 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"PD1/internal/protocol"
|
||||||
|
"database/sql"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DataStore struct {
|
||||||
|
db *sql.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func OpenDB() DataStore {
|
||||||
|
db, err := sql.Open("sqlite3", "server.db")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error opening db file")
|
||||||
|
}
|
||||||
|
return DataStore{db: db}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds DataStore) CreateTables() error {
|
||||||
|
// Create users table
|
||||||
|
_, err := ds.db.Exec(`CREATE TABLE IF NOT EXISTS users (
|
||||||
|
UID TEXT PRIMARY KEY,
|
||||||
|
userCert BLOB
|
||||||
|
)`)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create messages table
|
||||||
|
_, err = ds.db.Exec(`CREATE TABLE IF NOT EXISTS messages (
|
||||||
|
fromUID TEXT,
|
||||||
|
toUID TEXT,
|
||||||
|
timestamp TIMESTAMP,
|
||||||
|
content BLOB,
|
||||||
|
PRIMARY KEY (toUID, fromUID, timestamp),
|
||||||
|
FOREIGN KEY(fromUID) REFERENCES users(UID),
|
||||||
|
FOREIGN KEY(toUID) REFERENCES users(UID)
|
||||||
|
)`)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds DataStore) GetMessage(toUID string, position int) protocol.ServerMessagePacket {
|
||||||
|
|
||||||
|
var serverMessage protocol.ServerMessagePacket
|
||||||
|
query := `
|
||||||
|
SELECT fromUID, toUID, content, timestamp
|
||||||
|
FROM messages
|
||||||
|
WHERE toUID = ?
|
||||||
|
AND status = 0
|
||||||
|
ORDER BY timestamp
|
||||||
|
LIMIT 1 OFFSET ?
|
||||||
|
`
|
||||||
|
// Execute the query
|
||||||
|
row := ds.db.QueryRow(query, toUID, position)
|
||||||
|
err := row.Scan(&serverMessage.FromUID, &serverMessage.ToUID, &serverMessage.Content, &serverMessage.Timestamp)
|
||||||
|
if err != nil {
|
||||||
|
log.Panicln("Could not map DB query to ServerMessage")
|
||||||
|
}
|
||||||
|
return serverMessage
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds DataStore) MarkMessageInQueueAsRead(toUID string, position int) error {
|
||||||
|
query := `
|
||||||
|
UPDATE messages
|
||||||
|
SET status = 1
|
||||||
|
WHERE toUID = ? AND status = 0
|
||||||
|
ORDER BY timestamp
|
||||||
|
LIMIT 1 OFFSET ?
|
||||||
|
`
|
||||||
|
|
||||||
|
// Execute the SQL statement
|
||||||
|
_, err := ds.db.Exec(query, toUID, position)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds DataStore) GetAllMessages(toUID string) []protocol.Packet {
|
||||||
|
var messagePackets []protocol.Packet
|
||||||
|
|
||||||
|
// Query to retrieve all messages from the user's queue
|
||||||
|
query := `
|
||||||
|
SELECT fromUID, toUID, content, timestamp
|
||||||
|
FROM messages
|
||||||
|
WHERE toUID = ?
|
||||||
|
AND status = 0
|
||||||
|
ORDER BY timestamp
|
||||||
|
`
|
||||||
|
|
||||||
|
// Execute the query
|
||||||
|
rows, err := ds.db.Query(query, toUID)
|
||||||
|
if err != nil {
|
||||||
|
log.Panicln("Failed to execute query:", err)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
// Iterate through the result set and scan each row into a ServerMessage struct
|
||||||
|
for rows.Next() {
|
||||||
|
var fromUID string
|
||||||
|
var toUID string
|
||||||
|
var content []byte
|
||||||
|
var timestamp time.Time
|
||||||
|
if err := rows.Scan(&fromUID, &toUID, &content, ×tamp); err != nil {
|
||||||
|
log.Panicln("Failed to scan row:", err)
|
||||||
|
}
|
||||||
|
message := protocol.NewMessagePacket(fromUID, toUID, content, timestamp)
|
||||||
|
messagePackets = append(messagePackets, message)
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
log.Panicln("Error when getting user's messages")
|
||||||
|
}
|
||||||
|
|
||||||
|
return messagePackets
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds DataStore) AddMessageToQueue(uid string, message protocol.SubmitMessagePacket) {
|
||||||
|
query := `
|
||||||
|
INSERT INTO messages (fromUID, toUID, content, timestamp, status)
|
||||||
|
VALUES (?, ?, ?, ?, 0)
|
||||||
|
`
|
||||||
|
|
||||||
|
// Execute the SQL statement
|
||||||
|
currentTime := time.Now()
|
||||||
|
_, err := ds.db.Exec(query, uid, message.ToUID, message.Content, currentTime)
|
||||||
|
if err != nil {
|
||||||
|
log.Panicln("Error adding message to database")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds DataStore) GetUserCertificate(uid string) protocol.Packet {
|
||||||
|
query := `
|
||||||
|
SELECT userCert
|
||||||
|
FROM users
|
||||||
|
WHERE UID = ?
|
||||||
|
`
|
||||||
|
|
||||||
|
// Execute the SQL query
|
||||||
|
var userCert []byte
|
||||||
|
err := ds.db.QueryRow(query, uid).Scan(&userCert)
|
||||||
|
if err != nil {
|
||||||
|
log.Panicln("Error getting user certificate from the database")
|
||||||
|
}
|
||||||
|
return protocol.NewSendUserCertPacket(uid, userCert)
|
||||||
|
}
|
||||||
|
|
|
@ -6,19 +6,23 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func clientHandler(connection networking.Connection[protocol.Packet]) {
|
func clientHandler(connection networking.Connection[protocol.Packet], dataStore DataStore) {
|
||||||
defer connection.Conn.Close()
|
defer connection.Conn.Close()
|
||||||
|
|
||||||
|
// FIX: GET THE UID FROM THE USER CERTIFICATE FROM THE TLS SESSION
|
||||||
|
uid := "0"
|
||||||
|
|
||||||
for {
|
for {
|
||||||
pac := connection.Receive()
|
pac := connection.Receive()
|
||||||
switch pac.Flag {
|
switch pac.Flag {
|
||||||
case protocol.ReqPK:
|
case protocol.ReqUserCertPkt:
|
||||||
fmt.Println("ReqPK")
|
userCertPacket := dataStore.GetUserCertificate(uid)
|
||||||
case protocol.ReqAllMsg:
|
connection.Send(userCertPacket)
|
||||||
|
case protocol.ReqAllMsgPkt:
|
||||||
fmt.Println("ReqAllMsg")
|
fmt.Println("ReqAllMsg")
|
||||||
case protocol.ReqMsg:
|
case protocol.ReqMsgPkt:
|
||||||
fmt.Println("ReqMsg")
|
fmt.Println("ReqMsg")
|
||||||
case protocol.SubmitMsg:
|
case protocol.SubmitMsgPkt:
|
||||||
fmt.Println("SubmitMsg")
|
fmt.Println("SubmitMsg")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +30,11 @@ func clientHandler(connection networking.Connection[protocol.Packet]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Run(port int) {
|
func Run(port int) {
|
||||||
|
//Open connection to DB
|
||||||
|
dataStore := OpenDB()
|
||||||
|
defer dataStore.db.Close()
|
||||||
|
|
||||||
|
//Create server listener
|
||||||
server := networking.NewServer[protocol.Packet](port)
|
server := networking.NewServer[protocol.Packet](port)
|
||||||
go server.ListenLoop()
|
go server.ListenLoop()
|
||||||
|
|
||||||
|
@ -33,6 +42,6 @@ func Run(port int) {
|
||||||
//Receive Connection via channel
|
//Receive Connection via channel
|
||||||
conn := <-server.C
|
conn := <-server.C
|
||||||
//Launch client handler via clientHandler
|
//Launch client handler via clientHandler
|
||||||
go clientHandler(conn)
|
go clientHandler(conn, dataStore)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue