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 | ||||
| ``` | ||||
| 
 | ||||
| ## 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 | ||||
| 
 | ||||
| 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, | ||||
| 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 | ||||
| * [ ] Rooms | ||||
|  | ||||
| @ -83,6 +83,7 @@ func handleTelnetConn(bufConn bufferedConn) { | ||||
| 				email = strings.TrimSpace(msg) | ||||
| 				emailParts := strings.Split(email, "@") | ||||
| 				if 2 != len(emailParts) { | ||||
| 					email = "" | ||||
| 					fmt.Fprintf(bufConn, "Email: ") | ||||
| 					continue | ||||
| 				} | ||||
|  | ||||
| @ -10,7 +10,6 @@ import ( | ||||
| 	"encoding/base64" | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"net" | ||||
| 	"net/http" | ||||
| @ -42,13 +41,13 @@ type ConfMailer struct { | ||||
| // So we can peek at net.Conn, which we can't do natively | ||||
| // https://stackoverflow.com/questions/51472020/how-to-get-the-size-of-available-tcp-data | ||||
| type bufferedConn struct { | ||||
| 	r    *bufio.Reader | ||||
| 	rout io.Reader // See https://github.com/polvi/sni/blob/master/sni.go#L135 | ||||
| 	r *bufio.Reader | ||||
| 	//rout *io.Reader // See https://github.com/polvi/sni/blob/master/sni.go#L135 | ||||
| 	net.Conn | ||||
| } | ||||
| 
 | ||||
| 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) { | ||||
| @ -60,9 +59,11 @@ func (b bufferedConn) Buffered() int { | ||||
| } | ||||
| 
 | ||||
| func (b bufferedConn) Read(p []byte) (int, error) { | ||||
| 	if b.rout != nil { | ||||
| 		return b.rout.Read(p) | ||||
| 	} | ||||
| 	/* | ||||
| 		if b.rout != nil { | ||||
| 			return b.rout.Read(p) | ||||
| 		} | ||||
| 	*/ | ||||
| 	return b.r.Read(p) | ||||
| } | ||||
| 
 | ||||
| @ -91,7 +92,7 @@ var broadcastMsg chan chatMsg | ||||
| // Telnet | ||||
| var wantsServerHello chan bufferedConn | ||||
| var authTelnet chan telnetUser | ||||
| var cleanTelnet chan telnetUser | ||||
| var cleanTelnet chan telnetUser // intentionally blocking | ||||
| 
 | ||||
| // HTTP | ||||
| var demuxHttpClient chan bufferedConn | ||||
| @ -100,7 +101,7 @@ var valAuthReqs chan authReq | ||||
| var delAuthReqs chan authReq | ||||
| 
 | ||||
| func usage() { | ||||
| 	fmt.Fprintf(os.Stderr, "\nusage: go run chatserver.go\n") | ||||
| 	fmt.Fprintf(os.Stderr, "\nusage: go run chatserver*.go\n") | ||||
| 	flag.PrintDefaults() | ||||
| 	fmt.Println() | ||||
| 
 | ||||
| @ -166,6 +167,9 @@ func muxTcp(conn bufferedConn) { | ||||
| 	} | ||||
| 
 | ||||
| 	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: ") | ||||
| 		wantsServerHello <- conn | ||||
| 		return | ||||
| @ -297,7 +301,7 @@ func main() { | ||||
| 	virginConns = make(chan net.Conn, 128) | ||||
| 
 | ||||
| 	// TCP & Authentication | ||||
| 	telnetConns := make(map[bufferedConn]telnetUser) | ||||
| 	telnetConns := make(map[string]telnetUser) | ||||
| 	wantsServerHello = make(chan bufferedConn, 128) | ||||
| 	authTelnet = make(chan telnetUser, 128) | ||||
| 
 | ||||
| @ -385,7 +389,12 @@ func main() { | ||||
| 		case u := <-authTelnet: | ||||
| 			// allow to receive messages | ||||
| 			// (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? | ||||
| 			u.userCount <- len(telnetConns) | ||||
| 			broadcastMsg <- chatMsg{ | ||||
| @ -418,7 +427,7 @@ func main() { | ||||
| 			close(u.newMsg) | ||||
| 			// we can safely ignore this error, if any | ||||
| 			u.bufConn.Close() | ||||
| 			delete(telnetConns, u.bufConn) | ||||
| 			delete(telnetConns, u.email) | ||||
| 		case bufConn := <-gotClientHello: | ||||
| 			go muxTcp(bufConn) | ||||
| 		case bufConn := <-demuxHttpClient: | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user