mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-02 19:57:35 +03:00
uTLS is not yet bumped to the new version, so this commit breaks the dependencies relationship by getting rid of the local replace.
114 lines
2.5 KiB
Go
114 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/x509"
|
|
"encoding/pem"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"math/big"
|
|
|
|
tls "github.com/refraction-networking/utls"
|
|
|
|
quic "github.com/refraction-networking/uquic"
|
|
)
|
|
|
|
const addr = "localhost:4242"
|
|
|
|
const message = "foobar"
|
|
|
|
// We start a server echoing data on the first stream the client opens,
|
|
// then connect with a client, send the message, and wait for its receipt.
|
|
func main() {
|
|
go func() { log.Fatal(echoServer()) }()
|
|
|
|
err := clientMain()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
// Start a server that echos all data on the first stream opened by the client
|
|
func echoServer() error {
|
|
listener, err := quic.ListenAddr(addr, generateTLSConfig(), nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
conn, err := listener.Accept(context.Background())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
stream, err := conn.AcceptStream(context.Background())
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
// Echo through the loggingWriter
|
|
_, err = io.Copy(loggingWriter{stream}, stream)
|
|
return err
|
|
}
|
|
|
|
func clientMain() error {
|
|
tlsConf := &tls.Config{
|
|
InsecureSkipVerify: true,
|
|
NextProtos: []string{"quic-echo-example"},
|
|
}
|
|
conn, err := quic.DialAddr(context.Background(), addr, tlsConf, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
stream, err := conn.OpenStreamSync(context.Background())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Printf("Client: Sending '%s'\n", message)
|
|
_, err = stream.Write([]byte(message))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
buf := make([]byte, len(message))
|
|
_, err = io.ReadFull(stream, buf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Printf("Client: Got '%s'\n", buf)
|
|
|
|
return nil
|
|
}
|
|
|
|
// A wrapper for io.Writer that also logs the message.
|
|
type loggingWriter struct{ io.Writer }
|
|
|
|
func (w loggingWriter) Write(b []byte) (int, error) {
|
|
fmt.Printf("Server: Got '%s'\n", string(b))
|
|
return w.Writer.Write(b)
|
|
}
|
|
|
|
// Setup a bare-bones TLS config for the server
|
|
func generateTLSConfig() *tls.Config {
|
|
key, err := rsa.GenerateKey(rand.Reader, 1024)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
template := x509.Certificate{SerialNumber: big.NewInt(1)}
|
|
certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})
|
|
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
|
|
|
|
tlsCert, err := tls.X509KeyPair(certPEM, keyPEM)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return &tls.Config{
|
|
Certificates: []tls.Certificate{tlsCert},
|
|
NextProtos: []string{"quic-echo-example"},
|
|
}
|
|
}
|