add quic dialer

This commit is contained in:
ginuerzh
2021-12-17 00:23:08 +08:00
parent c7f5da6ac7
commit 965c6846dd
15 changed files with 385 additions and 71 deletions

View File

@ -0,0 +1,134 @@
package http2
import (
"context"
"errors"
"net"
"net/http"
"time"
)
// a dummy HTTP2 client conn used by HTTP2 client connector
type ClientConn struct {
localAddr net.Addr
remoteAddr net.Addr
client *http.Client
onClose func()
}
func NewClientConn(localAddr, remoteAddr net.Addr, client *http.Client, onClose func()) net.Conn {
return &ClientConn{
localAddr: localAddr,
remoteAddr: remoteAddr,
client: client,
onClose: onClose,
}
}
func (c *ClientConn) Client() *http.Client {
return c.client
}
func (c *ClientConn) Close() error {
if c.onClose != nil {
c.onClose()
}
return nil
}
func (c *ClientConn) Read(b []byte) (n int, err error) {
return 0, &net.OpError{Op: "read", Net: "nop", Source: nil, Addr: nil, Err: errors.New("read not supported")}
}
func (c *ClientConn) Write(b []byte) (n int, err error) {
return 0, &net.OpError{Op: "write", Net: "nop", Source: nil, Addr: nil, Err: errors.New("write not supported")}
}
func (c *ClientConn) LocalAddr() net.Addr {
return c.localAddr
}
func (c *ClientConn) RemoteAddr() net.Addr {
return c.remoteAddr
}
func (c *ClientConn) SetDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "nop", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}
func (c *ClientConn) SetReadDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "nop", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}
func (c *ClientConn) SetWriteDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "nop", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}
// a dummy HTTP2 server conn used by HTTP2 handler
type ServerConn struct {
r *http.Request
w http.ResponseWriter
cancel context.CancelFunc
}
func NewServerConn(w http.ResponseWriter, r *http.Request) *ServerConn {
ctx, cancel := context.WithCancel(r.Context())
return &ServerConn{
r: r.Clone(ctx),
w: w,
cancel: cancel,
}
}
func (c *ServerConn) Done() <-chan struct{} {
return c.r.Context().Done()
}
func (c *ServerConn) Request() *http.Request {
return c.r
}
func (c *ServerConn) Writer() http.ResponseWriter {
return c.w
}
func (c *ServerConn) Read(b []byte) (n int, err error) {
return 0, &net.OpError{Op: "read", Net: "http2", Source: nil, Addr: nil, Err: errors.New("read not supported")}
}
func (c *ServerConn) Write(b []byte) (n int, err error) {
return 0, &net.OpError{Op: "write", Net: "http2", Source: nil, Addr: nil, Err: errors.New("write not supported")}
}
func (c *ServerConn) Close() error {
c.cancel()
select {
case <-c.r.Context().Done():
default:
}
return nil
}
func (c *ServerConn) LocalAddr() net.Addr {
addr, _ := net.ResolveTCPAddr("tcp", c.r.Host)
return addr
}
func (c *ServerConn) RemoteAddr() net.Addr {
addr, _ := net.ResolveTCPAddr("tcp", c.r.RemoteAddr)
return addr
}
func (c *ServerConn) SetDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}
func (c *ServerConn) SetReadDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}
func (c *ServerConn) SetWriteDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}

View File

@ -0,0 +1,97 @@
package quic
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"errors"
"io"
"net"
)
type cipherConn struct {
*net.UDPConn
key []byte
}
func CipherConn(conn *net.UDPConn, key []byte) net.Conn {
return &cipherConn{
UDPConn: conn,
key: key,
}
}
func CipherPacketConn(conn *net.UDPConn, key []byte) net.PacketConn {
return &cipherConn{
UDPConn: conn,
key: key,
}
}
func (conn *cipherConn) ReadFrom(data []byte) (n int, addr net.Addr, err error) {
n, addr, err = conn.UDPConn.ReadFrom(data)
if err != nil {
return
}
b, err := conn.decrypt(data[:n])
if err != nil {
return
}
copy(data, b)
return len(b), addr, nil
}
func (conn *cipherConn) WriteTo(data []byte, addr net.Addr) (n int, err error) {
b, err := conn.encrypt(data)
if err != nil {
return
}
_, err = conn.UDPConn.WriteTo(b, addr)
if err != nil {
return
}
return len(b), nil
}
func (conn *cipherConn) encrypt(data []byte) ([]byte, error) {
c, err := aes.NewCipher(conn.key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(c)
if err != nil {
return nil, err
}
nonce := make([]byte, gcm.NonceSize())
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
return nil, err
}
return gcm.Seal(nonce, nonce, data, nil), nil
}
func (conn *cipherConn) decrypt(data []byte) ([]byte, error) {
c, err := aes.NewCipher(conn.key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(c)
if err != nil {
return nil, err
}
nonceSize := gcm.NonceSize()
if len(data) < nonceSize {
return nil, errors.New("ciphertext too short")
}
nonce, ciphertext := data[:nonceSize], data[nonceSize:]
return gcm.Open(nil, nonce, ciphertext, nil)
}