github.com/danielpfeifer02/quic-go-prio-packs@v0.41.0-28/prio_packs_example/example_traffic.go (about) 1 package main 2 3 // https://fossies.org/linux/quic-go/example/echo/echo.go 4 // if error: 5 // sudo sysctl -w net.core.rmem_max=2500000 6 // sudo sysctl -w net.core.wmem_max=2500000 7 8 import ( 9 "context" 10 "crypto/rand" 11 "crypto/rsa" 12 "crypto/tls" 13 "crypto/x509" 14 "encoding/pem" 15 "fmt" 16 "math/big" 17 "os" 18 19 "github.com/danielpfeifer02/quic-go-prio-packs" 20 "github.com/danielpfeifer02/quic-go-prio-packs/crypto_turnoff" 21 "github.com/danielpfeifer02/quic-go-prio-packs/priority_setting" 22 ) 23 24 const addr = "192.168.11.2:4242" 25 26 const message = "foobar" 27 28 // We start a server echoing data on the first stream the client opens, 29 // then connect with a client, send the message, and wait for its receipt. 30 func main() { 31 32 // check that there is an argument 33 if len(os.Args) != 2 { 34 fmt.Println("Usage: go run example.go server|client") 35 return 36 } 37 38 crypto_turnoff.CRYPTO_TURNED_OFF = true 39 40 // check if the argument is "server" or "client" 41 is_server := os.Args[1] == "server" 42 is_client := os.Args[1] == "client" 43 44 if is_server { 45 err := echoServer() 46 if err != nil { 47 panic(err) 48 } 49 } else if is_client { 50 err := clientMain() 51 if err != nil { 52 panic(err) 53 } 54 } else { 55 fmt.Println("Usage: go run example.go server|client") 56 return 57 } 58 } 59 60 // Start a server that echos all data on the first stream opened by the client 61 func echoServer() error { 62 63 listener, err := quic.ListenAddr(addr, generateTLSConfig(), generateQUICConfig()) 64 if err != nil { 65 return err 66 } 67 defer listener.Close() 68 69 // Accept the incoming connection from the client 70 conn, err := listener.Accept(context.Background()) 71 if err != nil { 72 return err 73 } 74 75 go func() { 76 for { 77 buf, err := conn.ReceiveDatagram(context.Background()) 78 if err != nil { 79 panic(err) 80 } 81 fmt.Printf(" >>Server: Got '%s'\n", string(buf)) 82 err = conn.SendDatagram(buf) 83 if err != nil { 84 panic(err) 85 } 86 fmt.Println(" >>Server: Echoing via datagram") 87 } 88 }() 89 90 // Accept the first stream opened by the client 91 stream_high_prio, err := conn.AcceptStream(context.Background()) 92 if err != nil { 93 panic(err) 94 } 95 defer stream_high_prio.Close() 96 97 // Handle the first stream opened by the client 98 // in a separate goroutine 99 go ListenAndRepeat(stream_high_prio) 100 101 // Accept the second stream opened by the client 102 stream_low_prio, err2 := conn.AcceptStream(context.Background()) 103 if err2 != nil { 104 panic(err2) 105 } 106 defer stream_low_prio.Close() 107 108 // Handle the second stream opened by the client 109 // in the current goroutine 110 // Echo through the loggingWriter 111 ListenAndRepeat(stream_low_prio) 112 113 return nil 114 } 115 116 func ListenAndRepeat(stream quic.Stream) { 117 fmt.Println("Echo up and running") 118 for { 119 // Read and echo the message 120 buf := make([]byte, 1024) 121 n, err := stream.Read(buf) 122 if err != nil { 123 panic(err) 124 } 125 fmt.Printf(" >>Server: Got '%s'\n >>Server: Echoing on same stream\n", string(buf[:n])) 126 _, err = stream.Write(buf) 127 if err != nil { 128 panic(err) 129 } 130 } 131 132 } 133 134 func clientMain() error { 135 tlsConf := &tls.Config{ 136 InsecureSkipVerify: true, 137 NextProtos: []string{"quic-echo-example"}, 138 } 139 conn, err := quic.DialAddr(context.Background(), addr, tlsConf, generateQUICConfig()) 140 if err != nil { 141 return err 142 } 143 defer conn.CloseWithError(0, "") 144 145 // Open a new stream with high priority 146 stream_high_prio, err := conn.OpenStreamSyncWithPriority(context.Background(), priority_setting.HighPriority) 147 if err != nil { 148 return err 149 } 150 defer stream_high_prio.Close() 151 fmt.Printf("Prio of stream one (clientside): %d\n", stream_high_prio.Priority()) 152 153 // Open a new stream with low priority 154 stream_low_prio, err := conn.OpenStreamSyncWithPriority(context.Background(), priority_setting.LowPriority) 155 if err != nil { 156 return err 157 } 158 defer stream_low_prio.Close() 159 fmt.Printf("Prio of stream two (clientside): %d\n", stream_low_prio.Priority()) 160 161 for { 162 163 // Print info field for the user 164 fmt.Println("What would you like to do?") 165 fmt.Println("1: Send a message with high priority over stream") 166 fmt.Println("2: Send a message with low priority over stream") 167 fmt.Println("3: Send a message with high priority via datagrams") 168 fmt.Println("4: Send a message with low priority via datagrans") 169 fmt.Println("5: Quit") 170 171 // Read the user's choice 172 var choice int 173 fmt.Scan(&choice) 174 // clear screen on terminal 175 fmt.Print("\033[H\033[2J") 176 177 var stream quic.Stream 178 var is_stream bool = false 179 var datagram_prio priority_setting.Priority 180 181 // Check the user's choice 182 switch choice { 183 case 1: 184 stream = stream_high_prio 185 is_stream = true 186 case 2: 187 stream = stream_low_prio 188 is_stream = true 189 case 3: 190 datagram_prio = priority_setting.HighPriority 191 case 4: 192 datagram_prio = priority_setting.LowPriority 193 case 5: 194 return nil 195 default: 196 fmt.Println("Invalid choice") 197 continue 198 } 199 200 fmt.Printf(" >>Client: Sending '%s'\n", message) 201 202 var buf []byte 203 var n int 204 if is_stream { 205 _, err := stream.Write([]byte(message)) 206 if err != nil { 207 return err 208 } 209 210 buf = make([]byte, 1024) 211 n, err = stream.Read(buf) 212 if err != nil { 213 return err 214 } 215 } else { 216 err := conn.SendDatagramWithPriority([]byte(message), datagram_prio) 217 if err != nil { 218 return err 219 } 220 221 buf, err = conn.ReceiveDatagram(context.Background()) 222 if err != nil { 223 return err 224 } 225 n = len(buf) 226 } 227 228 fmt.Printf(" >>Client: Got '%s'\n\n", buf[:n]) 229 230 } 231 } 232 233 // Setup a bare-bones TLS config for the server 234 func generateTLSConfig() *tls.Config { 235 key, err := rsa.GenerateKey(rand.Reader, 1024) 236 if err != nil { 237 panic(err) 238 } 239 template := x509.Certificate{SerialNumber: big.NewInt(1)} 240 certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key) 241 if err != nil { 242 panic(err) 243 } 244 keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}) 245 certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}) 246 247 tlsCert, err := tls.X509KeyPair(certPEM, keyPEM) 248 if err != nil { 249 panic(err) 250 } 251 252 // Create a KeyLogWriter 253 keyLogFile, err := os.OpenFile("tls.keylog", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) 254 if err != nil { 255 panic(err) 256 } 257 // defer keyLogFile.Close() // TODO why not close? 258 259 return &tls.Config{ 260 Certificates: []tls.Certificate{tlsCert}, 261 NextProtos: []string{"quic-echo-example"}, 262 KeyLogWriter: keyLogFile, 263 CipherSuites: []uint16{tls.TLS_CHACHA20_POLY1305_SHA256}, 264 } 265 } 266 267 func generateQUICConfig() *quic.Config { 268 return &quic.Config{ 269 EnableDatagrams: true, 270 } 271 }