Finishing shutdown implementation

This commit is contained in:
Denis-Cosmin Nutiu 2017-12-02 19:59:09 +02:00
parent b11510ef9c
commit ecbb599d48

View file

@ -14,6 +14,8 @@ import (
"os/signal" "os/signal"
"syscall" "syscall"
"sync"
"github.com/fsnotify/fsnotify" "github.com/fsnotify/fsnotify"
"github.com/metonimie/simpleFTP/server/server/config" "github.com/metonimie/simpleFTP/server/server/config"
"github.com/spf13/viper" "github.com/spf13/viper"
@ -35,10 +37,15 @@ var uploadTimeout time.Duration
// Shutdown is the shutdown where SIGINT and SIGTERM is send too // Shutdown is the shutdown where SIGINT and SIGTERM is send too
var Shutdown = make(chan os.Signal, 1) var Shutdown = make(chan os.Signal, 1)
var ftpShutdown = make(chan struct{}, 1)
var uploadShutdown = make(chan struct{}, 1)
var uploadListener net.Listener var uploadListener net.Listener
var ftpListener net.Listener var ftpListener net.Listener
// All connected clients
var clients map[Client]bool
// Client interface provides the blueprints for the Client that is used by the server. // Client interface provides the blueprints for the Client that is used by the server.
type Client interface { type Client interface {
Connection() net.Conn // Connection returns the connection stream. Connection() net.Conn // Connection returns the connection stream.
@ -83,23 +90,43 @@ func shutdownHandler() {
select { select {
case <-Shutdown: case <-Shutdown:
log.Println("Shutdown signal received") log.Println("Shutdown signal received")
if ftpListener != nil { var wg sync.WaitGroup
ftpListener.Close() wg.Add(1)
}
if uploadListener != nil { go func() { // Disconnect all the clients.
uploadListener.Close() for k := range clients {
} k.Disconnect()
}
wg.Done()
}()
wg.Wait()
ShutdownFtpServer()
ShutdownUploadServer()
// FIXME: Find a way to close all clients before this
os.Exit(0)
return return
} }
} }
} }
func ShutdownUploadServer() {
if uploadListener != nil {
uploadListener.Close()
uploadShutdown <- struct{}{}
}
}
func ShutdownFtpServer() {
if ftpListener != nil {
ftpListener.Close()
ftpShutdown <- struct{}{}
}
}
func Init() { func Init() {
signal.Notify(Shutdown, syscall.SIGINT, syscall.SIGTERM) signal.Notify(Shutdown, syscall.SIGINT, syscall.SIGTERM)
clients = make(map[Client]bool)
go shutdownHandler() go shutdownHandler()
config.InitializeConfiguration("config", ConfigPath) config.InitializeConfiguration("config", ConfigPath)
@ -122,6 +149,7 @@ func HandleConnection(client Client) {
}() }()
log.Println(client.Connection().RemoteAddr(), "has connected.") log.Println(client.Connection().RemoteAddr(), "has connected.")
clients[client] = true
// Process input // Process input
input := bufio.NewScanner(client.Connection()) input := bufio.NewScanner(client.Connection())
@ -137,6 +165,7 @@ func HandleConnection(client Client) {
} }
// Client has left. // Client has left.
delete(clients, client)
log.Println(client.Connection().RemoteAddr(), "has disconnected.") log.Println(client.Connection().RemoteAddr(), "has disconnected.")
} }
@ -159,6 +188,14 @@ func StartFtpServer() error {
log.Println("Ftp server running on:", Addr, "port", Port) log.Println("Ftp server running on:", Addr, "port", Port)
for { for {
// Handle shutdown
select {
case <-ftpShutdown:
return nil
default:
// move on
}
conn, err := ftpListener.Accept() conn, err := ftpListener.Accept()
if err != nil { if err != nil {
log.Print(err) log.Print(err)
@ -182,6 +219,7 @@ func HandleUpload(conn net.Conn) {
// Upload directory // Upload directory
client.Stack().Push(uploadDirectory) client.Stack().Push(uploadDirectory)
client.SetConnection(conn) client.SetConnection(conn)
defer client.Disconnect()
// Create the file on the disk and make sure that the filename is random. // Create the file on the disk and make sure that the filename is random.
var filename = randSeq(10) var filename = randSeq(10)
@ -195,6 +233,7 @@ func HandleUpload(conn net.Conn) {
// This channel will be used to store the uploadResult // This channel will be used to store the uploadResult
c1 := make(chan error, 1) c1 := make(chan error, 1)
log.Println(conn.RemoteAddr().String() + " is uploading something.") log.Println(conn.RemoteAddr().String() + " is uploading something.")
clients[&client] = true
// Create a new Go routine for uploading // Create a new Go routine for uploading
go func() { go func() {
@ -226,6 +265,8 @@ func HandleUpload(conn net.Conn) {
conn.Close() conn.Close()
} }
} }
delete(clients, &client)
} }
// StartUploadServer starts the uploading server // StartUploadServer starts the uploading server
@ -260,6 +301,14 @@ func StartUploadServer() error {
log.Println("Upload server running on:", addr, "port", port) log.Println("Upload server running on:", addr, "port", port)
for { for {
// Handle shutdown
select {
case <-uploadShutdown:
return nil
default:
// move on
}
conn, err := uploadListener.Accept() conn, err := uploadListener.Accept()
if err != nil { if err != nil {
log.Print(err) log.Print(err)