shelfy/main.go
2025-06-15 21:18:23 +02:00

142 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/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 || len(clients) == 0 {
return false
}
localIP := getLocalIP()
if localIP == "" {
log.Println("Impossible dobtenir lIP locale")
return false
}
client := clients[0]
protocol := "TCP"
description := "GoAutoExposition"
duration := uint32(3600)
// Fonction de mapping UPnP
mapPort := func() {
err = client.AddPortMapping("", externalPort, protocol, internalPort, localIP, true, description, duration)
if err != nil {
log.Println("UPnP mapping échoué :", err)
} else {
log.Printf("✅ [UPnP] Port %d externe redirigé vers %s:%d", externalPort, localIP, internalPort)
}
}
mapPort()
// Renouveler toutes les 55 minutes
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", 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 {
// Connexion UDP simulée pour déduire la passerelle
conn, err := net.Dial("udp", "192.168.0.1:80")
if err != nil {
return ""
}
defer conn.Close()
localAddr := conn.LocalAddr().(*net.UDPAddr)
ip := localAddr.IP.To4()
if ip == nil {
return ""
}
// Exemple : 192.168.1.34 → gateway supposée : 192.168.1.1
ip[3] = 1
return ip.String()
}