Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add QUIC server support #423

Open
wants to merge 26 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f0e9732
feat: basic sketch for QUICAcceptor
juniorjse Oct 7, 2024
c7c961c
refactor: add TODO for HTTP/3 integration while awaiting testing
juniorjse Oct 7, 2024
b6ebaf3
refactor: add TODO for HTTP/3 integration while awaiting testing
juniorjse Oct 7, 2024
996c7c9
refactor: update QUIC acceptor to use quic-go, add connection wrapper…
juniorjse Oct 8, 2024
952f655
feat: Refactor QUIC acceptor
juniorjse Oct 8, 2024
3093d37
feat: Refactor QUIC acceptor
juniorjse Oct 8, 2024
52b3d8c
fix: increase context timeout in Accept method to prevent deadline ex…
juniorjse Oct 8, 2024
5fe9bc7
refact: TLS config
juniorjse Oct 9, 2024
51a72c1
refactor: adjust time
juniorjse Oct 10, 2024
046174c
feat: adding a server that uses NewQuicAcceptor but does not follow t…
juniorjse Oct 14, 2024
f83a633
feat: created connectToQUIC logic
Oct 14, 2024
98a3e19
feat: receiving and sending encoded messages
Oct 15, 2024
5af9cdb
refactor: message pattern
juniorjse Oct 15, 2024
d7cdb0e
feat: adding heartbeat to keep connection alive
Oct 15, 2024
5ecf6c3
Merge branch 'feature/quic-server' of https://github.com/juniorjse/pi…
Oct 15, 2024
025e85c
feat: making client work for cluster_grpc server
Oct 16, 2024
4f0a099
feat: making connectToQuic in pitaya-cli
Oct 17, 2024
f0bfa2f
feat: changing xk6-pitaya client to connect via QUIC
Oct 28, 2024
85d044c
refactor: housecleaning - deleting files that were not being used any…
Nov 7, 2024
c6b21b0
refactor: removing forgotten debug logs
Nov 7, 2024
79d5738
refactor: remove main_quic and simplify to a single main
juniorjse Nov 11, 2024
3d2a7dc
refactor: Make QuicConnWrapper timeout configurable with default of 1…
juniorjse Nov 11, 2024
8364172
refactor: enhance QUIC stream message handling with header parsing, t…
juniorjse Nov 11, 2024
8ac55ef
refactor: fix xk6 build and modified scenarios for quic server
Nov 21, 2024
817eb41
feat: Add flag to select TCP or QUIC as acceptor
juniorjse Nov 21, 2024
7d6b914
fix: fixing requests timeouts
Nov 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: created connectToQUIC logic
  • Loading branch information
Victor Emanuel Barbosa Rodrigues (EXT) committed Oct 14, 2024
commit f83a633bf9404ee6bf35b7086ff7f8463d7faa2a
43 changes: 17 additions & 26 deletions examples/demo/client.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package main

import (
"context"
"crypto/tls"
"fmt"
"log"
"time"
"github.com/sirupsen/logrus"

"github.com/quic-go/quic-go"
"github.com/topfreegames/pitaya/v3/pkg/client"
)

