108 lines
2.6 KiB
Go
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
|
|
}
|
|
}
|
|
}
|