diff --git a/rendevouz.go b/rendevouz.go index c85f80f..0ba0621 100644 --- a/rendevouz.go +++ b/rendevouz.go @@ -1,48 +1,97 @@ package main import ( - "io" - "log" "net" ) // also see : http://archive.is/4Um4u -func runRendevouz() { - // Listen on the specified TCP port on all interfaces. - from := "0.0.0.0:27001" - to := "0.0.0.0:27009" - l, err := net.Listen("tcp", to) - if err != nil { - log.Fatal(err) - } - defer l.Close() - for { - // Wait for a connection. - c, err := l.Accept() - if err != nil { - log.Fatal(err) +// func runRendevouz() { +// // Listen on the specified TCP port on all interfaces. +// from := "0.0.0.0:27001" +// to := "0.0.0.0:27009" +// l, err := net.Listen("tcp", to) +// if err != nil { +// log.Fatal(err) +// } +// defer l.Close() +// for { +// // Wait for a connection. +// c, err := l.Accept() +// if err != nil { +// log.Fatal(err) +// } + +// // handle the connection in a goroutine +// go wormhole(c, from) +// } +// } + +// func relay(c net.Conn, from string) { +// defer c.Close() +// log.Println("Opening relay to", c.RemoteAddr()) + +// // connect to the destination tcp port +// destConn, err := net.Dial("tcp", *to) +// if err != nil { +// log.Fatal("Error connecting to destination port") +// } +// defer destConn.Close() +// log.Println("Wormhole open from", c.RemoteAddr()) + +// go func() { io.Copy(c, destConn) }() +// io.Copy(destConn, c) + +// log.Println("Stopping wormhole from", c.RemoteAddr()) +// } + +// BETTER? + +// chanFromConn creates a channel from a Conn object, and sends everything it +// Read()s from the socket to the channel. +func chanFromConn(conn net.Conn) chan []byte { + c := make(chan []byte) + + go func() { + b := make([]byte, 1024) + + for { + n, err := conn.Read(b) + if n > 0 { + res := make([]byte, n) + // Copy the buffer so it doesn't get changed while read by the recipient. + copy(res, b[:n]) + c <- res + } + if err != nil { + c <- nil + break + } } + }() - // handle the connection in a goroutine - go wormhole(c, from) - } + return c } -func relay(c net.Conn, from string) { - defer c.Close() - log.Println("Opening relay to", c.RemoteAddr()) +// Pipe creates a full-duplex pipe between the two sockets and transfers data from one to the other. +func Pipe(conn1 net.Conn, conn2 net.Conn) { + chan1 := chanFromConn(conn1) + chan2 := chanFromConn(conn2) - // connect to the destination tcp port - destConn, err := net.Dial("tcp", *to) - if err != nil { - log.Fatal("Error connecting to destination port") + for { + select { + case b1 := <-chan1: + if b1 == nil { + return + } else { + conn2.Write(b1) + } + case b2 := <-chan2: + if b2 == nil { + return + } else { + conn1.Write(b2) + } + } } - defer destConn.Close() - log.Println("Wormhole open from", c.RemoteAddr()) - - go func() { io.Copy(c, destConn) }() - io.Copy(destConn, c) - - log.Println("Stopping wormhole from", c.RemoteAddr()) } diff --git a/server.go b/server.go index 35004a0..45cb4ab 100644 --- a/server.go +++ b/server.go @@ -56,7 +56,7 @@ func listener(id int) (err error) { if err != nil { return errors.Wrap(err, "problem accepting connection") } - logger.Info("Client connected") + logger.Infof("Client %s connected", connection.RemoteAddr().String()) go sendFileToClient(id, connection) } } diff --git a/test/client.go b/test/client.go new file mode 100644 index 0000000..7f54faf --- /dev/null +++ b/test/client.go @@ -0,0 +1,36 @@ +package main + +import ( + "fmt" + "net" + "strconv" + "strings" + "sync" +) + +func runClient() { + var wg sync.WaitGroup + wg.Add(numberConnections) + for id := 0; id < numberConnections; id++ { + go func(id int) { + defer wg.Done() + port := strconv.Itoa(27001 + id) + connection, err := net.Dial("tcp", "localhost:"+port) + if err != nil { + panic(err) + } + defer connection.Close() + + var messageByte []byte + var message string + messageByte = make([]byte, 64) + connection.Read(messageByte) + message = strings.Replace(string(messageByte), ":", "", -1) + fmt.Println(message) + message = fillString("reciever-123", 64) + connection.Write([]byte(message)) + + }(id) + } + wg.Wait() +} diff --git a/test/main.go b/test/main.go new file mode 100644 index 0000000..63f0b4a --- /dev/null +++ b/test/main.go @@ -0,0 +1,50 @@ +package main + +import ( + "flag" + "fmt" + + log "github.com/sirupsen/logrus" +) + +const BUFFERSIZE = 1024 +const numberConnections = 1 + +// Build flags +var server, file string + +// Global varaibles +var serverAddress, fileName string + +func main() { + flag.StringVar(&serverAddress, "server", "", "(run as client) server address to connect to") + flag.StringVar(&fileName, "file", "", "(run as server) file to serve") + flag.Parse() + // Check build flags too, which take precedent + if server != "" { + serverAddress = server + } + if file != "" { + fileName = file + } + if len(fileName) != 0 { + runServer() + } else if len(serverAddress) != 0 { + runClient() + } else { + fmt.Println("You must specify either -file (for running as a server) or -server (for running as a client)") + } +} + +func init() { + // Log as JSON instead of the default ASCII formatter. + // log.SetFormatter(&log.JSONFormatter{}) + log.SetFormatter(&log.TextFormatter{}) + + // Output to stdout instead of the default stderr + // Can be any io.Writer, see below for File example + // log.SetOutput(os.Stdout) + + // Only log the warning severity or above. + log.SetLevel(log.DebugLevel) +} diff --git a/test/rendevouz.go b/test/rendevouz.go new file mode 100644 index 0000000..0ba0621 --- /dev/null +++ b/test/rendevouz.go @@ -0,0 +1,97 @@ +package main + +import ( + "net" +) + +// also see : http://archive.is/4Um4u + +// func runRendevouz() { +// // Listen on the specified TCP port on all interfaces. +// from := "0.0.0.0:27001" +// to := "0.0.0.0:27009" +// l, err := net.Listen("tcp", to) +// if err != nil { +// log.Fatal(err) +// } +// defer l.Close() +// for { +// // Wait for a connection. +// c, err := l.Accept() +// if err != nil { +// log.Fatal(err) +// } + +// // handle the connection in a goroutine +// go wormhole(c, from) +// } +// } + +// func relay(c net.Conn, from string) { +// defer c.Close() +// log.Println("Opening relay to", c.RemoteAddr()) + +// // connect to the destination tcp port +// destConn, err := net.Dial("tcp", *to) +// if err != nil { +// log.Fatal("Error connecting to destination port") +// } +// defer destConn.Close() +// log.Println("Wormhole open from", c.RemoteAddr()) + +// go func() { io.Copy(c, destConn) }() +// io.Copy(destConn, c) + +// log.Println("Stopping wormhole from", c.RemoteAddr()) +// } + +// BETTER? + +// chanFromConn creates a channel from a Conn object, and sends everything it +// Read()s from the socket to the channel. +func chanFromConn(conn net.Conn) chan []byte { + c := make(chan []byte) + + go func() { + b := make([]byte, 1024) + + for { + n, err := conn.Read(b) + if n > 0 { + res := make([]byte, n) + // Copy the buffer so it doesn't get changed while read by the recipient. + copy(res, b[:n]) + c <- res + } + if err != nil { + c <- nil + break + } + } + }() + + return c +} + +// Pipe creates a full-duplex pipe between the two sockets and transfers data from one to the other. +func Pipe(conn1 net.Conn, conn2 net.Conn) { + chan1 := chanFromConn(conn1) + chan2 := chanFromConn(conn2) + + for { + select { + case b1 := <-chan1: + if b1 == nil { + return + } else { + conn2.Write(b1) + } + case b2 := <-chan2: + if b2 == nil { + return + } else { + conn1.Write(b2) + } + } + } +} diff --git a/test/server.go b/test/server.go new file mode 100644 index 0000000..fbb3bda --- /dev/null +++ b/test/server.go @@ -0,0 +1,91 @@ +package main + +import ( + "fmt" + "net" + "strconv" + "strings" + "sync" + + "github.com/pkg/errors" + log "github.com/sirupsen/logrus" +) + +func runServer() { + logger := log.WithFields(log.Fields{ + "function": "main", + }) + logger.Info("Initializing") + var wg sync.WaitGroup + wg.Add(numberConnections) + for id := 0; id < numberConnections; id++ { + go listenerThread(id, &wg) + } + wg.Wait() +} + +func listenerThread(id int, wg *sync.WaitGroup) { + logger := log.WithFields(log.Fields{ + "function": "listenerThread@" + serverAddress + ":" + strconv.Itoa(27000+id), + }) + + defer wg.Done() + err := listener(id) + if err != nil { + logger.Error(err) + } +} + +func listener(id int) (err error) { + port := strconv.Itoa(27001 + id) + logger := log.WithFields(log.Fields{ + "function": "listener@" + serverAddress + ":" + port, + }) + server, err := net.Listen("tcp", serverAddress+":"+port) + if err != nil { + return errors.Wrap(err, "Error listening on "+serverAddress+":"+port) + } + defer server.Close() + logger.Info("waiting for connections") + //Spawn a new goroutine whenever a client connects + for { + connection, err := server.Accept() + if err != nil { + return errors.Wrap(err, "problem accepting connection") + } + logger.Infof("Client %s connected", connection.RemoteAddr().String()) + go clientCommuncation(id, connection) + } +} + +func clientCommuncation(id int, connection net.Conn) { + defer connection.Close() + sendMessage("who?", connection) + message := receiveMessage(connection) + // TODO: parse message for sender/reciever and the code phrase + fmt.Println(message) + return +} + +func sendMessage(message string, connection net.Conn) { + message = fillString(message, 64) + connection.Write([]byte(message)) +} + +func receiveMessage(connection net.Conn) string { + messageByte := make([]byte, 64) + connection.Read(messageByte) + return strings.Replace(string(messageByte), ":", "", -1) +} + +func fillString(retunString string, toLength int) string { + for { + lengthString := len(retunString) + if lengthString < toLength { + retunString = retunString + ":" + continue + } + break + } + return retunString +}