From a4f3b6f1785872c9d7ac6376ea633e67f0c4ce14 Mon Sep 17 00:00:00 2001 From: Jordan Orelli Date: Sat, 15 Jun 2013 11:27:27 -0400 Subject: [PATCH] added a connection manager type --- args.go | 88 ------------------------------------------- connection_manager.go | 51 +++++++++++++++++++++++++ env.go | 6 +-- tcp_connections.go | 71 ++++++++++++++++++++++++++++++++++ 4 files changed, 125 insertions(+), 91 deletions(-) create mode 100644 connection_manager.go create mode 100644 tcp_connections.go diff --git a/args.go b/args.go index 213c467..8ef0e6e 100644 --- a/args.go +++ b/args.go @@ -5,7 +5,6 @@ import ( "flag" "fmt" "io" - "net" "os" ) @@ -41,90 +40,3 @@ func die(message string) { printErrorMsg(message) os.Exit(2) } - -func tcpInterpreter(conn net.Conn, out chan interface{}, errors chan error) { - prompt := func() { - io.WriteString(conn, "> ") - } - prompt() - for { - select { - case v := <-out: - fmt.Fprintln(conn, v) - prompt() - case err := <-errors: - fmt.Fprintf(conn, "error: %v", err) - } - } -} - -func startConnection(conn net.Conn, c, d chan net.Conn) { - c <- conn - defer func() { - d <- conn - fmt.Println("disconnected") - }() - - out, errors := make(chan interface{}), make(chan error) - go tcpInterpreter(conn, out, errors) - - r := bufio.NewReader(conn) - for { - line, prefix, err := r.ReadLine() - if prefix { - fmt.Println("(prefix)") - } - switch err { - case nil: - break - case io.EOF: - return - default: - printErrorMsg(err.Error()) - return - } - - tokens := make(chan token, 32) - go lexs(string(line)+"\n", tokens) - evalall(tokens, out, errors, universe) - } -} - -var activeConnections = make([]net.Conn, 0, 10) - -func removeConnection(conn net.Conn) { - for i, other := range activeConnections { - if conn.RemoteAddr() == other.RemoteAddr() { - activeConnections = append(activeConnections[:i], activeConnections[i+1:]...) - return - } - } -} - -func manageConnections(connect, disconnect chan net.Conn) { - for { - select { - case conn := <-connect: - activeConnections = append(activeConnections, conn) - case conn := <-disconnect: - removeConnection(conn) - } - } -} - -func runTCPServer() { - connect, disconnect := make(chan net.Conn), make(chan net.Conn) - go manageConnections(connect, disconnect) - ln, err := net.Listen("tcp", *tcpAddr) - if err != nil { - die(err.Error()) - } - for { - conn, err := ln.Accept() - if err != nil { - printErrorMsg(err.Error()) - continue - } - go startConnection(conn, connect, disconnect) - } -} diff --git a/connection_manager.go b/connection_manager.go new file mode 100644 index 0000000..0a72146 --- /dev/null +++ b/connection_manager.go @@ -0,0 +1,51 @@ +package main + +import ( + "net" +) + +var manager = newConnectionManager() + +type connectionManager struct { + active []net.Conn + connect chan net.Conn + disconnect chan net.Conn +} + +func newConnectionManager() *connectionManager { + m := &connectionManager{ + active: make([]net.Conn, 0, 10), + connect: make(chan net.Conn), + disconnect: make(chan net.Conn), + } + go m.run() + return m +} + +func (m *connectionManager) run() { + for { + select { + case conn := <-m.connect: + m.active = append(m.active, conn) + case conn := <-m.disconnect: + m.removeConnection(conn) + } + } +} + +func (m *connectionManager) Add(conn net.Conn) { + m.connect <- conn +} + +func (m *connectionManager) Remove(conn net.Conn) { + m.disconnect <- conn +} + +func (m *connectionManager) removeConnection(conn net.Conn) { + for i, other := range m.active { + if conn.RemoteAddr() == other.RemoteAddr() { + m.active = append(m.active[:i], m.active[i+1:]...) + return + } + } +} diff --git a/env.go b/env.go index 66ef5e4..e58cc32 100644 --- a/env.go +++ b/env.go @@ -46,9 +46,9 @@ func (e environment) keys() []string { for key, _ := range e.items { keys = append(keys, string(key)) } - if e.outer != nil { - keys = append(keys, e.outer.keys()...) - } + if e.outer != nil { + keys = append(keys, e.outer.keys()...) + } sort.Strings(keys) return keys } diff --git a/tcp_connections.go b/tcp_connections.go new file mode 100644 index 0000000..a3984b2 --- /dev/null +++ b/tcp_connections.go @@ -0,0 +1,71 @@ +package main + +import ( + "bufio" + "fmt" + "io" + "net" +) + +func tcpInterpreter(conn net.Conn, userinput chan string, out chan interface{}, errors chan error) { + prompt := func() { + io.WriteString(conn, "> ") + } + prompt() + for { + select { + case v := <-out: + fmt.Fprintln(conn, v) + prompt() + case err := <-errors: + fmt.Fprintf(conn, "error: %v", err) + case line := <-userinput: + tokens := make(chan token, 32) + go lexs(line+"\n", tokens) + go evalall(tokens, out, errors, universe) + } + } +} + +func runTCPServer() { + ln, err := net.Listen("tcp", *tcpAddr) + if err != nil { + die(err.Error()) + } + for { + conn, err := ln.Accept() + if err != nil { + printErrorMsg(err.Error()) + continue + } + go startConnection(conn, manager) + } +} + +func startConnection(conn net.Conn, m *connectionManager) { + m.Add(conn) + defer m.Remove(conn) + + out, errors := make(chan interface{}), make(chan error) + userinput := make(chan string) + + go tcpInterpreter(conn, userinput, out, errors) + + r := bufio.NewReader(conn) + for { + line, prefix, err := r.ReadLine() + if prefix { + fmt.Println("(prefix)") + } + switch err { + case nil: + break + case io.EOF: + return + default: + printErrorMsg(err.Error()) + return + } + userinput <- string(line) + } +}