func main() {
Expand All @@ -16,41 +16,32 @@ func main() {
InsecureSkipVerify: true, // Only for testing, do not use in production
}

// Create context
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

// Define QUIC configurations (can be nil if not needed)
quicConf := &quic.Config{}

// Connect to the server using QUIC
addr := "localhost:3250"
session, err := quic.DialAddr(ctx, addr, tlsConf, quicConf)
if err != nil {
c := client.New(logrus.InfoLevel)

conn, err := c.ConnectToQUIC("localhost:3250", tlsConf, quicConf)

if(err != nil) {
log.Fatalf("Failed to connect to server: %v", err)
}
defer session.CloseWithError(0, "connection closed")

msg := "Hello from QUIC client!"
fmt.Printf("Sending message: %v\n", msg)
_, err = conn.Write([]byte(msg))

// Open a stream to send data
stream, err := session.OpenStreamSync(ctx)
if err != nil {
log.Fatalf("Failed to open stream: %v", err)
if(err != nil) {
log.Fatalf("Failed to send data: %v\n", err)
}
defer stream.Close()

// Send message to the server
message := "Hello from QUIC client!"
fmt.Printf("Sending message: %s\n", message)
_, err = stream.Write([]byte(message))
if err != nil {
log.Fatalf("Failed to send data: %v", err)
}
fmt.Printf("it's all ok\n")

// Receive response from the server
buffer := make([]byte, 1024)
n, err := stream.Read(buffer)
n, err := conn.Read(buffer)

if err != nil {
log.Fatalf("Failed to read response: %v", err)
log.Fatalf("Failed to read response data: %v\n", err)
}

fmt.Printf("Response from server: %s\n", string(buffer[:n]))
Expand Down
12 changes: 3 additions & 9 deletions examples/demo/cluster_grpc/server.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package main

import (
"context"
"crypto/tls"
"fmt"
"log"
Expand Down Expand Up @@ -45,18 +44,13 @@ func main() {
}

func handleConnection(conn quic.Connection) {
defer conn.CloseWithError(0, "sessão encerrada")

// Aceitar um stream
stream, err := conn.AcceptStream(context.Background())
if err != nil {
log.Printf("Erro ao aceitar stream: %v", err)
return
}
c := acceptor.NewQuicConnWrapper(conn)

// Ler dados do cliente
buff := make([]byte, 1024)
n, err := stream.Read(buff)
n, err := c.Read(buff)
if err != nil {
log.Printf("Erro ao ler do stream: %v", err)
return
Expand All @@ -65,7 +59,7 @@ func handleConnection(conn quic.Connection) {

// Enviar resposta ao cliente
response := "Olá, cliente QUIC!"
_, err = stream.Write([]byte(response))
_, err = c.Write([]byte(response))
if err != nil {
log.Printf("Erro ao enviar resposta: %v", err)
return
Expand Down
11 changes: 4 additions & 7 deletions pkg/acceptor/quic_acceptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func (a *QuicAcceptor) Accept() (quic.Connection, error) {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

conn, err := (*a.listener).Accept(ctx)
conn, err := a.listener.Accept(ctx)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -125,8 +125,7 @@ func (a *QuicAcceptor) GetConfiguredAddress() string {

func (a *QuicAcceptor) ListenAndServe() {
// Start the QUIC listener
err := a.Listen()
if err != nil {
if err := a.Listen(); err != nil {
fmt.Printf("Failed to start QUIC listener: %s\n", err)
return
}
Expand Down Expand Up @@ -163,8 +162,7 @@ func NewQuicConnWrapper(conn quic.Connection) *QuicConnWrapper {

// Read reads data from the QUIC connection
func (q *QuicConnWrapper) Read(p []byte) (int, error) {
ctx, cancel := context.WithTimeout(context.Background(), 1000*time.Second) // 1000 seconds timeout as an example
defer cancel()
ctx, _ := context.WithTimeout(context.Background(), 1000*time.Second) // 1000 seconds timeout as an example

stream, err := q.conn.AcceptStream(ctx)
if err != nil {
Expand All @@ -176,8 +174,7 @@ func (q *QuicConnWrapper) Read(p []byte) (int, error) {

// Write writes data to the connection with a defined deadline
func (q *QuicConnWrapper) Write(p []byte) (int, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) // 1000 seconds timeout as an example
defer cancel()
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) // 1000 seconds timeout as an example

stream, err := q.conn.OpenStreamSync(ctx)
if err != nil {
Expand Down
26 changes: 26 additions & 0 deletions pkg/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package client

import (
"bytes"
"context"
"crypto/tls"
"encoding/json"
"errors"
Expand All @@ -34,6 +35,7 @@ import (

"github.com/topfreegames/pitaya/v3/pkg/acceptor"

"github.com/quic-go/quic-go"
"github.com/gorilla/websocket"
"github.com/sirupsen/logrus"
"github.com/topfreegames/pitaya/v3/pkg"
Expand Down Expand Up @@ -282,6 +284,7 @@ func (c *Client) readPackets(buf *bytes.Buffer) ([]*packet.Packet, error) {
}
buf.Write(data[:n])
}
fmt.Printf("Response from server: %s\n", string(data[:n]))
packets, err := c.packetDecoder.Decode(buf.Bytes())
if err != nil {
logger.Log.Errorf("error decoding packet from server: %s", err.Error())
Expand Down Expand Up @@ -366,6 +369,29 @@ func (c *Client) ConnectTo(addr string, tlsConfig ...*tls.Config) error {
return nil
}

func (c *Client) ConnectToQUIC(addr string, tlsConfig *tls.Config, quicConfig *quic.Config) (net.Conn, error) {
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)

conn, err := quic.DialAddr(ctx, addr, tlsConfig, quicConfig)
if err != nil {
fmt.Printf("Failed to connect to server: %v", err)
return nil, err;
}

c.conn = acceptor.NewQuicConnWrapper(conn);

c.IncomingMsgChan = make(chan *message.Message, 10)

c.closeChan = make(chan struct{})

/*go c.sendHeartbeats(30)
go c.handleServerMessages()
go c.handlePackets()
go c.pendingRequestsReaper()*/

return c.conn, nil
}

// ConnectToWS connects using webshocket protocol
func (c *Client) ConnectToWS(addr string, path string, tlsConfig ...*tls.Config) error {
u := url.URL{Scheme: "ws", Host: addr, Path: path}
Expand Down
2 changes: 2 additions & 0 deletions pkg/client/pitayaclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ import (

"github.com/topfreegames/pitaya/v3/pkg/conn/message"
"github.com/topfreegames/pitaya/v3/pkg/session"
"github.com/quic-go/quic-go"
)

// PitayaClient iface
type PitayaClient interface {
ConnectTo(addr string, tlsConfig ...*tls.Config) error
ConnectToWS(addr string, path string, tlsConfig ...*tls.Config) error
ConnectToQUIC(addr string, tlsConfig *tls.Config, quicConfig *quic.Config) error
ConnectedStatus() bool
Disconnect()
MsgChannel() chan *message.Message
Expand Down