added a connection manager type

master
Jordan Orelli 12 years ago
parent 512549a07c
commit a4f3b6f178

@ -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)
}
}

@ -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
}
}
}

@ -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
}

@ -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)
}
}
Loading…
Cancel
Save