|
|
@ -1,23 +1,56 @@ |
|
|
|
package main |
|
|
|
|
|
|
|
// Lot's of learning right out of the gate:
|
|
|
|
// https://stackoverflow.com/questions/51472020/how-to-get-the-size-of-available-tcp-data
|
|
|
|
|
|
|
|
import ( |
|
|
|
"bufio" |
|
|
|
"flag" |
|
|
|
"fmt" |
|
|
|
"io" |
|
|
|
"net" |
|
|
|
"os" |
|
|
|
"strconv" |
|
|
|
"sync" |
|
|
|
"time" |
|
|
|
) |
|
|
|
|
|
|
|
type bufferedConn struct { |
|
|
|
r *bufio.Reader |
|
|
|
rout io.Reader |
|
|
|
net.Conn |
|
|
|
} |
|
|
|
|
|
|
|
func newBufferedConn(c net.Conn) bufferedConn { |
|
|
|
return bufferedConn{bufio.NewReader(c), nil, c} |
|
|
|
} |
|
|
|
|
|
|
|
func (b bufferedConn) Peek(n int) ([]byte, error) { |
|
|
|
return b.r.Peek(n) |
|
|
|
} |
|
|
|
|
|
|
|
func (b bufferedConn) Buffered() (int) { |
|
|
|
return b.r.Buffered() |
|
|
|
} |
|
|
|
|
|
|
|
func (b bufferedConn) Read(p []byte) (int, error) { |
|
|
|
if b.rout != nil { |
|
|
|
return b.rout.Read(p) |
|
|
|
} |
|
|
|
return b.r.Read(p) |
|
|
|
} |
|
|
|
|
|
|
|
type myMsg struct { |
|
|
|
sender net.Conn |
|
|
|
bytes []byte |
|
|
|
receivedAt time.Time |
|
|
|
} |
|
|
|
|
|
|
|
var firstMsgs chan myMsg |
|
|
|
var myMsgs chan myMsg |
|
|
|
var myConns map[net.Conn]bool |
|
|
|
var myUnsortedConns map[net.Conn]bool |
|
|
|
var myRawConns map[net.Conn]bool |
|
|
|
var newConns chan net.Conn |
|
|
|
|
|
|
|
func usage() { |
|
|
|
fmt.Fprintf(os.Stderr, "\nusage: go run chatserver.go\n") |
|
|
@ -27,14 +60,57 @@ func usage() { |
|
|
|
os.Exit(1) |
|
|
|
} |
|
|
|
|
|
|
|
func handleConnection(conn net.Conn) { |
|
|
|
// Why don't these work?
|
|
|
|
//buf := make([]byte, 0, 1024)
|
|
|
|
//buf := []byte{}
|
|
|
|
// But this does
|
|
|
|
fmt.Fprintf(conn, "Welcome! This is an open relay chat server. There is no security yet.\n") |
|
|
|
func handleRaw(conn bufferedConn) { |
|
|
|
// Handle all subsequent packets
|
|
|
|
buf := make([]byte, 1024) |
|
|
|
for { |
|
|
|
fmt.Fprintf(os.Stdout, "[raw] Waiting for message...\n"); |
|
|
|
count, err := conn.Read(buf) |
|
|
|
if nil != err { |
|
|
|
if io.EOF != err { |
|
|
|
fmt.Fprintf(os.Stderr, "Non-EOF socket error: %s\n", err) |
|
|
|
} |
|
|
|
fmt.Fprintf(os.Stdout, "Ending socket\n") |
|
|
|
break |
|
|
|
} |
|
|
|
// Fun fact: if the buffer's current length (not capacity) is 0
|
|
|
|
// then the Read returns 0 without error
|
|
|
|
if 0 == count { |
|
|
|
fmt.Fprintf(os.Stdout, "Weird") |
|
|
|
continue |
|
|
|
} |
|
|
|
fmt.Fprintf(os.Stdout, "Queing message...\n"); |
|
|
|
myMsgs <- myMsg{ |
|
|
|
receivedAt: time.Now(), |
|
|
|
sender: conn, |
|
|
|
bytes: buf[0:count], |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func handleSorted(conn bufferedConn) { |
|
|
|
// at this piont we've already at least one byte via Peek()
|
|
|
|
// so the first packet is available in the buffer
|
|
|
|
n := conn.Buffered() |
|
|
|
firstMsg, err := conn.Peek(n) |
|
|
|
if nil != err { |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
firstMsgs <- myMsg{ |
|
|
|
receivedAt: time.Now(), |
|
|
|
sender: conn, |
|
|
|
bytes: firstMsg, |
|
|
|
} |
|
|
|
|
|
|
|
// TODO
|
|
|
|
// * TCP-CHAT
|
|
|
|
// * HTTP
|
|
|
|
// * TLS
|
|
|
|
|
|
|
|
// Handle all subsequent packets
|
|
|
|
buf := make([]byte, 1024) |
|
|
|
for { |
|
|
|
fmt.Fprintf(os.Stdout, "[sortable] Waiting for message...\n"); |
|
|
|
count, err := conn.Read(buf) |
|
|
|
if nil != err { |
|
|
|
if io.EOF != err { |
|
|
@ -43,8 +119,8 @@ func handleConnection(conn net.Conn) { |
|
|
|
fmt.Fprintf(os.Stdout, "Ending socket\n") |
|
|
|
break |
|
|
|
} |
|
|
|
// not so sure about why this case exists
|
|
|
|
// we'll just ignore it for now...
|
|
|
|
// Fun fact: if the buffer's current length (not capacity) is 0
|
|
|
|
// then the Read returns 0 without error
|
|
|
|
if 0 == count { |
|
|
|
// fmt.Fprintf(os.Stdout, "Weird")
|
|
|
|
continue |
|
|
@ -57,9 +133,57 @@ func handleConnection(conn net.Conn) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// TODO https://github.com/polvi/sni
|
|
|
|
func handleConnection(conn net.Conn) { |
|
|
|
fmt.Fprintf(os.Stdout, "Accepting socket\n") |
|
|
|
|
|
|
|
m := sync.Mutex{} |
|
|
|
virgin := true |
|
|
|
myUnsortedConns[conn] = true |
|
|
|
|
|
|
|
// Why don't these work?
|
|
|
|
//buf := make([]byte, 0, 1024)
|
|
|
|
//buf := []byte{}
|
|
|
|
// But this does
|
|
|
|
|
|
|
|
bufConn := newBufferedConn(conn) |
|
|
|
go func() { |
|
|
|
// Handle First Packet
|
|
|
|
fmsg, err := bufConn.Peek(1) |
|
|
|
if nil != err { |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
fmt.Fprintf(os.Stdout, "[First Byte] %s\n", fmsg) |
|
|
|
|
|
|
|
m.Lock(); |
|
|
|
if virgin { |
|
|
|
virgin = false |
|
|
|
go handleSorted(bufConn) |
|
|
|
} else { |
|
|
|
go handleRaw(bufConn) |
|
|
|
} |
|
|
|
m.Unlock(); |
|
|
|
}() |
|
|
|
|
|
|
|
time.Sleep(250 * 1000000) |
|
|
|
// If we still haven't received data from the client
|
|
|
|
// assume that the client must be expecting a welcome from us
|
|
|
|
m.Lock() |
|
|
|
if virgin { |
|
|
|
virgin = false |
|
|
|
// don't block for this
|
|
|
|
// let it be handled after the unlock
|
|
|
|
defer fmt.Fprintf(conn, "Welcome! This is an open relay chat server. There is no security yet.\n") |
|
|
|
} |
|
|
|
m.Unlock() |
|
|
|
} |
|
|
|
|
|
|
|
func main() { |
|
|
|
firstMsgs = make(chan myMsg, 128) |
|
|
|
myMsgs = make(chan myMsg, 128) |
|
|
|
myConns = make(map[net.Conn]bool) |
|
|
|
newConns = make(chan net.Conn, 128) |
|
|
|
myRawConns = make(map[net.Conn]bool) |
|
|
|
myUnsortedConns = make(map[net.Conn]bool) |
|
|
|
flag.Usage = usage |
|
|
|
port:= flag.Uint("telnet-port", 4080, "tcp telnet chat port") |
|
|
|
flag.Parse() |
|
|
@ -76,8 +200,21 @@ func main() { |
|
|
|
|
|
|
|
go func() { |
|
|
|
for { |
|
|
|
fmt.Fprintf(os.Stdout, "Waiting for message...\n"); |
|
|
|
msg := <- myMsgs |
|
|
|
conn, err := sock.Accept() |
|
|
|
if err != nil { |
|
|
|
// Not sure what kind of error this could be or how it could happen.
|
|
|
|
// Could a connection abort or end before it's handled?
|
|
|
|
fmt.Fprintf(os.Stderr, "Error accepting connection:\n%s\n", err) |
|
|
|
} |
|
|
|
newConns <- conn |
|
|
|
} |
|
|
|
}() |
|
|
|
|
|
|
|
for { |
|
|
|
select { |
|
|
|
case conn := <- newConns: |
|
|
|
go handleConnection(conn) |
|
|
|
case msg := <- myMsgs: |
|
|
|
ts, err := msg.receivedAt.MarshalJSON() |
|
|
|
if nil != err { |
|
|
|
fmt.Fprintf(os.Stderr, "[Error] %s\n", err) |
|
|
@ -85,7 +222,7 @@ func main() { |
|
|
|
fmt.Fprintf(os.Stdout, "[Timestamp] %s\n", ts) |
|
|
|
fmt.Fprintf(os.Stdout, "[Remote] %s\n", msg.sender.RemoteAddr().String()) |
|
|
|
fmt.Fprintf(os.Stdout, "[Message] %s\n", msg.bytes); |
|
|
|
for conn, _ := range myConns { |
|
|
|
for conn, _ := range myRawConns { |
|
|
|
if msg.sender == conn { |
|
|
|
continue |
|
|
|
} |
|
|
@ -95,18 +232,15 @@ func main() { |
|
|
|
// SetDeadTime and Disconnect them?
|
|
|
|
conn.Write(msg.bytes) |
|
|
|
} |
|
|
|
case msg := <- firstMsgs: |
|
|
|
fmt.Fprintf(os.Stdout, "f [First Message]\n") |
|
|
|
ts, err := msg.receivedAt.MarshalJSON() |
|
|
|
if nil != err { |
|
|
|
fmt.Fprintf(os.Stderr, "f [Error] %s\n", err) |
|
|
|
} |
|
|
|
fmt.Fprintf(os.Stdout, "f [Timestamp] %s\n", ts) |
|
|
|
fmt.Fprintf(os.Stdout, "f [Remote] %s\n", msg.sender.RemoteAddr().String()) |
|
|
|
fmt.Fprintf(os.Stdout, "f [Message] %s\n", msg.bytes); |
|
|
|
} |
|
|
|
}() |
|
|
|
|
|
|
|
for { |
|
|
|
conn, err := sock.Accept() |
|
|
|
if err != nil { |
|
|
|
// Not sure what kind of error this could be or how it could happen.
|
|
|
|
// Could a connection abort or end before it's handled?
|
|
|
|
fmt.Fprintf(os.Stderr, "Error accepting connection:\n%s\n", err) |
|
|
|
} |
|
|
|
fmt.Fprintf(os.Stdout, "Accepting socket\n") |
|
|
|
myConns[conn] = true |
|
|
|
go handleConnection(conn) |
|
|
|
} |
|
|
|
} |
|
|
|