Created
June 25, 2023 17:50
-
-
Save kehiy/e7ea872315d48402cec28f9fd3cfd96e to your computer and use it in GitHub Desktop.
QUIC protocol simple server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"crypto/rand" | |
"crypto/rsa" | |
"crypto/tls" | |
"crypto/x509" | |
"encoding/pem" | |
"fmt" | |
"io" | |
"log" | |
"math/big" | |
"github.com/quic-go/quic-go" | |
) | |
const addr = "localhost:4242" | |
// the message we sent to server you can also change it! | |
const message = "hello gifarsi!" | |
// starting the server and call the client function. | |
func main() { | |
go func() { log.Fatal(echoServer()) }() | |
err := clientMain() | |
if err != nil { | |
panic(err) | |
} | |
} | |
// this function start our echo server | |
func echoServer() error { | |
// make a new listner with quic | |
listener, err := quic.ListenAddr(addr, generateTLSConfig(), nil) | |
if err != nil { | |
return err | |
} | |
// accept incoming connections | |
conn, err := listener.Accept(context.Background()) | |
if err != nil { | |
return err | |
} | |
// accept incoming streams | |
stream, err := conn.AcceptStream(context.Background()) | |
if err != nil { | |
panic(err) | |
} | |
// Echo using the loggingWriter | |
_, err = io.Copy(loggingWriter{stream}, stream) | |
return err | |
} | |
// client function thah send the message to our server | |
func clientMain() error { | |
// set up a tls config | |
tlsConf := &tls.Config{ | |
InsecureSkipVerify: true, | |
NextProtos: []string{"quic-echo-example"}, | |
} | |
// dial with our udp server | |
conn, err := quic.DialAddr(context.Background(), addr, tlsConf, nil) | |
if err != nil { | |
return err | |
} | |
// opening a new stream from our connection | |
stream, err := conn.OpenStreamSync(context.Background()) | |
if err != nil { | |
return err | |
} | |
// write the message over the stream | |
fmt.Printf("Client: Sending '%s'\n", message) | |
_, err = stream.Write([]byte(message)) | |
if err != nil { | |
return err | |
} | |
// read and print incoming answer from server | |
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"}, | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment