Refactoring: Instead of using net.Conn use a Client interface instead

This commit is contained in:
Denis-Cosmin Nutiu 2017-11-08 15:11:37 +02:00
parent a9da0ce2d9
commit cb46154ec8
3 changed files with 66 additions and 18 deletions

View file

@ -1,9 +1,10 @@
package main package main
import ( import (
"github.com/metonimie/simpleFTP/server/server"
"log" "log"
"net" "net"
"github.com/metonimie/simpleFTP/server/server"
) )
func main() { func main() {
@ -16,12 +17,17 @@ func main() {
log.Println("Running on:", "localhost", "port", "8080") log.Println("Running on:", "localhost", "port", "8080")
for { for {
conn, err := listener.Accept() conn, err := listener.Accept()
if err != nil { if err != nil {
log.Print(err) log.Print(err)
continue continue
} }
go server.HandleConnection(conn) client := server.FTPClient{}
client.SetStack(new(server.StringStack))
client.SetConnection(conn)
go server.HandleConnection(&client)
} }
} }

View file

@ -7,24 +7,67 @@ import (
"net" "net"
) )
func HandleConnection(c net.Conn) { // ClientStack interface holds the function needed to work with a stack.
defer c.Close() type ClientStack interface {
io.WriteString(c, "Hello and welcome to simple ftp\n") Stack() Stack // Returns the underlying Stack.
}
log.Println(c.RemoteAddr(), "has connected.") // Client interface provides the blueprints for the Client that is used by the server.
type Client interface {
Connection() net.Conn // Connection returns the connection stream.
SetConnection(conn net.Conn) // SetConnection sets the connection for the client.
Disconnect() // Disconnect closes the Client's connections and clears up resources.
}
// FTPClient represents a FTPClient connection, it holds a root cage and the underlying connection.
type FTPClient struct {
rootCage *StringStack // rootCage is a StringStack that is used to represent the current directory the client is in.
connection net.Conn
}
// Stack returns the root cage stack.
func (c *FTPClient) Stack() Stack {
return c.rootCage
}
// SetStack sets the stack for the FTPClient.
func (c *FTPClient) SetStack(stack *StringStack) {
c.rootCage = stack
}
// Connection returns the Connection of the client.
func (c *FTPClient) Connection() net.Conn {
return c.connection
}
// SetConnection sets the given connection to the client.
func (c *FTPClient) SetConnection(conn net.Conn) {
c.connection = conn
}
// Disconnects the client.
func (c *FTPClient) Disconnect() {
c.connection.Close()
}
func HandleConnection(client Client) {
defer client.Disconnect()
io.WriteString(client.Connection(), "Hello and welcome to simple ftp\n")
log.Println(client.Connection().RemoteAddr(), "has connected.")
// Process input // Process input
input := bufio.NewScanner(c) input := bufio.NewScanner(client.Connection())
for input.Scan() { for input.Scan() {
log.Println(c.RemoteAddr(), ":", input.Text()) log.Println(client.Connection().RemoteAddr(), ":", input.Text())
err := ProcessInput(c, input.Text()) err := ProcessInput(client, input.Text())
if err != nil { if err != nil {
log.Println(err) log.Println(err)
io.WriteString(c, err.Error()+"\n") io.WriteString(client.Connection(), err.Error()+"\n")
} }
} }
// Client has left. // Client has left.
log.Println(c.RemoteAddr(), "has disconnected.") log.Println(client.Connection().RemoteAddr(), "has disconnected.")
} }

View file

@ -1,7 +1,6 @@
package server package server
import ( import (
"net"
"strings" "strings"
) )
@ -15,7 +14,7 @@ func checkArgumentsLength(length int, expected int) error {
return nil return nil
} }
func ProcessInput(c net.Conn, text string) error { func ProcessInput(c Client, text string) error {
commands := strings.Fields(text) commands := strings.Fields(text)
commandsLen := len(commands) commandsLen := len(commands)
@ -33,7 +32,7 @@ func ProcessInput(c net.Conn, text string) error {
} }
// Get the file // Get the file
_, err = GetFile(c, commands[1]) _, err = GetFile(c.Connection(), commands[1])
if err != nil { if err != nil {
return &InputError{thisCommand, err} return &InputError{thisCommand, err}
} }
@ -43,7 +42,7 @@ func ProcessInput(c net.Conn, text string) error {
return &InputError{thisCommand, err} return &InputError{thisCommand, err}
} }
err = ListFiles(c) err = ListFiles(c.Connection())
if err != nil { if err != nil {
return &InputError{thisCommand, err} return &InputError{thisCommand, err}
} }
@ -57,7 +56,7 @@ func ProcessInput(c net.Conn, text string) error {
// clear | hexdump -C // clear | hexdump -C
var b = []byte{0x1b, 0x5b, 0x48, 0x1b, 0x5b, 0x4a} var b = []byte{0x1b, 0x5b, 0x48, 0x1b, 0x5b, 0x4a}
c.Write(b) c.Connection().Write(b)
case "help": case "help":
// Check arguments // Check arguments
err := checkArgumentsLength(commandsLen, 1) err := checkArgumentsLength(commandsLen, 1)
@ -65,7 +64,7 @@ func ProcessInput(c net.Conn, text string) error {
return &InputError{thisCommand, err} return &InputError{thisCommand, err}
} }
err = ShowHelp(c) err = ShowHelp(c.Connection())
if err != nil { if err != nil {
return &InputError{thisCommand, err} return &InputError{thisCommand, err}
} }
@ -75,7 +74,7 @@ func ProcessInput(c net.Conn, text string) error {
return &InputError{thisCommand, err} return &InputError{thisCommand, err}
} }
c.Close() c.Connection().Close()
default: default:
return &InputError{thisCommand, InputInvalidCommand} return &InputError{thisCommand, InputInvalidCommand}
} }