|
|
@ -28,7 +28,8 @@ import ( |
|
|
|
// I'm not sure how to pass nested structs, so I de-nested this.
|
|
|
|
// TODO Learn if passing nested structs is desirable?
|
|
|
|
type Conf struct { |
|
|
|
Port uint `yaml:"port,omitempty"` |
|
|
|
Addr string `yaml:"addr,omitempty"` |
|
|
|
Port uint `yaml:"port,omitempty"` |
|
|
|
Mailer ConfMailer |
|
|
|
RootPath string `yaml:"root_path,omitempty"` |
|
|
|
} |
|
|
@ -100,7 +101,7 @@ var authTelnet chan tcpUser |
|
|
|
var cleanTelnet chan tcpUser |
|
|
|
var gotClientHello chan bufferedConn |
|
|
|
|
|
|
|
// Http
|
|
|
|
// HTTP
|
|
|
|
var demuxHttpClient chan bufferedConn |
|
|
|
var newAuthReqs chan authReq |
|
|
|
var valAuthReqs chan authReq |
|
|
@ -277,25 +278,11 @@ func sendAuthCode(cnf ConfMailer, to string) (string, error) { |
|
|
|
return code, nil |
|
|
|
} |
|
|
|
|
|
|
|
type myHttpServer struct { |
|
|
|
chans chan bufferedConn |
|
|
|
net.Listener |
|
|
|
} |
|
|
|
|
|
|
|
func (m *myHttpServer) Accept() (net.Conn, error) { |
|
|
|
bufConn := <-m.chans |
|
|
|
return bufConn, nil |
|
|
|
} |
|
|
|
|
|
|
|
func newHttpServer(l net.Listener) *myHttpServer { |
|
|
|
return &myHttpServer{make(chan bufferedConn), l} |
|
|
|
} |
|
|
|
|
|
|
|
var config Conf |
|
|
|
|
|
|
|
func main() { |
|
|
|
flag.Usage = usage |
|
|
|
port := flag.Uint("telnet-port", 0, "tcp telnet chat port") |
|
|
|
port := flag.Uint("port", 0, "tcp telnet chat port") |
|
|
|
confname := flag.String("conf", "./config.yml", "yaml config file") |
|
|
|
flag.Parse() |
|
|
|
|
|
|
@ -318,7 +305,7 @@ func main() { |
|
|
|
virginConns = make(chan net.Conn, 128) |
|
|
|
|
|
|
|
// TCP & Authentication
|
|
|
|
myRawConns := make(map[bufferedConn]tcpUser) |
|
|
|
telnetConns := make(map[bufferedConn]tcpUser) |
|
|
|
wantsServerHello = make(chan bufferedConn, 128) |
|
|
|
authTelnet = make(chan tcpUser, 128) |
|
|
|
|
|
|
@ -344,9 +331,9 @@ func main() { |
|
|
|
|
|
|
|
var addr string |
|
|
|
if 0 != int(*port) { |
|
|
|
addr = ":" + strconv.Itoa(int(*port)) |
|
|
|
addr = config.Addr + ":" + strconv.Itoa(int(*port)) |
|
|
|
} else { |
|
|
|
addr = ":" + strconv.Itoa(int(config.Port)) |
|
|
|
addr = config.Addr + ":" + strconv.Itoa(int(config.Port)) |
|
|
|
} |
|
|
|
|
|
|
|
// https://golang.org/pkg/net/#Conn
|
|
|
@ -388,8 +375,8 @@ func main() { |
|
|
|
wsApi.Route(wsApi.GET("/hello").To(serveHello)) |
|
|
|
wsApi.Route(wsApi.POST("/sessions").To(requestAuth)) |
|
|
|
wsApi.Route(wsApi.POST("/sessions/{cid}").To(issueToken)) |
|
|
|
wsApi.Route(wsApi.GET("/rooms/general").Filter(requireToken).To(listMsgs)) |
|
|
|
wsApi.Route(wsApi.POST("/rooms/general").Filter(requireToken).To(postMsg)) |
|
|
|
wsApi.Route(wsApi.GET("/rooms/{room}").Filter(requireToken).To(listMsgs)) |
|
|
|
wsApi.Route(wsApi.POST("/rooms/{room}").Filter(requireToken).To(postMsg)) |
|
|
|
container.Add(wsApi) |
|
|
|
|
|
|
|
server := &http.Server{ |
|
|
@ -410,9 +397,9 @@ func main() { |
|
|
|
case u := <-authTelnet: |
|
|
|
// allow to receive messages
|
|
|
|
// (and be counted among the users)
|
|
|
|
myRawConns[u.bufConn] = u |
|
|
|
telnetConns[u.bufConn] = u |
|
|
|
// is chan chan the right way to handle this?
|
|
|
|
u.userCount <- len(myRawConns) |
|
|
|
u.userCount <- len(telnetConns) |
|
|
|
broadcastMsg <- myMsg{ |
|
|
|
sender: nil, |
|
|
|
// TODO fmt.Fprintf()? template?
|
|
|
@ -442,9 +429,19 @@ func main() { |
|
|
|
go handleTelnetConn(bufConn) |
|
|
|
case u := <-cleanTelnet: |
|
|
|
// we can safely ignore this error, if any
|
|
|
|
if "" != u.email { |
|
|
|
broadcastMsg <- myMsg{ |
|
|
|
sender: nil, |
|
|
|
// TODO fmt.Fprintf()? template?
|
|
|
|
Message: "<" + u.email + "> left #general\n", |
|
|
|
ReceivedAt: time.Now(), |
|
|
|
Channel: "general", |
|
|
|
User: "system", |
|
|
|
} |
|
|
|
} |
|
|
|
close(u.newMsg) |
|
|
|
u.bufConn.Close() |
|
|
|
delete(myRawConns, u.bufConn) |
|
|
|
delete(telnetConns, u.bufConn) |
|
|
|
case bufConn := <-gotClientHello: |
|
|
|
go muxTcp(bufConn) |
|
|
|
case bufConn := <-demuxHttpClient: |
|
|
@ -480,7 +477,7 @@ func main() { |
|
|
|
sender, |
|
|
|
msg.User, msg.Message) |
|
|
|
|
|
|
|
for _, u := range myRawConns { |
|
|
|
for _, u := range telnetConns { |
|
|
|
// Don't echo back to the original client
|
|
|
|
if msg.sender == u.bufConn { |
|
|
|
continue |
|
|
|