Compare commits
	
		
			5 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 1061dd4c71 | |||
| db15b22e40 | |||
| bfdabd1228 | |||
| ccf0f28da7 | |||
| c5100b35bf | 
							
								
								
									
										24
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								README.md
									
									
									
									
									
								
							@ -38,6 +38,28 @@ You can also use HTTP.
 | 
				
			|||||||
curl http://localhost:4080
 | 
					curl http://localhost:4080
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Testing Beyond Localhost
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can use [Telebit](https://telebit.cloud) to share the experience with friends and loved ones:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Completely userspace installation:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					curl -fsSL https://get.telebit.cloud | bash
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Easy configuration:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					~/telebit http 4080
 | 
				
			||||||
 | 
					> Forwarding https://lucky-duck-42.telebit.fun => localhost:4080
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					~/telebit tcp 4080
 | 
				
			||||||
 | 
					> Forwarding telebit.cloud:1234 => localhost:4080
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Caveat: Due to a bug in telebit you must send 'hello' in telnet to establish a connection.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# API Docs
 | 
					# API Docs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The API docs and examples can be seen at <http://localhost:4080>
 | 
					The API docs and examples can be seen at <http://localhost:4080>
 | 
				
			||||||
@ -93,7 +115,7 @@ Not Implemented
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
I don't think these things would be difficult to add,
 | 
					I don't think these things would be difficult to add,
 | 
				
			||||||
but I was having fun learning lots of other things
 | 
					but I was having fun learning lots of other things
 | 
				
			||||||
and I figured Some of these things I didn't implement
 | 
					and I figured they're not that important.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* [ ] local log file
 | 
					* [ ] local log file
 | 
				
			||||||
* [ ] Rooms
 | 
					* [ ] Rooms
 | 
				
			||||||
 | 
				
			|||||||
@ -83,6 +83,7 @@ func handleTelnetConn(bufConn bufferedConn) {
 | 
				
			|||||||
				email = strings.TrimSpace(msg)
 | 
									email = strings.TrimSpace(msg)
 | 
				
			||||||
				emailParts := strings.Split(email, "@")
 | 
									emailParts := strings.Split(email, "@")
 | 
				
			||||||
				if 2 != len(emailParts) {
 | 
									if 2 != len(emailParts) {
 | 
				
			||||||
 | 
										email = ""
 | 
				
			||||||
					fmt.Fprintf(bufConn, "Email: ")
 | 
										fmt.Fprintf(bufConn, "Email: ")
 | 
				
			||||||
					continue
 | 
										continue
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,6 @@ import (
 | 
				
			|||||||
	"encoding/base64"
 | 
						"encoding/base64"
 | 
				
			||||||
	"flag"
 | 
						"flag"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
					 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
@ -43,12 +42,12 @@ type ConfMailer struct {
 | 
				
			|||||||
// https://stackoverflow.com/questions/51472020/how-to-get-the-size-of-available-tcp-data
 | 
					// https://stackoverflow.com/questions/51472020/how-to-get-the-size-of-available-tcp-data
 | 
				
			||||||
type bufferedConn struct {
 | 
					type bufferedConn struct {
 | 
				
			||||||
	r *bufio.Reader
 | 
						r *bufio.Reader
 | 
				
			||||||
	rout io.Reader // See https://github.com/polvi/sni/blob/master/sni.go#L135
 | 
						//rout *io.Reader // See https://github.com/polvi/sni/blob/master/sni.go#L135
 | 
				
			||||||
	net.Conn
 | 
						net.Conn
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newBufferedConn(c net.Conn) bufferedConn {
 | 
					func newBufferedConn(c net.Conn) bufferedConn {
 | 
				
			||||||
	return bufferedConn{bufio.NewReader(c), nil, c}
 | 
						return bufferedConn{bufio.NewReader(c), c}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (b bufferedConn) Peek(n int) ([]byte, error) {
 | 
					func (b bufferedConn) Peek(n int) ([]byte, error) {
 | 
				
			||||||
@ -60,9 +59,11 @@ func (b bufferedConn) Buffered() int {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (b bufferedConn) Read(p []byte) (int, error) {
 | 
					func (b bufferedConn) Read(p []byte) (int, error) {
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
		if b.rout != nil {
 | 
							if b.rout != nil {
 | 
				
			||||||
			return b.rout.Read(p)
 | 
								return b.rout.Read(p)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						*/
 | 
				
			||||||
	return b.r.Read(p)
 | 
						return b.r.Read(p)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -91,7 +92,7 @@ var broadcastMsg chan chatMsg
 | 
				
			|||||||
// Telnet
 | 
					// Telnet
 | 
				
			||||||
var wantsServerHello chan bufferedConn
 | 
					var wantsServerHello chan bufferedConn
 | 
				
			||||||
var authTelnet chan telnetUser
 | 
					var authTelnet chan telnetUser
 | 
				
			||||||
var cleanTelnet chan telnetUser
 | 
					var cleanTelnet chan telnetUser // intentionally blocking
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// HTTP
 | 
					// HTTP
 | 
				
			||||||
var demuxHttpClient chan bufferedConn
 | 
					var demuxHttpClient chan bufferedConn
 | 
				
			||||||
@ -100,7 +101,7 @@ var valAuthReqs chan authReq
 | 
				
			|||||||
var delAuthReqs chan authReq
 | 
					var delAuthReqs chan authReq
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func usage() {
 | 
					func usage() {
 | 
				
			||||||
	fmt.Fprintf(os.Stderr, "\nusage: go run chatserver.go\n")
 | 
						fmt.Fprintf(os.Stderr, "\nusage: go run chatserver*.go\n")
 | 
				
			||||||
	flag.PrintDefaults()
 | 
						flag.PrintDefaults()
 | 
				
			||||||
	fmt.Println()
 | 
						fmt.Println()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -166,6 +167,9 @@ func muxTcp(conn bufferedConn) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if "" == protocol {
 | 
						if "" == protocol {
 | 
				
			||||||
 | 
							// Throw away the first bytes
 | 
				
			||||||
 | 
							b := make([]byte, 4096)
 | 
				
			||||||
 | 
							conn.Read(b)
 | 
				
			||||||
		fmt.Fprintf(conn, "\n\nWelcome to Sample Chat! You're not an HTTP client, assuming Telnet.\nYou must authenticate via email to participate\n\nEmail: ")
 | 
							fmt.Fprintf(conn, "\n\nWelcome to Sample Chat! You're not an HTTP client, assuming Telnet.\nYou must authenticate via email to participate\n\nEmail: ")
 | 
				
			||||||
		wantsServerHello <- conn
 | 
							wantsServerHello <- conn
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@ -297,7 +301,7 @@ func main() {
 | 
				
			|||||||
	virginConns = make(chan net.Conn, 128)
 | 
						virginConns = make(chan net.Conn, 128)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TCP & Authentication
 | 
						// TCP & Authentication
 | 
				
			||||||
	telnetConns := make(map[bufferedConn]telnetUser)
 | 
						telnetConns := make(map[string]telnetUser)
 | 
				
			||||||
	wantsServerHello = make(chan bufferedConn, 128)
 | 
						wantsServerHello = make(chan bufferedConn, 128)
 | 
				
			||||||
	authTelnet = make(chan telnetUser, 128)
 | 
						authTelnet = make(chan telnetUser, 128)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -385,7 +389,12 @@ func main() {
 | 
				
			|||||||
		case u := <-authTelnet:
 | 
							case u := <-authTelnet:
 | 
				
			||||||
			// allow to receive messages
 | 
								// allow to receive messages
 | 
				
			||||||
			// (and be counted among the users)
 | 
								// (and be counted among the users)
 | 
				
			||||||
			telnetConns[u.bufConn] = u
 | 
								_, ok := telnetConns[u.email]
 | 
				
			||||||
 | 
								if ok {
 | 
				
			||||||
 | 
									// this is a blocking channel, and that's important
 | 
				
			||||||
 | 
									cleanTelnet <- telnetConns[u.email]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								telnetConns[u.email] = u
 | 
				
			||||||
			// is chan chan the right way to handle this?
 | 
								// is chan chan the right way to handle this?
 | 
				
			||||||
			u.userCount <- len(telnetConns)
 | 
								u.userCount <- len(telnetConns)
 | 
				
			||||||
			broadcastMsg <- chatMsg{
 | 
								broadcastMsg <- chatMsg{
 | 
				
			||||||
@ -418,7 +427,7 @@ func main() {
 | 
				
			|||||||
			close(u.newMsg)
 | 
								close(u.newMsg)
 | 
				
			||||||
			// we can safely ignore this error, if any
 | 
								// we can safely ignore this error, if any
 | 
				
			||||||
			u.bufConn.Close()
 | 
								u.bufConn.Close()
 | 
				
			||||||
			delete(telnetConns, u.bufConn)
 | 
								delete(telnetConns, u.email)
 | 
				
			||||||
		case bufConn := <-gotClientHello:
 | 
							case bufConn := <-gotClientHello:
 | 
				
			||||||
			go muxTcp(bufConn)
 | 
								go muxTcp(bufConn)
 | 
				
			||||||
		case bufConn := <-demuxHttpClient:
 | 
							case bufConn := <-demuxHttpClient:
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user