DHT-kademlia-P2Psec/cmd/api_server.go
2024-09-13 14:04:40 +09:00

108 lines
2.6 KiB
Go

package main
import (
"encoding/binary"
kademlia "gitlab.lrz.de/netintum/teaching/p2psec_projects_2024/DHT-6/pkg"
"io"
"log"
"net"
"strconv"
)
// Server configuration and message type identifiers
type APIServer struct {
dht *kademlia.DHT
}
func initializeAPIServer(config *kademlia.Config, dht *kademlia.DHT) {
server := APIServer{}
server.dht = dht
listener, err := net.Listen("tcp", config.APIAddress+":"+strconv.Itoa(int(config.APIPort)))
if err != nil {
log.Fatalln("[API Server] Error starting server: ", err)
}
defer listener.Close()
for {
connection, err := listener.Accept()
if err != nil {
log.Println("[API Server] Error accepting connection: ", err)
continue
}
// Handle in seperate thread
go server.handleAPIRequest(connection)
}
}
func (s *APIServer) handleAPIRequest(connection net.Conn) {
buf := make([]byte, 4)
_, err := connection.Read(buf)
if err != nil {
log.Println("[API Server] Error reading message: ", err)
return
}
defer connection.Close()
size := binary.BigEndian.Uint16(buf[:2])
messageType := binary.BigEndian.Uint16(buf[2:])
// Subtract 4 bytes used for size and message type
messageBody := make([]byte, size-4)
io.ReadFull(connection, messageBody)
// Combine body and head to get the full message again
message := append(buf, messageBody...)
switch messageType {
case kademlia.PUT:
s.handlePut(message, connection)
case kademlia.GET:
s.handleGet(message, connection)
default:
log.Println("[API Server] Invalid message type")
}
}
func (s *APIServer) handlePut(data []byte, connection net.Conn) {
packet, err := kademlia.ParsePutPacket(data)
if err != nil {
log.Printf("[API Server] Error receiving PUT request: %v", err)
return
}
// Store the value in the network
s.dht.Store(packet.Key, packet.Value, packet.TTL, uint16(packet.Replication))
}
func (s *APIServer) handleGet(data []byte, connection net.Conn) {
packet, err := kademlia.ParseGetPacket(data)
if err != nil {
log.Printf("[API Server] Error receiving GET request: %v", err)
return
}
// Query the network for the value
val, exists := s.dht.Get(packet.Key)
if exists {
response := kademlia.DHTSuccessPacket{
Key: packet.Key,
Value: val,
}
_, err := connection.Write(kademlia.SerialiseSuccessPacket(response))
if err != nil {
log.Println("[API Server] Error sending GET response: ", err)
return
}
} else {
response := kademlia.DHTFailurePacket{Key: packet.Key}
_, err := connection.Write(kademlia.SerialiseFailurePacket(response))
if err != nil {
log.Println("[API Server] Error sending GET response: ", err)
return
}
}
}