mirror of
https://github.com/dalbodeule/hop-gate.git
synced 2025-12-11 06:15:43 +09:00
[feat](protocol): replace JSON handlers with codec abstraction
- Introduced `WireCodec` interface in `internal/protocol/codec.go` to abstract serialization/deserialization logic. - Updated server and client to use `DefaultCodec`, replacing direct JSON encoding/decoding. - Eliminated `bufio.Reader` from session handling, as `DefaultCodec` manages buffering for DTLS sessions. - Marked related protocol tasks in `progress.md` as complete.
This commit is contained in:
41
internal/protocol/codec.go
Normal file
41
internal/protocol/codec.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
// defaultDecoderBufferSize 는 pion/dtls 가 복호화한 애플리케이션 데이터를
|
||||
// JSON 디코더가 안전하게 처리할 수 있도록 사용하는 버퍼 크기입니다.
|
||||
// This matches existing 64KiB readers used around DTLS sessions.
|
||||
const defaultDecoderBufferSize = 64 * 1024
|
||||
|
||||
// WireCodec 는 protocol.Envelope 의 직렬화/역직렬화를 추상화합니다.
|
||||
// JSON, Protobuf, length-prefixed binary 등으로 교체할 때 이 인터페이스만 유지하면 됩니다.
|
||||
type WireCodec interface {
|
||||
Encode(w io.Writer, env *Envelope) error
|
||||
Decode(r io.Reader, env *Envelope) error
|
||||
}
|
||||
|
||||
// jsonCodec 은 현재 사용 중인 JSON 기반 WireCodec 구현입니다.
|
||||
type jsonCodec struct{}
|
||||
|
||||
// Encode 는 Envelope 를 JSON 으로 인코딩해 작성합니다.
|
||||
// Encode encodes an Envelope as JSON to the given writer.
|
||||
func (jsonCodec) Encode(w io.Writer, env *Envelope) error {
|
||||
enc := json.NewEncoder(w)
|
||||
return enc.Encode(env)
|
||||
}
|
||||
|
||||
// Decode 는 DTLS 세션에서 읽은 데이터를 JSON Envelope 로 디코딩합니다.
|
||||
// pion/dtls 의 버퍼 특성 때문에, 충분히 큰 bufio.Reader 로 감싸서 사용합니다.
|
||||
// Decode decodes an Envelope from JSON using a buffered reader on top of the DTLS session.
|
||||
func (jsonCodec) Decode(r io.Reader, env *Envelope) error {
|
||||
dec := json.NewDecoder(bufio.NewReaderSize(r, defaultDecoderBufferSize))
|
||||
return dec.Decode(env)
|
||||
}
|
||||
|
||||
// DefaultCodec 은 현재 런타임에서 사용하는 기본 WireCodec 입니다.
|
||||
// 초기 구현은 JSON 기반이지만, 추후 Protobuf/length-prefixed binary 로 교체 가능하도록 분리해 두었습니다.
|
||||
var DefaultCodec WireCodec = jsonCodec{}
|
||||
@@ -1,10 +1,8 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
@@ -67,10 +65,10 @@ func (p *ClientProxy) StartLoop(ctx context.Context, sess dtls.Session) error {
|
||||
// "dtls: buffer too small" 오류가 날 수 있으므로, 여기서는 여유 있는 버퍼(64KiB)를 사용합니다. (ko)
|
||||
// NOTE: pion/dtls decrypts application data into the buffer provided by the caller.
|
||||
// Using only the default JSON decoder buffer (a few hundred bytes) can trigger
|
||||
// "dtls: buffer too small" for large HTTP bodies/envelopes, so we wrap the
|
||||
// session with a reasonably large bufio.Reader (64KiB). (en)
|
||||
dec := json.NewDecoder(bufio.NewReaderSize(sess, 64*1024))
|
||||
enc := json.NewEncoder(sess)
|
||||
// "dtls: buffer too small" for large HTTP bodies/envelopes. The default
|
||||
// JSON-based WireCodec internally wraps the DTLS session with a 64KiB
|
||||
// bufio.Reader, matching this requirement. (en)
|
||||
codec := protocol.DefaultCodec
|
||||
|
||||
for {
|
||||
select {
|
||||
@@ -83,7 +81,7 @@ func (p *ClientProxy) StartLoop(ctx context.Context, sess dtls.Session) error {
|
||||
}
|
||||
|
||||
var env protocol.Envelope
|
||||
if err := dec.Decode(&env); err != nil {
|
||||
if err := codec.Decode(sess, &env); err != nil {
|
||||
if err == io.EOF {
|
||||
log.Info("dtls session closed by server", nil)
|
||||
return nil
|
||||
@@ -135,7 +133,7 @@ func (p *ClientProxy) StartLoop(ctx context.Context, sess dtls.Session) error {
|
||||
HTTPResponse: &resp,
|
||||
}
|
||||
|
||||
if err := enc.Encode(&respEnv); err != nil {
|
||||
if err := codec.Encode(sess, &respEnv); err != nil {
|
||||
logReq.Error("failed to encode http response envelope", logging.Fields{
|
||||
"error": err.Error(),
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user