shelfy/main.go
2025-06-17 22:05:00 +02:00

145 lines
3.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"app/shelfly/handlers"
"app/shelfly/internal/db"
"app/shelfly/internal/library"
"app/shelfly/internal/route"
"log"
"net"
"net/http"
"time"
"github.com/huin/goupnp/dcps/internetgateway1"
"github.com/jackpal/gateway"
"github.com/jackpal/go-nat-pmp"
"github.com/gorilla/mux"
)
func main() {
// 1. Démarrer le routeur principal
r := mux.NewRouter()
// 2. Initialiser la DB
bd := db.InitDB()
// 2.1
library.CreateDefaultFolder(bd)
// 3. Routes non protégées : on les monte sur le routeur principal
route.RoutesPublic(r, bd)
// 4. Créer un sous-routeur pour les routes protégées
protected := r.PathPrefix("/").Subrouter()
// 5. Appliquer le middleware JWT à ce sous-routeur
protected.Use(handlers.AuthMiddleware)
// 6. Enregistrer les routes protégées sur ce sous-routeur
route.RoutesProtected(protected, bd)
setupPortMappingWithFallback(4000, 4000)
// 7. Lancer le serveur sur le port 4000
log.Fatal(http.ListenAndServe(":4000", r))
}
// Fonction principale à appeler dans main()
func setupPortMappingWithFallback(internalPort, externalPort uint16) {
success := setupUPnPWithRenewal(internalPort, externalPort)
if !success {
log.Println("🔁 UPnP indisponible, tentative NAT-PMP...")
setupNATPMP(internalPort, externalPort)
}
}
// UPnP avec renouvellement automatique
func setupUPnPWithRenewal(internalPort, externalPort uint16) bool {
clients, _, err := internetgateway1.NewWANIPConnection1Clients()
if err != nil {
log.Println("Erreur découverte UPnP :", err)
return false
}
if len(clients) == 0 {
log.Println("Aucun client UPnP détecté.")
return false
}
localIP := getLocalIP()
log.Println("IP locale détectée :", localIP)
if localIP == "" {
log.Println("Impossible dobtenir lIP locale")
return false
}
client := clients[0]
protocol := "TCP"
description := "GoAutoExposition"
duration := uint32(3600)
mapPort := func() error {
err := client.AddPortMapping("", externalPort, protocol, internalPort, localIP, true, description, duration)
if err != nil {
log.Println("UPnP mapping échoué :", err)
return err
}
log.Printf("✅ [UPnP] Port %d externe redirigé vers %s:%d", externalPort, localIP, internalPort)
return nil
}
// Premier essai
if err := mapPort(); err != nil {
return false
}
// Renouvellement
go func() {
for {
time.Sleep(55 * time.Minute)
mapPort()
}
}()
return true
}
// NAT-PMP fallback
func setupNATPMP(internalPort, externalPort uint16) {
gatewayIP := getGatewayIP()
if gatewayIP == "" {
log.Println("Impossible dobtenir la gateway pour NAT-PMP")
return
}
client := natpmp.NewClient(net.ParseIP(gatewayIP))
_, err := client.AddPortMapping("tcp", int(internalPort), int(externalPort), 3600)
if err != nil {
log.Println("NAT-PMP mapping échoué :", err)
} else {
log.Printf("✅ [NAT-PMP] Port %d externe redirigé vers local :%d via NAT-PMP", externalPort, internalPort)
}
}
// Obtenir IP locale
func getLocalIP() string {
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
return ""
}
defer conn.Close()
localAddr := conn.LocalAddr().(*net.UDPAddr)
return localAddr.IP.String()
}
// Obtenir IP de la passerelle (gateway) locale
func getGatewayIP() string {
ip, err := gateway.DiscoverGateway()
if err != nil {
log.Println("Erreur récupération gateway réelle :", err)
return ""
}
return ip.String()
}