Files

109 lines
3.0 KiB
Go

package main
import (
"fmt"
"log"
"net"
"net/http"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
// "server/api" // This would be the generated package
)
const version = "1.0.0"
// CoordinatorServer implements the Coordinator gRPC service
type CoordinatorServer struct {
// In a full implementation, we would have a Redis client here
// nodes map[string]*NodeInfo
}
func (s *CoordinatorServer) RegisterNode(ctx interface{}, req interface{}) (interface{}, error) {
fmt.Println("RegisterNode called")
return nil, nil // Placeholder for actual implementation
}
func (s *CoordinatorServer) Heartbeat(ctx interface{}, req interface{}) (interface{}, error) {
fmt.Println("Heartbeat called")
return nil, nil
}
func (s *CoordinatorServer) GetPeerEndpoint(ctx interface{}, req interface{}) (interface{}, error) {
fmt.Println("GetPeerEndpoint called")
return nil, nil
}
func (s *CoordinatorServer) SignalConnection(ctx interface{}, req interface{}) (interface{}, error) {
fmt.Println("SignalConnection called")
return nil, nil
}
// STUN server implementation
func startSTUNServer(port int) {
addr := fmt.Sprintf(":%d", port)
conn, err := net.ListenUDP("udp", &net.UDPAddr{Port: port})
if err != nil {
log.Fatalf("STUN server failed to start: %v", err)
}
defer conn.Close()
fmt.Printf("STUN server listening on %s\n", addr)
buf := make([]byte, 1024)
for {
n, remoteAddr, err := conn.ReadFromUDP(buf)
if err != nil {
log.Printf("STUN read error: %v", err)
continue
}
fmt.Printf("Received STUN request from %s (size: %d)\n", remoteAddr, n)
// Simplified STUN response: send the remote address back to the client
// In a real STUN server, we would follow RFC 5389
response := []byte(fmt.Sprintf("STUN_RESP:%s", remoteAddr.String()))
_, err = conn.WriteToUDP(response, remoteAddr)
if err != nil {
log.Printf("STUN write error: %v", err)
}
}
}
func main() {
// Start STUN server in a goroutine
go startSTUNServer(3478)
// Serve HTML Dashboard
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// Note: In a production app, we would use a template to inject the version
// For this task, we serve the file and suggest using a template for dynamic injection
http.ServeFile(w, r, "C:\\Users\\jadon\\Documents\\vscode\\tailscale-test\\meshvpn-dashboard\\index.html")
})
// Start HTTP server in a goroutine
go func() {
fmt.Printf("HTTP Dashboard listening on :8080 (Version: %s)\n", version)
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatalf("HTTP server failed: %v", err)
}
}()
// Start gRPC Coordinator server
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
// In a real setup, we'd register the generated server:
// pb.RegisterCoordinatorServer(s, &CoordinatorServer{})
reflection.Register(s)
fmt.Println("Coordinator Server listening on :50051")
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}