github.com/danielpfeifer02/quic-go-prio-packs@v0.41.0-28/datagram_example/example.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  	"time"
    19  
    20  	"github.com/danielpfeifer02/quic-go-prio-packs"
    21  	"github.com/danielpfeifer02/quic-go-prio-packs/crypto_turnoff"
    22  	"github.com/danielpfeifer02/quic-go-prio-packs/priority_setting"
    23  	"github.com/danielpfeifer02/quic-go-prio-packs/qlog"
    24  )
    25  
    26  const server_addr = "192.168.11.2:4242"
    27  
    28  const message = "foobar"
    29  
    30  const NUM_MESSAGES = 3
    31  
    32  var PRIO = priority_setting.NoPriority
    33  var PRIO_S = priority_setting.HighPriority
    34  var PRIO_C = priority_setting.LowPriority
    35  
    36  // We start a server echoing data on the first stream the client opens,
    37  // then connect with a client, send the message, and wait for its receipt.
    38  func main() {
    39  
    40  	// expect one argument: "server" or "client"
    41  	if len(os.Args) != 2 {
    42  		fmt.Println("Usage: go run example.go server|client")
    43  		return
    44  	}
    45  
    46  	is_server := os.Args[1] == "server"
    47  	is_client := os.Args[1] == "client"
    48  
    49  	os.Remove("tls.keylog")
    50  	crypto_turnoff.CRYPTO_TURNED_OFF = true
    51  
    52  	if is_server {
    53  		err := echoServer()
    54  		if err != nil {
    55  			panic(err)
    56  		}
    57  	} else if is_client {
    58  		err := clientMain()
    59  		if err != nil {
    60  			panic(err)
    61  		}
    62  	} else {
    63  		fmt.Println("Usage: go run example.go server|client")
    64  	}
    65  
    66  	time.Sleep(100 * time.Millisecond)
    67  }
    68  
    69  // Start a server that echos all data on the first stream opened by the client
    70  func echoServer() error {
    71  
    72  	listener, err := quic.ListenAddr(server_addr, generateTLSConfig(), generateQUICConfig())
    73  	if err != nil {
    74  		panic(err)
    75  	}
    76  	defer listener.Close()
    77  
    78  	// Accept the incoming connection from the client
    79  	conn, err := listener.Accept(context.Background())
    80  	if err != nil {
    81  		panic(err)
    82  	}
    83  
    84  	for i := 1; i <= NUM_MESSAGES; i++ {
    85  
    86  		data, err := conn.ReceiveDatagram(context.Background())
    87  		if err != nil {
    88  			return err
    89  		}
    90  		fmt.Printf("	>>Server: Got '%s'\n", string(data))
    91  		err = conn.SendDatagramWithPriority([]byte(data), PRIO_S)
    92  		// err = conn.SendDatagram([]byte(data))
    93  		if err != nil {
    94  			return err
    95  		}
    96  
    97  	}
    98  
    99  	time.Sleep(100 * time.Millisecond)
   100  
   101  	return nil
   102  }
   103  
   104  func clientMain() error {
   105  	tlsConf := &tls.Config{
   106  		InsecureSkipVerify: true,
   107  		NextProtos:         []string{"quic-echo-example"},
   108  	}
   109  	conn, err := quic.DialAddr(context.Background(), server_addr, tlsConf, generateQUICConfig())
   110  	if err != nil {
   111  		return err
   112  	}
   113  	defer conn.CloseWithError(0, "")
   114  
   115  	// Open a new stream
   116  	// stream_prio, err := conn.OpenStreamSyncWithPriority(context.Background(), priority_setting.HighPriority)
   117  	// if err != nil {
   118  	// 	return err
   119  	// }
   120  	// defer stream_prio.Close()
   121  
   122  	for i := 1; i <= NUM_MESSAGES; i++ {
   123  
   124  		fmt.Printf("	>>Client: Sending '%s%d'\n", message, i)
   125  
   126  		err := conn.SendDatagramWithPriority([]byte(message+fmt.Sprintf("%d", i)), PRIO_C)
   127  		// err := conn.SendDatagram([]byte(message + fmt.Sprintf("%d", i)))
   128  		if err != nil {
   129  			return err
   130  		}
   131  		buf, err := conn.ReceiveDatagram(context.Background())
   132  		if err != nil {
   133  			return err
   134  		}
   135  		fmt.Printf("	>>Client: Got '%s'\n\n", buf)
   136  
   137  	}
   138  
   139  	time.Sleep(100 * time.Millisecond)
   140  
   141  	return nil
   142  }
   143  
   144  // Setup a bare-bones TLS config for the server
   145  func generateTLSConfig() *tls.Config {
   146  	key, err := rsa.GenerateKey(rand.Reader, 1024)
   147  	if err != nil {
   148  		panic(err)
   149  	}
   150  	template := x509.Certificate{SerialNumber: big.NewInt(1)}
   151  	certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key)
   152  	if err != nil {
   153  		panic(err)
   154  	}
   155  	keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})
   156  	certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
   157  
   158  	tlsCert, err := tls.X509KeyPair(certPEM, keyPEM)
   159  	if err != nil {
   160  		panic(err)
   161  	}
   162  
   163  	// Create a KeyLogWriter
   164  	keyLogFile, err := os.OpenFile("tls.keylog", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
   165  	if err != nil {
   166  		panic(err)
   167  	}
   168  	// defer keyLogFile.Close() // TODO why not close?
   169  
   170  	return &tls.Config{
   171  		Certificates: []tls.Certificate{tlsCert},
   172  		NextProtos:   []string{"quic-echo-example"},
   173  		KeyLogWriter: keyLogFile,
   174  		CipherSuites: []uint16{tls.TLS_CHACHA20_POLY1305_SHA256},
   175  	}
   176  }
   177  
   178  func generateQUICConfig() *quic.Config {
   179  	return &quic.Config{
   180  		Tracer:          qlog.DefaultTracer,
   181  		EnableDatagrams: true,
   182  	}
   183  }