github.com/micro/go-micro/examples@v0.0.0-20210105173217-bf4ab679e18b/tunnel/echo/main.go (about) 1 package main 2 3 import ( 4 "bufio" 5 "flag" 6 "fmt" 7 "os" 8 9 "github.com/google/uuid" 10 "github.com/micro/go-micro/v2/transport" 11 "github.com/micro/go-micro/v2/tunnel" 12 ) 13 14 var ( 15 address = flag.String("address", ":10001", "tunnel address") 16 nodes = flag.String("nodes", "", "tunnel nodes") 17 channel = flag.String("channel", "default", "the channel") 18 ) 19 20 func readLoop(c tunnel.Session, readChan chan *transport.Message) { 21 for { 22 m := new(transport.Message) 23 if err := c.Recv(m); err != nil { 24 return 25 } 26 27 // fire them into the channel 28 select { 29 case readChan <- m: 30 default: 31 } 32 } 33 } 34 35 func writeLoop(c tunnel.Session, sendChan chan *transport.Message) { 36 for { 37 m := <-sendChan 38 39 // don't relay back to sender 40 if c.Id() == m.Header["Session"] { 41 continue 42 } 43 44 // send messages 45 if err := c.Send(m); err != nil { 46 return 47 } 48 } 49 } 50 51 func serverAccept(l tunnel.Listener, sendChan chan *transport.Message) { 52 connCh := make(chan chan *transport.Message) 53 54 go func() { 55 conns := make(map[string]chan *transport.Message) 56 57 for { 58 // send all things we're writing to all connections 59 select { 60 case b := <-sendChan: 61 for _, c := range conns { 62 select { 63 case c <- b: 64 default: 65 } 66 } 67 // append new connections 68 case c := <-connCh: 69 conns[uuid.New().String()] = c 70 } 71 } 72 }() 73 74 for { 75 c, err := l.Accept() 76 if err != nil { 77 return 78 } 79 80 fmt.Println("Accepting new connection") 81 82 // pass to reader 83 rch := make(chan *transport.Message) 84 connCh <- rch 85 86 // send anything we receive 87 go readLoop(c, sendChan) 88 89 // write our messages to conn 90 go writeLoop(c, rch) 91 } 92 } 93 94 func main() { 95 flag.Parse() 96 97 // create a tunnel 98 tun := tunnel.NewTunnel( 99 tunnel.Address(*address), 100 tunnel.Nodes(*nodes), 101 ) 102 if err := tun.Connect(); err != nil { 103 fmt.Println(err) 104 return 105 } 106 defer tun.Close() 107 108 // listen for inbound messages on the channel 109 l, err := tun.Listen(*channel) 110 if err != nil { 111 fmt.Println(err) 112 return 113 } 114 defer l.Close() 115 116 sendChan := make(chan *transport.Message) 117 printChan := make(chan *transport.Message) 118 119 // accept the messages on the channel 120 go serverAccept(l, sendChan) 121 122 // client code 123 124 // dial an outbound connection for the channel 125 c, err := tun.Dial(*channel) 126 if err != nil { 127 fmt.Println(err) 128 return 129 } 130 defer c.Close() 131 132 // write the things we get back 133 go func() { 134 for m := range printChan { 135 if m.Header["Session"] == c.Id() { 136 continue 137 } 138 fmt.Println(string(m.Body)) 139 } 140 }() 141 142 // read and print what we get back on the dialled conn 143 go readLoop(c, printChan) 144 145 // read input and send over the tunnel 146 scanner := bufio.NewScanner(os.Stdin) 147 148 for scanner.Scan() { 149 m := &transport.Message{ 150 Header: map[string]string{ 151 "Session": c.Id(), 152 }, 153 Body: scanner.Bytes(), 154 } 155 156 // send to all listeners 157 sendChan <- m 158 159 // send it also 160 c.Send(m) 161 } 162 }