diff --git a/cmd/cgat/main.go b/cmd/cgat/main.go index 8c6df416433e6ebf3744935080fd350e26898037..20108d1978150527696a92dbf065d2c383eaea22 100644 --- a/cmd/cgat/main.go +++ b/cmd/cgat/main.go @@ -8,17 +8,16 @@ import ( "pggat2/lib/bouncer/backends/v0" "pggat2/lib/bouncer/bouncers/v0" "pggat2/lib/bouncer/frontends/v0" - "pggat2/lib/middleware/middlewares/eqp" "pggat2/lib/middleware/middlewares/unread" "pggat2/lib/middleware/middlewares/unterminate" - "pggat2/lib/pnet" - "pggat2/lib/pnet/pio" "pggat2/lib/rob" "pggat2/lib/rob/schedulers/v2" + "pggat2/lib/zap" + "pggat2/lib/zap/zio" ) type job struct { - client pnet.ReadWriter + client zap.ReadWriter done chan<- struct{} } @@ -27,13 +26,12 @@ func testServer(r rob.Scheduler) { if err != nil { panic(err) } - server := pio.MakeReadWriter(conn) + server := zio.MakeReadWriter(conn) backends.Accept(&server) - consumer := eqp.MakeConsumer(&server) sink := r.NewSink(0) for { j := sink.Read().(job) - bouncers.Bounce(j.client, &consumer) + bouncers.Bounce(j.client, &server) select { case j.done <- struct{}{}: default: @@ -60,14 +58,13 @@ func main() { } go func() { source := r.NewSource() - client := pio.MakeReadWriter(conn) + client := zio.MakeReadWriter(conn) ut := unterminate.MakeUnterminate(&client) frontends.Accept(ut) - creator := eqp.MakeCreator(ut) done := make(chan struct{}) defer close(done) for { - u, err := unread.NewUnread(&creator) + u, err := unread.NewUnread(&ut) if err != nil { break } diff --git a/lib/bouncer/backends/v0/accept.go b/lib/bouncer/backends/v0/accept.go index a1d5d0a6f043170023c07b17f20e25309d439828..65d6ede76b27c6666324a3c1bf3ee514973af5bb 100644 --- a/lib/bouncer/backends/v0/accept.go +++ b/lib/bouncer/backends/v0/accept.go @@ -6,9 +6,8 @@ import ( "pggat2/lib/auth/md5" "pggat2/lib/auth/sasl" "pggat2/lib/perror" - "pggat2/lib/pnet" - "pggat2/lib/pnet/packet" - packets "pggat2/lib/pnet/packet/packets/v3.0" + "pggat2/lib/zap" + packets "pggat2/lib/zap/packets/v3.0" ) type Status int @@ -23,22 +22,22 @@ var ( ErrBadPacket = errors.New("bad packet") ) -func fail(server pnet.ReadWriter, err error) { +func fail(server zap.ReadWriter, err error) { panic(err) } -func failpg(server pnet.ReadWriter, err perror.Error) { +func failpg(server zap.ReadWriter, err perror.Error) { panic(err) } -func authenticationSASLChallenge(server pnet.ReadWriter, mechanism sasl.Client) (done bool, status Status) { +func authenticationSASLChallenge(server zap.ReadWriter, mechanism sasl.Client) (done bool, status Status) { in, err := server.Read() if err != nil { fail(server, err) return false, Fail } - if in.Type() != packet.Authentication { + if in.Type() != packets.Authentication { fail(server, ErrProtocolError) return false, Fail } @@ -61,7 +60,7 @@ func authenticationSASLChallenge(server pnet.ReadWriter, mechanism sasl.Client) out := server.Write() packets.WriteAuthenticationResponse(out, response) - err = server.Send(out.Finish()) + err = server.Send(out) if err != nil { fail(server, err) return false, Fail @@ -82,7 +81,7 @@ func authenticationSASLChallenge(server pnet.ReadWriter, mechanism sasl.Client) } } -func authenticationSASL(server pnet.ReadWriter, mechanisms []string, username, password string) Status { +func authenticationSASL(server zap.ReadWriter, mechanisms []string, username, password string) Status { mechanism, err := sasl.NewClient(mechanisms, username, password) if err != nil { fail(server, err) @@ -92,7 +91,7 @@ func authenticationSASL(server pnet.ReadWriter, mechanisms []string, username, p out := server.Write() packets.WriteSASLInitialResponse(out, mechanism.Name(), initialResponse) - err = server.Send(out.Finish()) + err = server.Send(out) if err != nil { fail(server, err) return Fail @@ -112,10 +111,10 @@ func authenticationSASL(server pnet.ReadWriter, mechanisms []string, username, p return Ok } -func authenticationMD5(server pnet.ReadWriter, salt [4]byte, username, password string) Status { +func authenticationMD5(server zap.ReadWriter, salt [4]byte, username, password string) Status { out := server.Write() packets.WritePasswordMessage(out, md5.Encode(username, password, salt)) - err := server.Send(out.Finish()) + err := server.Send(out) if err != nil { fail(server, err) return Fail @@ -123,10 +122,10 @@ func authenticationMD5(server pnet.ReadWriter, salt [4]byte, username, password return Ok } -func authenticationCleartext(server pnet.ReadWriter, password string) Status { +func authenticationCleartext(server zap.ReadWriter, password string) Status { out := server.Write() packets.WritePasswordMessage(out, password) - err := server.Send(out.Finish()) + err := server.Send(out) if err != nil { fail(server, err) return Fail @@ -134,7 +133,7 @@ func authenticationCleartext(server pnet.ReadWriter, password string) Status { return Ok } -func startup0(server pnet.ReadWriter, username, password string) (done bool, status Status) { +func startup0(server zap.ReadWriter, username, password string) (done bool, status Status) { in, err := server.Read() if err != nil { fail(server, err) @@ -142,7 +141,7 @@ func startup0(server pnet.ReadWriter, username, password string) (done bool, sta } switch in.Type() { - case packet.ErrorResponse: + case packets.ErrorResponse: perr, ok := packets.ReadErrorResponse(in) if !ok { fail(server, ErrBadPacket) @@ -150,7 +149,7 @@ func startup0(server pnet.ReadWriter, username, password string) (done bool, sta } failpg(server, perr) return false, Fail - case packet.Authentication: + case packets.Authentication: method, ok := in.Int32() if !ok { fail(server, ErrBadPacket) @@ -195,7 +194,7 @@ func startup0(server pnet.ReadWriter, username, password string) (done bool, sta fail(server, errors.New("unknown authentication method")) return false, Fail } - case packet.NegotiateProtocolVersion: + case packets.NegotiateProtocolVersion: // we only support protocol 3.0 for now fail(server, errors.New("server wanted to negotiate protocol version")) return false, Fail @@ -205,7 +204,7 @@ func startup0(server pnet.ReadWriter, username, password string) (done bool, sta } } -func startup1(server pnet.ReadWriter) (done bool, status Status) { +func startup1(server zap.ReadWriter) (done bool, status Status) { in, err := server.Read() if err != nil { fail(server, err) @@ -213,7 +212,7 @@ func startup1(server pnet.ReadWriter) (done bool, status Status) { } switch in.Type() { - case packet.BackendKeyData: + case packets.BackendKeyData: var cancellationKey [8]byte ok := in.Bytes(cancellationKey[:]) if !ok { @@ -222,11 +221,11 @@ func startup1(server pnet.ReadWriter) (done bool, status Status) { } // TODO(garet) put cancellation key somewhere return false, Ok - case packet.ParameterStatus: + case packets.ParameterStatus: return false, Ok - case packet.ReadyForQuery: + case packets.ReadyForQuery: return true, Ok - case packet.ErrorResponse: + case packets.ErrorResponse: perr, ok := packets.ReadErrorResponse(in) if !ok { fail(server, ErrBadPacket) @@ -234,7 +233,7 @@ func startup1(server pnet.ReadWriter) (done bool, status Status) { } failpg(server, perr) return false, Fail - case packet.NoticeResponse: + case packets.NoticeResponse: // TODO(garet) do something with notice return false, Ok default: @@ -243,7 +242,7 @@ func startup1(server pnet.ReadWriter) (done bool, status Status) { } } -func Accept(server pnet.ReadWriter) { +func Accept(server zap.ReadWriter) { // we can re-use the memory for this pkt most of the way down because we don't pass this anywhere out := server.Write() out.Int16(3) @@ -255,7 +254,7 @@ func Accept(server pnet.ReadWriter) { out.String("uniswap") out.String("") - err := server.Send(out.Finish()) + err := server.Send(out) if err != nil { fail(server, err) return diff --git a/lib/bouncer/bouncers/v0/bouncer.go b/lib/bouncer/bouncers/v0/bouncer.go index 250e90173863496ad7a13ccaf1b7e5ce3a3de875..5af359f57c676e631c2f37dd9427efe757fb65a3 100644 --- a/lib/bouncer/bouncers/v0/bouncer.go +++ b/lib/bouncer/bouncers/v0/bouncer.go @@ -6,9 +6,8 @@ import ( "runtime/debug" "pggat2/lib/perror" - "pggat2/lib/pnet" - "pggat2/lib/pnet/packet" - packets "pggat2/lib/pnet/packet/packets/v3.0" + "pggat2/lib/zap" + "pggat2/lib/zap/packets/v3.0" ) type Status int @@ -18,21 +17,21 @@ const ( Ok ) -func clientFail(client pnet.ReadWriter, err perror.Error) { +func clientFail(client zap.ReadWriter, err perror.Error) { // DEBUG(garet) log.Println("client fail", err) debug.PrintStack() out := client.Write() packets.WriteErrorResponse(out, err) - _ = client.Send(out.Finish()) + _ = client.Send(out) } -func serverFail(server pnet.ReadWriter, err error) { +func serverFail(server zap.ReadWriter, err error) { panic(err) } -func copyIn0(client, server pnet.ReadWriter) (done bool, status Status) { +func copyIn0(client, server zap.ReadWriter) (done bool, status Status) { in, err := client.Read() if err != nil { clientFail(client, perror.Wrap(err)) @@ -40,29 +39,29 @@ func copyIn0(client, server pnet.ReadWriter) (done bool, status Status) { } switch in.Type() { - case packet.CopyData: - err = pnet.ProxyPacket(server, in) + case packets.CopyData: + err = server.Send(zap.InToOut(in)) if err != nil { serverFail(server, err) return false, Fail } return true, Ok - case packet.CopyDone, packet.CopyFail: - err = pnet.ProxyPacket(server, in) + case packets.CopyDone, packets.CopyFail: + err = server.Send(zap.InToOut(in)) if err != nil { serverFail(server, err) return false, Fail } return true, Ok default: - clientFail(client, pnet.ErrProtocolError) + clientFail(client, packets.ErrUnexpectedPacket) return false, Fail } } -func copyIn(client, server pnet.ReadWriter, in packet.In) (status Status) { +func copyIn(client, server zap.ReadWriter, in zap.In) (status Status) { // send in (copyInResponse) to client - err := pnet.ProxyPacket(client, in) + err := client.Send(zap.InToOut(in)) if err != nil { clientFail(client, perror.Wrap(err)) return Fail @@ -82,7 +81,7 @@ func copyIn(client, server pnet.ReadWriter, in packet.In) (status Status) { return Ok } -func copyOut0(client, server pnet.ReadWriter) (done bool, status Status) { +func copyOut0(client, server zap.ReadWriter) (done bool, status Status) { in, err := server.Read() if err != nil { serverFail(server, err) @@ -90,15 +89,15 @@ func copyOut0(client, server pnet.ReadWriter) (done bool, status Status) { } switch in.Type() { - case packet.CopyData: - err = pnet.ProxyPacket(client, in) + case packets.CopyData: + err = client.Send(zap.InToOut(in)) if err != nil { clientFail(client, perror.Wrap(err)) return false, Fail } return false, Ok - case packet.CopyDone, packet.ErrorResponse: - err = pnet.ProxyPacket(client, in) + case packets.CopyDone, packets.ErrorResponse: + err = client.Send(zap.InToOut(in)) if err != nil { clientFail(client, perror.Wrap(err)) return false, Fail @@ -110,9 +109,9 @@ func copyOut0(client, server pnet.ReadWriter) (done bool, status Status) { } } -func copyOut(client, server pnet.ReadWriter, in packet.In) (status Status) { +func copyOut(client, server zap.ReadWriter, in zap.In) (status Status) { // send in (copyOutResponse) to client - err := pnet.ProxyPacket(client, in) + err := client.Send(zap.InToOut(in)) if err != nil { clientFail(client, perror.Wrap(err)) return Fail @@ -132,7 +131,7 @@ func copyOut(client, server pnet.ReadWriter, in packet.In) (status Status) { return Ok } -func query0(client, server pnet.ReadWriter) (done bool, status Status) { +func query0(client, server zap.ReadWriter) (done bool, status Status) { in, err := server.Read() if err != nil { serverFail(server, err) @@ -140,33 +139,33 @@ func query0(client, server pnet.ReadWriter) (done bool, status Status) { } switch in.Type() { - case packet.CommandComplete, - packet.RowDescription, - packet.DataRow, - packet.EmptyQueryResponse, - packet.ErrorResponse, - packet.NoticeResponse, - packet.ParameterStatus: - err = pnet.ProxyPacket(client, in) + case packets.CommandComplete, + packets.RowDescription, + packets.DataRow, + packets.EmptyQueryResponse, + packets.ErrorResponse, + packets.NoticeResponse, + packets.ParameterStatus: + err = client.Send(zap.InToOut(in)) if err != nil { clientFail(client, perror.Wrap(err)) return false, Fail } return false, Ok - case packet.CopyInResponse: + case packets.CopyInResponse: status = copyIn(client, server, in) if status != Ok { return false, status } return false, Ok - case packet.CopyOutResponse: + case packets.CopyOutResponse: status = copyOut(client, server, in) if status != Ok { return false, status } return false, Ok - case packet.ReadyForQuery: - err = pnet.ProxyPacket(client, in) + case packets.ReadyForQuery: + err = client.Send(zap.InToOut(in)) if err != nil { clientFail(client, perror.Wrap(err)) return false, Fail @@ -178,9 +177,9 @@ func query0(client, server pnet.ReadWriter) (done bool, status Status) { } } -func query(client, server pnet.ReadWriter, in packet.In) (status Status) { +func query(client, server zap.ReadWriter, in zap.In) (status Status) { // send in (initial query) to server - err := pnet.ProxyPacket(server, in) + err := server.Send(zap.InToOut(in)) if err != nil { serverFail(server, err) return Fail @@ -199,7 +198,7 @@ func query(client, server pnet.ReadWriter, in packet.In) (status Status) { return Ok } -func functionCall0(client, server pnet.ReadWriter) (done bool, status Status) { +func functionCall0(client, server zap.ReadWriter) (done bool, status Status) { in, err := server.Read() if err != nil { serverFail(server, err) @@ -207,15 +206,15 @@ func functionCall0(client, server pnet.ReadWriter) (done bool, status Status) { } switch in.Type() { - case packet.ErrorResponse, packet.FunctionCallResponse, packet.NoticeResponse: - err = pnet.ProxyPacket(client, in) + case packets.ErrorResponse, packets.FunctionCallResponse, packets.NoticeResponse: + err = client.Send(zap.InToOut(in)) if err != nil { clientFail(client, perror.Wrap(err)) return false, Fail } return false, Ok - case packet.ReadyForQuery: - err = pnet.ProxyPacket(client, in) + case packets.ReadyForQuery: + err = client.Send(zap.InToOut(in)) if err != nil { clientFail(client, perror.Wrap(err)) return false, Fail @@ -227,9 +226,9 @@ func functionCall0(client, server pnet.ReadWriter) (done bool, status Status) { } } -func functionCall(client, server pnet.ReadWriter, in packet.In) (status Status) { +func functionCall(client, server zap.ReadWriter, in zap.In) (status Status) { // send in (FunctionCall) to server - err := pnet.ProxyPacket(server, in) + err := server.Send(zap.InToOut(in)) if err != nil { serverFail(server, err) return Fail @@ -248,7 +247,7 @@ func functionCall(client, server pnet.ReadWriter, in packet.In) (status Status) return Ok } -func sync0(client, server pnet.ReadWriter) (done bool, status Status) { +func sync0(client, server zap.ReadWriter) (done bool, status Status) { in, err := server.Read() if err != nil { serverFail(server, err) @@ -256,27 +255,27 @@ func sync0(client, server pnet.ReadWriter) (done bool, status Status) { } switch in.Type() { - case packet.ParseComplete, - packet.BindComplete, - packet.ErrorResponse, - packet.RowDescription, - packet.NoData, - packet.ParameterDescription, + case packets.ParseComplete, + packets.BindComplete, + packets.ErrorResponse, + packets.RowDescription, + packets.NoData, + packets.ParameterDescription, - packet.CommandComplete, - packet.DataRow, - packet.EmptyQueryResponse, - packet.NoticeResponse, - packet.ParameterStatus, - packet.PortalSuspended: - err = pnet.ProxyPacket(client, in) + packets.CommandComplete, + packets.DataRow, + packets.EmptyQueryResponse, + packets.NoticeResponse, + packets.ParameterStatus, + packets.PortalSuspended: + err = client.Send(zap.InToOut(in)) if err != nil { clientFail(client, perror.Wrap(err)) return false, Fail } return false, Ok - case packet.ReadyForQuery: - err = pnet.ProxyPacket(client, in) + case packets.ReadyForQuery: + err = client.Send(zap.InToOut(in)) if err != nil { clientFail(client, perror.Wrap(err)) return false, Fail @@ -289,9 +288,9 @@ func sync0(client, server pnet.ReadWriter) (done bool, status Status) { } } -func sync(client, server pnet.ReadWriter, in packet.In) (status Status) { +func sync(client, server zap.ReadWriter, in zap.In) (status Status) { // send initial (sync) to server - err := pnet.ProxyPacket(server, in) + err := server.Send(zap.InToOut(in)) if err != nil { serverFail(server, err) return Fail @@ -311,13 +310,13 @@ func sync(client, server pnet.ReadWriter, in packet.In) (status Status) { return Ok } -func eqp(client, server pnet.ReadWriter, in packet.In) (status Status) { +func eqp(client, server zap.ReadWriter, in zap.In) (status Status) { for { switch in.Type() { - case packet.Sync: + case packets.Sync: return sync(client, server, in) - case packet.Parse, packet.Bind, packet.Describe, packet.Execute: - err := pnet.ProxyPacket(server, in) + case packets.Parse, packets.Bind, packets.Describe, packets.Execute: + err := server.Send(zap.InToOut(in)) if err != nil { serverFail(server, err) return Fail @@ -340,7 +339,7 @@ func eqp(client, server pnet.ReadWriter, in packet.In) (status Status) { } } -func Bounce(client, server pnet.ReadWriter) { +func Bounce(client, server zap.ReadWriter) { in, err := client.Read() if err != nil { clientFail(client, perror.Wrap(err)) @@ -348,11 +347,11 @@ func Bounce(client, server pnet.ReadWriter) { } switch in.Type() { - case packet.Query: + case packets.Query: query(client, server, in) - case packet.FunctionCall: + case packets.FunctionCall: functionCall(client, server, in) - case packet.Sync, packet.Parse, packet.Bind, packet.Describe, packet.Execute: + case packets.Sync, packets.Parse, packets.Bind, packets.Describe, packets.Execute: eqp(client, server, in) default: log.Printf("operation %c", in.Type()) diff --git a/lib/bouncer/frontends/v0/accept.go b/lib/bouncer/frontends/v0/accept.go index a160b66a7bd58bac9e5c9e06d85072a8b00b1ee6..fa4bee4f3ca808d779474830b9af89b2bdaadb74 100644 --- a/lib/bouncer/frontends/v0/accept.go +++ b/lib/bouncer/frontends/v0/accept.go @@ -8,8 +8,8 @@ import ( "pggat2/lib/auth/sasl" "pggat2/lib/perror" - "pggat2/lib/pnet" - "pggat2/lib/pnet/packet/packets/v3.0" + "pggat2/lib/zap" + "pggat2/lib/zap/packets/v3.0" ) type Status int @@ -19,17 +19,17 @@ const ( Ok ) -func fail(client pnet.ReadWriter, err perror.Error) { +func fail(client zap.ReadWriter, err perror.Error) { // DEBUG(garet) log.Println("client fail", err) debug.PrintStack() out := client.Write() packets.WriteErrorResponse(out, err) - _ = client.Send(out.Finish()) + _ = client.Send(out) } -func startup0(client pnet.ReadWriter) (done bool, status Status) { +func startup0(client zap.ReadWriter) (done bool, status Status) { in, err := client.ReadUntyped() if err != nil { fail(client, perror.Wrap(err)) @@ -38,12 +38,12 @@ func startup0(client pnet.ReadWriter) (done bool, status Status) { majorVersion, ok := in.Uint16() if !ok { - fail(client, pnet.ErrBadPacketFormat) + fail(client, packets.ErrBadFormat) return false, Fail } minorVersion, ok := in.Uint16() if !ok { - fail(client, pnet.ErrBadPacketFormat) + fail(client, packets.ErrBadFormat) return false, Fail } @@ -100,7 +100,7 @@ func startup0(client pnet.ReadWriter) (done bool, status Status) { for { key, ok := in.String() if !ok { - fail(client, pnet.ErrBadPacketFormat) + fail(client, packets.ErrBadFormat) return false, Fail } if key == "" { @@ -109,7 +109,7 @@ func startup0(client pnet.ReadWriter) (done bool, status Status) { value, ok := in.String() if !ok { - fail(client, pnet.ErrBadPacketFormat) + fail(client, packets.ErrBadFormat) return false, Fail } @@ -147,7 +147,7 @@ func startup0(client pnet.ReadWriter) (done bool, status Status) { out := client.Write() packets.WriteNegotiateProtocolVersion(out, 0, unsupportedOptions) - err = client.Send(out.Finish()) + err = client.Send(out) if err != nil { fail(client, perror.Wrap(err)) return false, Fail @@ -169,7 +169,7 @@ func startup0(client pnet.ReadWriter) (done bool, status Status) { return true, Ok } -func authenticationSASLInitial(client pnet.ReadWriter, username, password string) (server sasl.Server, resp []byte, done bool, status Status) { +func authenticationSASLInitial(client zap.ReadWriter, username, password string) (server sasl.Server, resp []byte, done bool, status Status) { // check which authentication method the client wants in, err := client.Read() if err != nil { @@ -178,7 +178,7 @@ func authenticationSASLInitial(client pnet.ReadWriter, username, password string } mechanism, initialResponse, ok := packets.ReadSASLInitialResponse(in) if !ok { - fail(client, pnet.ErrBadPacketFormat) + fail(client, packets.ErrBadFormat) return nil, nil, false, Fail } @@ -196,7 +196,7 @@ func authenticationSASLInitial(client pnet.ReadWriter, username, password string return tool, resp, done, Ok } -func authenticationSASLContinue(client pnet.ReadWriter, tool sasl.Server) (resp []byte, done bool, status Status) { +func authenticationSASLContinue(client zap.ReadWriter, tool sasl.Server) (resp []byte, done bool, status Status) { in, err := client.Read() if err != nil { fail(client, perror.Wrap(err)) @@ -204,7 +204,7 @@ func authenticationSASLContinue(client pnet.ReadWriter, tool sasl.Server) (resp } clientResp, ok := packets.ReadAuthenticationResponse(in) if !ok { - fail(client, pnet.ErrProtocolError) + fail(client, packets.ErrBadFormat) return nil, false, Fail } @@ -216,10 +216,10 @@ func authenticationSASLContinue(client pnet.ReadWriter, tool sasl.Server) (resp return resp, done, Ok } -func authenticationSASL(client pnet.ReadWriter, username, password string) Status { +func authenticationSASL(client zap.ReadWriter, username, password string) Status { out := client.Write() packets.WriteAuthenticationSASL(out, sasl.Mechanisms) - err := client.Send(out.Finish()) + err := client.Send(out) if err != nil { fail(client, perror.Wrap(err)) return Fail @@ -234,7 +234,7 @@ func authenticationSASL(client pnet.ReadWriter, username, password string) Statu if done { out = client.Write() packets.WriteAuthenticationSASLFinal(out, resp) - err = client.Send(out.Finish()) + err = client.Send(out) if err != nil { fail(client, perror.Wrap(err)) return Fail @@ -243,7 +243,7 @@ func authenticationSASL(client pnet.ReadWriter, username, password string) Statu } else { out = client.Write() packets.WriteAuthenticationSASLContinue(out, resp) - err = client.Send(out.Finish()) + err = client.Send(out) if err != nil { fail(client, perror.Wrap(err)) return Fail @@ -256,10 +256,10 @@ func authenticationSASL(client pnet.ReadWriter, username, password string) Statu return Ok } -func updateParameter(client pnet.ReadWriter, name, value string) Status { +func updateParameter(client zap.ReadWriter, name, value string) Status { out := client.Write() packets.WriteParameterStatus(out, name, value) - err := client.Send(out.Finish()) + err := client.Send(out) if err != nil { fail(client, perror.Wrap(err)) return Fail @@ -267,7 +267,7 @@ func updateParameter(client pnet.ReadWriter, name, value string) Status { return Ok } -func Accept(client pnet.ReadWriter) { +func Accept(client zap.ReadWriter) { for { done, status := startup0(client) if status != Ok { @@ -286,7 +286,7 @@ func Accept(client pnet.ReadWriter) { // send auth Ok out := client.Write() packets.WriteAuthenticationOk(out) - err := client.Send(out.Finish()) + err := client.Send(out) if err != nil { fail(client, perror.Wrap(err)) return @@ -354,7 +354,7 @@ func Accept(client pnet.ReadWriter) { } out = client.Write() packets.WriteBackendKeyData(out, cancellationKey) - err = client.Send(out.Finish()) + err = client.Send(out) if err != nil { fail(client, perror.Wrap(err)) return @@ -363,7 +363,7 @@ func Accept(client pnet.ReadWriter) { // send ready for query out = client.Write() packets.WriteReadyForQuery(out, 'I') - err = client.Send(out.Finish()) + err = client.Send(out) if err != nil { fail(client, perror.Wrap(err)) return diff --git a/lib/middleware/middlewares/eqp/consumer.go b/lib/middleware/middlewares/eqp/consumer.go deleted file mode 100644 index bd364d3f6ff27a300e8e8f3828a2c48b3af22a3a..0000000000000000000000000000000000000000 --- a/lib/middleware/middlewares/eqp/consumer.go +++ /dev/null @@ -1,125 +0,0 @@ -package eqp - -import ( - "pggat2/lib/pnet" - "pggat2/lib/pnet/packet" - packets "pggat2/lib/pnet/packet/packets/v3.0" - "pggat2/lib/util/decorator" - "pggat2/lib/util/ring" -) - -type Consumer struct { - noCopy decorator.NoCopy - - preparedStatements map[string]PreparedStatement - portals map[string]Portal - pendingPreparedStatements ring.Ring[string] - pendingPortals ring.Ring[string] - inner pnet.ReadWriter -} - -func MakeConsumer(inner pnet.ReadWriter) Consumer { - return Consumer{ - preparedStatements: make(map[string]PreparedStatement), - portals: make(map[string]Portal), - inner: inner, - } -} - -func NewConsumer(inner pnet.ReadWriter) *Consumer { - c := MakeConsumer(inner) - return &c -} - -func (T *Consumer) Read() (packet.In, error) { - in, err := T.inner.Read() - if err != nil { - return packet.In{}, err - } - switch in.Type() { - case packet.ParseComplete: - T.pendingPreparedStatements.PopFront() - case packet.BindComplete: - T.pendingPortals.PopFront() - case packet.ReadyForQuery: - // remove all pending, they were not added. - for pending, ok := T.pendingPreparedStatements.PopFront(); ok; pending, ok = T.pendingPreparedStatements.PopFront() { - delete(T.preparedStatements, pending) - } - for pending, ok := T.pendingPortals.PopFront(); ok; pending, ok = T.pendingPortals.PopFront() { - delete(T.portals, pending) - } - } - return in, nil -} - -func (T *Consumer) ReadUntyped() (packet.In, error) { - return T.inner.ReadUntyped() -} - -func (T *Consumer) Write() packet.Out { - return T.inner.Write() -} - -func (T *Consumer) WriteByte(b byte) error { - return T.inner.WriteByte(b) -} - -func (T *Consumer) Send(typ packet.Type, bytes []byte) error { - buf := packet.MakeInBuf(typ, bytes) - in := packet.MakeIn(&buf) - switch typ { - case packet.Query: - // clobber unnamed portal and unnamed prepared statement - delete(T.preparedStatements, "") - delete(T.portals, "") - case packet.Parse: - destination, query, parameterDataTypes, ok := packets.ReadParse(in) - if !ok { - return ErrBadPacketFormat - } - if destination != "" { - if _, ok = T.preparedStatements[destination]; ok { - return ErrPreparedStatementExists - } - } - T.preparedStatements[destination] = PreparedStatement{ - Query: query, - ParameterDataTypes: parameterDataTypes, - } - T.pendingPreparedStatements.PushBack(destination) - case packet.Bind: - destination, source, parameterFormatCodes, parameterValues, resultFormatCodes, ok := packets.ReadBind(in) - if !ok { - return ErrBadPacketFormat - } - if destination != "" { - if _, ok = T.portals[destination]; ok { - return ErrPortalExists - } - } - T.portals[destination] = Portal{ - Source: source, - ParameterFormatCodes: parameterFormatCodes, - ParameterValues: parameterValues, - ResultFormatCodes: resultFormatCodes, - } - T.pendingPortals.PushBack(destination) - case packet.Close: - which, target, ok := packets.ReadClose(in) - if !ok { - return ErrBadPacketFormat - } - switch which { - case 'S': - delete(T.preparedStatements, target) - case 'P': - delete(T.portals, target) - default: - return ErrUnknownCloseTarget - } - } - return T.inner.Send(typ, bytes) -} - -var _ pnet.ReadWriter = (*Consumer)(nil) diff --git a/lib/middleware/middlewares/eqp/creator.go b/lib/middleware/middlewares/eqp/creator.go deleted file mode 100644 index 6c1baa692685e1a9420e518fefcd03cc0866a9e1..0000000000000000000000000000000000000000 --- a/lib/middleware/middlewares/eqp/creator.go +++ /dev/null @@ -1,143 +0,0 @@ -package eqp - -import ( - "pggat2/lib/pnet" - "pggat2/lib/pnet/packet" - packets "pggat2/lib/pnet/packet/packets/v3.0" - "pggat2/lib/util/decorator" - "pggat2/lib/util/ring" -) - -type Creator struct { - noCopy decorator.NoCopy - - preparedStatements map[string]PreparedStatement - portals map[string]Portal - pendingPreparedStatements ring.Ring[string] - pendingPortals ring.Ring[string] - inner pnet.ReadWriter -} - -func MakeCreator(inner pnet.ReadWriter) Creator { - return Creator{ - preparedStatements: make(map[string]PreparedStatement), - portals: make(map[string]Portal), - inner: inner, - } -} - -func NewCreator(inner pnet.ReadWriter) *Creator { - c := MakeCreator(inner) - return &c -} - -func (T *Creator) Read() (packet.In, error) { - for { - in, err := T.inner.Read() - if err != nil { - return packet.In{}, err - } - switch in.Type() { - case packet.Query: - // clobber unnamed portal and unnamed prepared statement - delete(T.preparedStatements, "") - delete(T.portals, "") - return in, nil - case packet.Parse: - destination, query, parameterDataTypes, ok := packets.ReadParse(in) - if !ok { - return packet.In{}, ErrBadPacketFormat - } - if destination != "" { - if _, ok = T.preparedStatements[destination]; ok { - return packet.In{}, ErrPreparedStatementExists - } - } - T.preparedStatements[destination] = PreparedStatement{ - Query: query, - ParameterDataTypes: parameterDataTypes, - } - T.pendingPreparedStatements.PushBack(destination) - - // send parse complete - out := T.inner.Write() - out.Type(packet.ParseComplete) - err = T.inner.Send(out.Finish()) - if err != nil { - return packet.In{}, err - } - case packet.Bind: - destination, source, parameterFormatCodes, parameterValues, resultFormatCodes, ok := packets.ReadBind(in) - if !ok { - return packet.In{}, ErrBadPacketFormat - } - if destination != "" { - if _, ok = T.portals[destination]; ok { - return packet.In{}, ErrPortalExists - } - } - T.portals[destination] = Portal{ - Source: source, - ParameterFormatCodes: parameterFormatCodes, - ParameterValues: parameterValues, - ResultFormatCodes: resultFormatCodes, - } - T.pendingPortals.PushBack(destination) - - // send bind complete - out := T.inner.Write() - out.Type(packet.BindComplete) - err = T.inner.Send(out.Finish()) - if err != nil { - return packet.In{}, err - } - case packet.Close: - which, target, ok := packets.ReadClose(in) - if !ok { - return packet.In{}, ErrBadPacketFormat - } - switch which { - case 'S': - delete(T.preparedStatements, target) - case 'P': - delete(T.portals, target) - default: - return packet.In{}, ErrBadPacketFormat - } - default: - return in, nil - } - } -} - -func (T *Creator) ReadUntyped() (packet.In, error) { - return T.inner.ReadUntyped() -} - -func (T *Creator) Write() packet.Out { - return T.inner.Write() -} - -func (T *Creator) WriteByte(b byte) error { - return T.inner.WriteByte(b) -} - -func (T *Creator) Send(typ packet.Type, payload []byte) error { - switch typ { - case packet.ParseComplete: - T.pendingPreparedStatements.PopFront() - case packet.BindComplete: - T.pendingPortals.PopFront() - case packet.ReadyForQuery: - // remove all pending, they were not added. - for pending, ok := T.pendingPreparedStatements.PopFront(); ok; pending, ok = T.pendingPreparedStatements.PopFront() { - delete(T.preparedStatements, pending) - } - for pending, ok := T.pendingPortals.PopFront(); ok; pending, ok = T.pendingPortals.PopFront() { - delete(T.portals, pending) - } - } - return T.inner.Send(typ, payload) -} - -var _ pnet.ReadWriter = (*Creator)(nil) diff --git a/lib/middleware/middlewares/eqp/errors.go b/lib/middleware/middlewares/eqp/errors.go deleted file mode 100644 index d74b38814e9ab0e4f367d43859c812577035950a..0000000000000000000000000000000000000000 --- a/lib/middleware/middlewares/eqp/errors.go +++ /dev/null @@ -1,10 +0,0 @@ -package eqp - -import "errors" - -var ( - ErrBadPacketFormat = errors.New("bad packet format") - ErrPreparedStatementExists = errors.New("prepared statement already exists") - ErrPortalExists = errors.New("portal already exists") - ErrUnknownCloseTarget = errors.New("unknown close target") -) diff --git a/lib/middleware/middlewares/eqp/portal.go b/lib/middleware/middlewares/eqp/portal.go deleted file mode 100644 index 7ec58e4d2253cf47ef640977d3d40788420e57dc..0000000000000000000000000000000000000000 --- a/lib/middleware/middlewares/eqp/portal.go +++ /dev/null @@ -1,31 +0,0 @@ -package eqp - -import "pggat2/lib/util/slices" - -type Portal struct { - Source string - ParameterFormatCodes []int16 - ParameterValues [][]byte - ResultFormatCodes []int16 -} - -func (T Portal) Equals(rhs Portal) bool { - if T.Source != rhs.Source { - return false - } - if !slices.Equal(T.ParameterFormatCodes, rhs.ParameterFormatCodes) { - return false - } - if len(T.ParameterValues) != len(rhs.ParameterValues) { - return false - } - for i := range T.ParameterValues { - if !slices.Equal(T.ParameterValues[i], rhs.ParameterValues[i]) { - return false - } - } - if !slices.Equal(T.ResultFormatCodes, rhs.ResultFormatCodes) { - return false - } - return true -} diff --git a/lib/middleware/middlewares/eqp/preparedStatement.go b/lib/middleware/middlewares/eqp/preparedStatement.go deleted file mode 100644 index a710b61b8139ba7b6a7c54a6bc51760bcc3cd5f3..0000000000000000000000000000000000000000 --- a/lib/middleware/middlewares/eqp/preparedStatement.go +++ /dev/null @@ -1,18 +0,0 @@ -package eqp - -import "pggat2/lib/util/slices" - -type PreparedStatement struct { - Query string - ParameterDataTypes []int32 -} - -func (T PreparedStatement) Equals(rhs PreparedStatement) bool { - if T.Query != rhs.Query { - return false - } - if !slices.Equal(T.ParameterDataTypes, rhs.ParameterDataTypes) { - return false - } - return true -} diff --git a/lib/middleware/middlewares/eqp/stealer.go b/lib/middleware/middlewares/eqp/stealer.go deleted file mode 100644 index 3d59d7829825bedc2a2d0b23b9f6035ce46a78ea..0000000000000000000000000000000000000000 --- a/lib/middleware/middlewares/eqp/stealer.go +++ /dev/null @@ -1,171 +0,0 @@ -package eqp - -import ( - "errors" - - "pggat2/lib/pnet" - "pggat2/lib/pnet/packet" - packets "pggat2/lib/pnet/packet/packets/v3.0" -) - -// Stealer wraps a Consumer and duplicates the underlying Consumer's portals and prepared statements on use. -type Stealer struct { - creator *Creator - consumer *Consumer - - // need a second buf because we cannot use the underlying Consumer's buf (or it would overwrite the outgoing packet) - buf packet.OutBuf -} - -func NewStealer(consumer *Consumer, creator *Creator) *Stealer { - return &Stealer{ - creator: creator, - consumer: consumer, - } -} - -func (T *Stealer) Read() (packet.In, error) { - for { - in, err := T.consumer.Read() - if err != nil { - return packet.In{}, err - } - switch in.Type() { - case packet.ParseComplete: - // previous parse was successful - case packet.BindComplete: - // previous bind was successful - default: - // forward - return in, nil - } - } -} - -func (T *Stealer) ReadUntyped() (packet.In, error) { - return T.consumer.ReadUntyped() -} - -func (T *Stealer) Write() packet.Out { - return T.consumer.Write() -} - -func (T *Stealer) WriteByte(b byte) error { - return T.consumer.WriteByte(b) -} - -func (T *Stealer) bindPreparedStatement(target string, preparedStatement PreparedStatement) error { - T.buf.Reset() - out := packet.MakeOut(&T.buf) - packets.WriteParse(out, target, preparedStatement.Query, preparedStatement.ParameterDataTypes) - return T.consumer.Send(out.Finish()) -} - -func (T *Stealer) bindPortal(target string, portal Portal) error { - T.buf.Reset() - out := packet.MakeOut(&T.buf) - packets.WriteBind(out, target, portal.Source, portal.ParameterFormatCodes, portal.ParameterValues, portal.ResultFormatCodes) - return T.consumer.Send(out.Finish()) -} - -func (T *Stealer) closePreparedStatement(target string) error { - if _, ok := T.consumer.preparedStatements[target]; !ok { - // doesn't exist - return nil - } - T.buf.Reset() - out := packet.MakeOut(&T.buf) - packets.WriteClose(out, 'S', target) - return T.consumer.Send(out.Finish()) -} - -func (T *Stealer) closePortal(target string) error { - if _, ok := T.consumer.portals[target]; !ok { - // doesn't exist - return nil - } - T.buf.Reset() - out := packet.MakeOut(&T.buf) - packets.WriteClose(out, 'P', target) - return T.consumer.Send(out.Finish()) -} - -func (T *Stealer) syncPreparedStatement(target string) error { - creatorStatement, ok := T.creator.preparedStatements[target] - if !ok { - return T.closePreparedStatement(target) - } - consumerStatement, prev := T.consumer.preparedStatements[target] - if creatorStatement.Equals(consumerStatement) { - return nil - } - // clean up prev - if prev { - err := T.closePreparedStatement(target) - if err != nil { - return err - } - } - // send prepared statement - return T.bindPreparedStatement(target, creatorStatement) -} - -func (T *Stealer) syncPortal(target string) error { - creatorPortal, ok := T.creator.portals[target] - if !ok { - return T.closePortal(target) - } - consumerPortal, prev := T.consumer.portals[target] - if creatorPortal.Equals(consumerPortal) { - return nil - } - // clean up prev - if prev { - err := T.closePortal(target) - if err != nil { - return err - } - } - // send portal - return T.bindPortal(target, creatorPortal) -} - -func (T *Stealer) Send(typ packet.Type, bytes []byte) error { - // check if we are using a prepared statement or portal that we need to steal - buf := packet.MakeInBuf(typ, bytes) - in := packet.MakeIn(&buf) - switch typ { - case packet.Describe: - which, target, ok := packets.ReadDescribe(in) - if !ok { - return errors.New("bad packet format") - } - switch which { - case 'S': - err := T.syncPreparedStatement(target) - if err != nil { - return err - } - case 'P': - err := T.syncPortal(target) - if err != nil { - return err - } - default: - return errors.New("unknown describe target") - } - case packet.Execute: - target, _, ok := packets.ReadExecute(in) - if !ok { - return errors.New("bad packet format") - } - err := T.syncPortal(target) - if err != nil { - return err - } - } - - return T.consumer.Send(typ, bytes) -} - -var _ pnet.ReadWriter = (*Stealer)(nil) diff --git a/lib/middleware/middlewares/unread/unread.go b/lib/middleware/middlewares/unread/unread.go index 4b41bb2f82074b8c0fb753f2dbab7c8322031d09..c5a860215c675e2607fe530c25c06c8d1316db7f 100644 --- a/lib/middleware/middlewares/unread/unread.go +++ b/lib/middleware/middlewares/unread/unread.go @@ -1,17 +1,16 @@ package unread import ( - "pggat2/lib/pnet" - "pggat2/lib/pnet/packet" + "pggat2/lib/zap" ) type Unread struct { - in packet.In + in zap.In read bool - pnet.ReadWriter + zap.ReadWriter } -func NewUnread(inner pnet.ReadWriter) (*Unread, error) { +func NewUnread(inner zap.ReadWriter) (*Unread, error) { in, err := inner.Read() if err != nil { return nil, err @@ -22,7 +21,7 @@ func NewUnread(inner pnet.ReadWriter) (*Unread, error) { }, nil } -func NewUnreadUntyped(inner pnet.ReadWriter) (*Unread, error) { +func NewUnreadUntyped(inner zap.ReadWriter) (*Unread, error) { in, err := inner.ReadUntyped() if err != nil { return nil, err @@ -33,7 +32,7 @@ func NewUnreadUntyped(inner pnet.ReadWriter) (*Unread, error) { }, nil } -func (T *Unread) Read() (packet.In, error) { +func (T *Unread) Read() (zap.In, error) { if !T.read { T.read = true return T.in, nil @@ -41,7 +40,7 @@ func (T *Unread) Read() (packet.In, error) { return T.ReadWriter.Read() } -func (T *Unread) ReadUntyped() (packet.In, error) { +func (T *Unread) ReadUntyped() (zap.In, error) { if !T.read { T.read = true return T.in, nil @@ -49,4 +48,4 @@ func (T *Unread) ReadUntyped() (packet.In, error) { return T.ReadWriter.ReadUntyped() } -var _ pnet.ReadWriter = (*Unread)(nil) +var _ zap.ReadWriter = (*Unread)(nil) diff --git a/lib/middleware/middlewares/unterminate/unterminate.go b/lib/middleware/middlewares/unterminate/unterminate.go index b08aa27468fae8019ca68a5d5c3376c3aa168f1e..5d818b4ac1abce233a53cf98966e0dd1f3bbe4dc 100644 --- a/lib/middleware/middlewares/unterminate/unterminate.go +++ b/lib/middleware/middlewares/unterminate/unterminate.go @@ -3,29 +3,29 @@ package unterminate import ( "io" - "pggat2/lib/pnet" - "pggat2/lib/pnet/packet" + "pggat2/lib/zap" + packets "pggat2/lib/zap/packets/v3.0" ) type Unterminate struct { - pnet.ReadWriter + zap.ReadWriter } -func MakeUnterminate(inner pnet.ReadWriter) Unterminate { +func MakeUnterminate(inner zap.ReadWriter) Unterminate { return Unterminate{ ReadWriter: inner, } } -func (T Unterminate) Read() (packet.In, error) { +func (T Unterminate) Read() (zap.In, error) { in, err := T.ReadWriter.Read() if err != nil { - return packet.In{}, err + return zap.In{}, err } - if in.Type() == packet.Terminate { - return packet.In{}, io.EOF + if in.Type() == packets.Terminate { + return zap.In{}, io.EOF } return in, nil } -var _ pnet.ReadWriter = Unterminate{} +var _ zap.ReadWriter = Unterminate{} diff --git a/lib/pnet/errors.go b/lib/pnet/errors.go deleted file mode 100644 index d094bd7ffaf36afa9648908e0f7203184e6fa12b..0000000000000000000000000000000000000000 --- a/lib/pnet/errors.go +++ /dev/null @@ -1,15 +0,0 @@ -package pnet - -import "pggat2/lib/perror" - -var ErrBadPacketFormat = perror.New( - perror.FATAL, - perror.ProtocolViolation, - "Bad packet format", -) - -var ErrProtocolError = perror.New( - perror.FATAL, - perror.ProtocolViolation, - "Unexpected packet", -) diff --git a/lib/pnet/intercepted.go b/lib/pnet/intercepted.go deleted file mode 100644 index 2e3ebc04b971eb4fc168c553e6db555adbcc54c6..0000000000000000000000000000000000000000 --- a/lib/pnet/intercepted.go +++ /dev/null @@ -1,72 +0,0 @@ -package pnet - -import ( - "pggat2/lib/middleware" - "pggat2/lib/pnet/packet" -) - -type Intercepted struct { - ReadWriter - Middlewares []middleware.Middleware -} - -func (T Intercepted) interceptRead(in packet.In) (forward bool, err error) { - for _, mw := range T.Middlewares { - forward, err = mw.Read(in) - if err != nil || !forward { - return - } - } - return true, nil -} - -func (T Intercepted) Read() (packet.In, error) { - for { - in, err := T.ReadWriter.Read() - if err != nil { - return packet.In{}, err - } - var forward bool - forward, err = T.interceptRead(in) - if err != nil { - return packet.In{}, err - } - if forward { - return in, nil - } - } -} - -func (T Intercepted) ReadUntyped() (packet.In, error) { - for { - in, err := T.ReadWriter.ReadUntyped() - if err != nil { - return packet.In{}, err - } - var forward bool - forward, err = T.interceptRead(in) - if err != nil { - return packet.In{}, err - } - if forward { - return in, nil - } - } -} - -func (T Intercepted) Send(typ packet.Type, payload []byte) error { - inBuf := packet.MakeInBuf(typ, payload) - in := packet.MakeIn(&inBuf) - for _, mw := range T.Middlewares { - forward, err := mw.Write(in) - if err != nil { - return err - } - if !forward { - return nil - } - } - return T.ReadWriter.Send(typ, payload) -} - -var _ ReadWriter = Intercepted{} diff --git a/lib/pnet/packet/in.go b/lib/pnet/packet/in.go deleted file mode 100644 index 5c96fe56786eb21655445150b8052bc8c435fdc3..0000000000000000000000000000000000000000 --- a/lib/pnet/packet/in.go +++ /dev/null @@ -1,182 +0,0 @@ -package packet - -import ( - "encoding/binary" - "math" - - "pggat2/lib/util/decorator" -) - -type InBuf struct { - noCopy decorator.NoCopy - typ Type - buf []byte - pos int - rev int -} - -func MakeInBuf(typ Type, buf []byte) InBuf { - return InBuf{ - typ: typ, - buf: buf, - } -} - -func (T *InBuf) Reset( - typ Type, - buf []byte, -) { - T.typ = typ - T.buf = buf - T.pos = 0 - T.rev++ -} - -type In struct { - buf *InBuf - rev int -} - -func MakeIn( - buf *InBuf, -) In { - return In{ - buf: buf, - rev: buf.rev, - } -} - -func (T In) done() bool { - return T.rev != T.buf.rev -} - -func (T In) Type() Type { - if T.done() { - panic("Read after Done") - } - return T.buf.typ -} - -// Full returns the full payload of the packet. -// NOTE: Full will be invalid after Done is called -func (T In) Full() []byte { - if T.done() { - panic("Read after Done") - } - return T.buf.buf -} - -// Remaining returns the remaining payload of the packet. -// NOTE: Remaining will be invalid after Done is called -func (T In) Remaining() []byte { - full := T.Full() - return full[T.buf.pos:] -} - -func (T In) Reset() { - if T.done() { - panic("Read after Done") - } - T.buf.pos = 0 -} - -func (T In) Int8() (int8, bool) { - v, ok := T.Uint8() - return int8(v), ok -} - -func (T In) Int16() (int16, bool) { - v, ok := T.Uint16() - return int16(v), ok -} - -func (T In) Int32() (int32, bool) { - v, ok := T.Uint32() - return int32(v), ok -} - -func (T In) Int64() (int64, bool) { - v, ok := T.Uint64() - return int64(v), ok -} - -func (T In) Uint8() (uint8, bool) { - rem := T.Remaining() - if len(rem) < 1 { - return 0, false - } - v := rem[0] - T.buf.pos += 1 - return v, true -} - -func (T In) Uint16() (uint16, bool) { - rem := T.Remaining() - if len(rem) < 2 { - return 0, false - } - v := binary.BigEndian.Uint16(rem) - T.buf.pos += 2 - return v, true -} - -func (T In) Uint32() (uint32, bool) { - rem := T.Remaining() - if len(rem) < 4 { - return 0, false - } - v := binary.BigEndian.Uint32(rem) - T.buf.pos += 4 - return v, true -} - -func (T In) Uint64() (uint64, bool) { - rem := T.Remaining() - if len(rem) < 8 { - return 0, false - } - v := binary.BigEndian.Uint64(rem) - T.buf.pos += 8 - return v, true -} - -func (T In) Float32() (float32, bool) { - v, ok := T.Uint32() - return math.Float32frombits(v), ok -} - -func (T In) Float64() (float64, bool) { - v, ok := T.Uint64() - return math.Float64frombits(v), ok -} - -func (T In) String() (string, bool) { - rem := T.Remaining() - for i, c := range rem { - if c == 0 { - v := string(rem[:i]) - T.buf.pos += i + 1 - return v, true - } - } - return "", false -} - -func (T In) Bytes(b []byte) bool { - rem := T.Remaining() - if len(b) > len(rem) { - return false - } - copy(b, rem) - T.buf.pos += len(b) - return true -} - -// UnsafeBytes returns a byte slice without copying. Use this only if you plan to be done with the slice when the In is reset or the data will be replaced with garbage. -func (T In) UnsafeBytes(count int) ([]byte, bool) { - rem := T.Remaining() - if count > len(rem) { - return nil, false - } - return rem[:count], true -} diff --git a/lib/pnet/packet/out.go b/lib/pnet/packet/out.go deleted file mode 100644 index a030b71f6950c5b22676231f772137cf5107c147..0000000000000000000000000000000000000000 --- a/lib/pnet/packet/out.go +++ /dev/null @@ -1,133 +0,0 @@ -package packet - -import ( - "encoding/binary" - "math" - - "pggat2/lib/util/decorator" -) - -type OutBuf struct { - noCopy decorator.NoCopy - typ Type - buf []byte - rev int -} - -func MakeOutBuf(buf []byte) OutBuf { - return OutBuf{ - buf: buf, - } -} - -func (T *OutBuf) Reset() { - T.typ = None - T.buf = T.buf[:0] - T.rev++ -} - -type Out struct { - buf *OutBuf - rev int -} - -func MakeOut( - buf *OutBuf, -) Out { - return Out{ - buf: buf, - rev: buf.rev, - } -} - -func (T Out) done() bool { - return T.rev != T.buf.rev -} - -func (T Out) Finish() (Type, []byte) { - if T.done() { - panic("Write after Send") - } - return T.buf.typ, T.buf.buf -} - -func (T Out) Type(typ Type) { - if T.done() { - panic("Write after Send") - } - T.buf.typ = typ -} - -func (T Out) Reset() { - if T.done() { - panic("Write after Send") - } - T.buf.buf = T.buf.buf[:0] -} - -func (T Out) Int8(v int8) { - T.Uint8(uint8(v)) -} - -func (T Out) Int16(v int16) { - T.Uint16(uint16(v)) -} - -func (T Out) Int32(v int32) { - T.Uint32(uint32(v)) -} - -func (T Out) Int64(v int64) { - T.Uint64(uint64(v)) -} - -func (T Out) Uint8(v uint8) { - if T.done() { - panic("Write after Send") - } - T.buf.buf = append(T.buf.buf, v) -} - -func (T Out) Uint16(v uint16) { - if T.done() { - panic("Write after Send") - } - T.buf.buf = binary.BigEndian.AppendUint16(T.buf.buf, v) -} - -func (T Out) Uint32(v uint32) { - if T.done() { - panic("Write after Send") - } - T.buf.buf = binary.BigEndian.AppendUint32(T.buf.buf, v) -} - -func (T Out) Uint64(v uint64) { - if T.done() { - panic("Write after Send") - } - T.buf.buf = binary.BigEndian.AppendUint64(T.buf.buf, v) -} - -func (T Out) Float32(v float32) { - T.Uint32(math.Float32bits(v)) -} - -func (T Out) Float64(v float64) { - T.Uint64(math.Float64bits(v)) -} - -func (T Out) String(v string) { - if T.done() { - panic("Write after Send") - } - T.buf.buf = append(T.buf.buf, v...) - T.Uint8(0) -} - -func (T Out) Bytes(v []byte) { - if T.done() { - panic("Write after Send") - } - T.buf.buf = append(T.buf.buf, v...) -} diff --git a/lib/pnet/packet/packets/v3.0/authenticationcleartext.go b/lib/pnet/packet/packets/v3.0/authenticationcleartext.go deleted file mode 100644 index 2464c5c60872f0309be025fb34e117de1f685c87..0000000000000000000000000000000000000000 --- a/lib/pnet/packet/packets/v3.0/authenticationcleartext.go +++ /dev/null @@ -1,24 +0,0 @@ -package packets - -import "pggat2/lib/pnet/packet" - -func ReadAuthenticationCleartext(in packet.In) bool { - in.Reset() - if in.Type() != packet.Authentication { - return false - } - method, ok := in.Int32() - if !ok { - return false - } - if method != 3 { - return false - } - return true -} - -func WriteAuthenticationCleartext(out packet.Out) { - out.Reset() - out.Type(packet.Authentication) - out.Int32(3) -} diff --git a/lib/pnet/packet/packets/v3.0/authenticationok.go b/lib/pnet/packet/packets/v3.0/authenticationok.go deleted file mode 100644 index 26d6f8261c6196310a855c544fdb1fbe71d216fd..0000000000000000000000000000000000000000 --- a/lib/pnet/packet/packets/v3.0/authenticationok.go +++ /dev/null @@ -1,24 +0,0 @@ -package packets - -import "pggat2/lib/pnet/packet" - -func ReadAuthenticationOk(in packet.In) bool { - in.Reset() - if in.Type() != packet.Authentication { - return false - } - method, ok := in.Int32() - if !ok { - return false - } - if method != 0 { - return false - } - return true -} - -func WriteAuthenticationOk(out packet.Out) { - out.Reset() - out.Type(packet.Authentication) - out.Int32(0) -} diff --git a/lib/pnet/packet/packets/v3.0/authenticationresponse.go b/lib/pnet/packet/packets/v3.0/authenticationresponse.go deleted file mode 100644 index 221cf19b7496ed8bf083a70e1f751e3dd14758a2..0000000000000000000000000000000000000000 --- a/lib/pnet/packet/packets/v3.0/authenticationresponse.go +++ /dev/null @@ -1,17 +0,0 @@ -package packets - -import "pggat2/lib/pnet/packet" - -func ReadAuthenticationResponse(in packet.In) ([]byte, bool) { - in.Reset() - if in.Type() != packet.AuthenticationResponse { - return nil, false - } - return in.Full(), true -} - -func WriteAuthenticationResponse(out packet.Out, resp []byte) { - out.Reset() - out.Type(packet.AuthenticationResponse) - out.Bytes(resp) -} diff --git a/lib/pnet/packet/packets/v3.0/authenticationsaslcontinue.go b/lib/pnet/packet/packets/v3.0/authenticationsaslcontinue.go deleted file mode 100644 index 69691e9c1a938188f5a0738ab1474eedd7201642..0000000000000000000000000000000000000000 --- a/lib/pnet/packet/packets/v3.0/authenticationsaslcontinue.go +++ /dev/null @@ -1,25 +0,0 @@ -package packets - -import "pggat2/lib/pnet/packet" - -func ReadAuthenticationSASLContinue(in packet.In) ([]byte, bool) { - in.Reset() - if in.Type() != packet.Authentication { - return nil, false - } - method, ok := in.Int32() - if !ok { - return nil, false - } - if method != 11 { - return nil, false - } - return in.Full(), true -} - -func WriteAuthenticationSASLContinue(out packet.Out, resp []byte) { - out.Reset() - out.Type(packet.Authentication) - out.Int32(11) - out.Bytes(resp) -} diff --git a/lib/pnet/packet/packets/v3.0/authenticationsaslfinal.go b/lib/pnet/packet/packets/v3.0/authenticationsaslfinal.go deleted file mode 100644 index 2a7d3594fe3e85dab9cd974090b48f71e47991f1..0000000000000000000000000000000000000000 --- a/lib/pnet/packet/packets/v3.0/authenticationsaslfinal.go +++ /dev/null @@ -1,25 +0,0 @@ -package packets - -import "pggat2/lib/pnet/packet" - -func ReadAuthenticationSASLFinal(in packet.In) ([]byte, bool) { - in.Reset() - if in.Type() != packet.Authentication { - return nil, false - } - method, ok := in.Int32() - if !ok { - return nil, false - } - if method != 12 { - return nil, false - } - return in.Full(), true -} - -func WriteAuthenticationSASLFinal(out packet.Out, resp []byte) { - out.Reset() - out.Type(packet.Authentication) - out.Int32(12) - out.Bytes(resp) -} diff --git a/lib/pnet/packet/packets/v3.0/close.go b/lib/pnet/packet/packets/v3.0/close.go deleted file mode 100644 index f20b0349db247fb6cdc6c5de0c2718d692c6465c..0000000000000000000000000000000000000000 --- a/lib/pnet/packet/packets/v3.0/close.go +++ /dev/null @@ -1,26 +0,0 @@ -package packets - -import "pggat2/lib/pnet/packet" - -func ReadClose(in packet.In) (which uint8, target string, ok bool) { - in.Reset() - if in.Type() != packet.Close { - return - } - which, ok = in.Uint8() - if !ok { - return - } - target, ok = in.String() - if !ok { - return - } - return -} - -func WriteClose(out packet.Out, which uint8, target string) { - out.Reset() - out.Type(packet.Close) - out.Uint8(which) - out.String(target) -} diff --git a/lib/pnet/packet/packets/v3.0/describe.go b/lib/pnet/packet/packets/v3.0/describe.go deleted file mode 100644 index 6d9623fdfb003f17bffa32553f928daead671d20..0000000000000000000000000000000000000000 --- a/lib/pnet/packet/packets/v3.0/describe.go +++ /dev/null @@ -1,26 +0,0 @@ -package packets - -import "pggat2/lib/pnet/packet" - -func ReadDescribe(in packet.In) (which uint8, target string, ok bool) { - in.Reset() - if in.Type() != packet.Describe { - return - } - which, ok = in.Uint8() - if !ok { - return - } - target, ok = in.String() - if !ok { - return - } - return -} - -func WriteDescribe(out packet.Out, which uint8, target string) { - out.Reset() - out.Type(packet.Describe) - out.Uint8(which) - out.String(target) -} diff --git a/lib/pnet/packet/packets/v3.0/execute.go b/lib/pnet/packet/packets/v3.0/execute.go deleted file mode 100644 index e012a6568cec16930004befbe95797976d700f4e..0000000000000000000000000000000000000000 --- a/lib/pnet/packet/packets/v3.0/execute.go +++ /dev/null @@ -1,26 +0,0 @@ -package packets - -import "pggat2/lib/pnet/packet" - -func ReadExecute(in packet.In) (target string, maxRows int32, ok bool) { - in.Reset() - if in.Type() != packet.Execute { - return - } - target, ok = in.String() - if !ok { - return - } - maxRows, ok = in.Int32() - if !ok { - return - } - return -} - -func WriteExecute(out packet.Out, target string, maxRows int32) { - out.Reset() - out.Type(packet.Execute) - out.String(target) - out.Int32(maxRows) -} diff --git a/lib/pnet/packet/packets/v3.0/parameterstatus.go b/lib/pnet/packet/packets/v3.0/parameterstatus.go deleted file mode 100644 index bac3411b64acd2664128ce47a409aa6067827d0b..0000000000000000000000000000000000000000 --- a/lib/pnet/packet/packets/v3.0/parameterstatus.go +++ /dev/null @@ -1,26 +0,0 @@ -package packets - -import "pggat2/lib/pnet/packet" - -func ReadParameterStatus(in packet.In) (key, value string, ok bool) { - in.Reset() - if in.Type() != packet.ParameterStatus { - return - } - key, ok = in.String() - if !ok { - return - } - value, ok = in.String() - if !ok { - return - } - return -} - -func WriteParameterStatus(out packet.Out, key, value string) { - out.Reset() - out.Type(packet.ParameterStatus) - out.String(key) - out.String(value) -} diff --git a/lib/pnet/packet/packets/v3.0/passwordmessage.go b/lib/pnet/packet/packets/v3.0/passwordmessage.go deleted file mode 100644 index ac01b9ad5a439eb6d48081363d8da57c67e83816..0000000000000000000000000000000000000000 --- a/lib/pnet/packet/packets/v3.0/passwordmessage.go +++ /dev/null @@ -1,21 +0,0 @@ -package packets - -import "pggat2/lib/pnet/packet" - -func ReadPasswordMessage(in packet.In) (string, bool) { - in.Reset() - if in.Type() != packet.AuthenticationResponse { - return "", false - } - password, ok := in.String() - if !ok { - return "", false - } - return password, true -} - -func WritePasswordMessage(out packet.Out, password string) { - out.Reset() - out.Type(packet.AuthenticationResponse) - out.String(password) -} diff --git a/lib/pnet/packet/packets/v3.0/readyforquery.go b/lib/pnet/packet/packets/v3.0/readyforquery.go deleted file mode 100644 index 4035428bc7b13259041ef73bcfdaff3e3fbff3ba..0000000000000000000000000000000000000000 --- a/lib/pnet/packet/packets/v3.0/readyforquery.go +++ /dev/null @@ -1,21 +0,0 @@ -package packets - -import "pggat2/lib/pnet/packet" - -func ReadReadyForQuery(in packet.In) (byte, bool) { - in.Reset() - if in.Type() != packet.ReadyForQuery { - return 0, false - } - state, ok := in.Uint8() - if !ok { - return 0, false - } - return state, true -} - -func WriteReadyForQuery(out packet.Out, state uint8) { - out.Reset() - out.Type(packet.ReadyForQuery) - out.Uint8(state) -} diff --git a/lib/pnet/packet/proxy.go b/lib/pnet/packet/proxy.go deleted file mode 100644 index 706b9163a5726ba942c2b2e0f2bd51d9ee058cdf..0000000000000000000000000000000000000000 --- a/lib/pnet/packet/proxy.go +++ /dev/null @@ -1,6 +0,0 @@ -package packet - -func Proxy(out Out, in In) { - out.Type(in.Type()) - out.Bytes(in.Full()) -} diff --git a/lib/pnet/packet/type.go b/lib/pnet/packet/type.go deleted file mode 100644 index 25b3ab87311708a57c1ddea11ed72f9d19eba7f3..0000000000000000000000000000000000000000 --- a/lib/pnet/packet/type.go +++ /dev/null @@ -1,43 +0,0 @@ -package packet - -type Type byte - -const ( - None Type = 0 - Authentication Type = 'R' - BackendKeyData Type = 'K' - Bind Type = 'B' - BindComplete Type = '2' - Close Type = 'C' - CloseComplete Type = '3' - CommandComplete Type = 'C' - CopyData Type = 'd' - CopyDone Type = 'c' - CopyFail Type = 'f' - CopyInResponse Type = 'G' - CopyOutResponse Type = 'H' - CopyBothResponse Type = 'W' - DataRow Type = 'D' - Describe Type = 'D' - EmptyQueryResponse Type = 'I' - ErrorResponse Type = 'E' - Execute Type = 'E' - Flush Type = 'H' - FunctionCall Type = 'F' - FunctionCallResponse Type = 'V' - AuthenticationResponse Type = 'p' - NegotiateProtocolVersion Type = 'v' - NoData Type = 'n' - NoticeResponse Type = 'N' - NotificationResponse Type = 'A' - ParameterDescription Type = 't' - ParameterStatus Type = 'S' - Parse Type = 'P' - ParseComplete Type = '1' - PortalSuspended Type = 's' - Query Type = 'Q' - ReadyForQuery Type = 'Z' - RowDescription Type = 'T' - Sync Type = 'S' - Terminate Type = 'X' -) diff --git a/lib/pnet/pio/reader.go b/lib/pnet/pio/reader.go deleted file mode 100644 index 1939881e4ce5255594ce3173a3892c4fccba5c7e..0000000000000000000000000000000000000000 --- a/lib/pnet/pio/reader.go +++ /dev/null @@ -1,106 +0,0 @@ -package pio - -import ( - "encoding/binary" - "io" - - "pggat2/lib/pnet" - "pggat2/lib/pnet/packet" - "pggat2/lib/util/decorator" - "pggat2/lib/util/slices" -) - -type Reader struct { - noCopy decorator.NoCopy - reader io.Reader - // header buffer for reading packet headers - // (allocating within Read would escape to heap) - header [5]byte - - buf packet.InBuf - payload []byte -} - -func MakeReader(reader io.Reader) Reader { - return Reader{ - reader: reader, - } -} - -func NewReader(reader io.Reader) *Reader { - v := MakeReader(reader) - return &v -} - -// Read fetches the next packet from the underlying io.Reader and gives you a packet.In -// Calling Read will invalidate all other packet.In's for this Reader -func (T *Reader) Read() (packet.In, error) { - // read header - _, err := io.ReadFull(T.reader, T.header[:]) - if err != nil { - return packet.In{}, err - } - - err = T.readPayload() - if err != nil { - return packet.In{}, err - } - - T.buf.Reset( - packet.Type(T.header[0]), - T.payload, - ) - - // log.Printf("read typed packet %c %v\n", typ, T.payload) - - return packet.MakeIn( - &T.buf, - ), nil -} - -// ReadUntyped is similar to Read, but it doesn't read a packet.Type -func (T *Reader) ReadUntyped() (packet.In, error) { - // read header - _, err := io.ReadFull(T.reader, T.header[1:]) - if err != nil { - return packet.In{}, err - } - - err = T.readPayload() - if err != nil { - return packet.In{}, err - } - - T.buf.Reset( - packet.None, - T.payload, - ) - - // log.Println("read untyped packet", T.payload) - - return packet.MakeIn( - &T.buf, - ), nil -} - -func (T *Reader) readPayload() error { - length := binary.BigEndian.Uint32(T.header[1:]) - 4 - - // resize body to length - T.payload = slices.Resize(T.payload, int(length)) - // read body - _, err := io.ReadFull(T.reader, T.payload) - if err != nil { - return err - } - - return nil -} - -func (T *Reader) ReadByte() (byte, error) { - T.header[0] = 0 - _, err := io.ReadFull(T.reader, T.header[:1]) - return T.header[0], err -} - -var _ pnet.Reader = (*Reader)(nil) diff --git a/lib/pnet/pio/readwriter.go b/lib/pnet/pio/readwriter.go deleted file mode 100644 index 43ce4561759a216ccc8a024a2ab2b466e221aafb..0000000000000000000000000000000000000000 --- a/lib/pnet/pio/readwriter.go +++ /dev/null @@ -1,26 +0,0 @@ -package pio - -import ( - "io" - - "pggat2/lib/pnet" -) - -type ReadWriter struct { - Reader - Writer -} - -func MakeReadWriter(inner io.ReadWriter) ReadWriter { - return ReadWriter{ - Reader: MakeReader(inner), - Writer: MakeWriter(inner), - } -} - -func NewReadWriter(inner io.ReadWriter) *ReadWriter { - rw := MakeReadWriter(inner) - return &rw -} - -var _ pnet.ReadWriter = (*ReadWriter)(nil) diff --git a/lib/pnet/pio/writer.go b/lib/pnet/pio/writer.go deleted file mode 100644 index 8bdcd5e3f30999baf3d23ce72b3d35354d11e876..0000000000000000000000000000000000000000 --- a/lib/pnet/pio/writer.go +++ /dev/null @@ -1,82 +0,0 @@ -package pio - -import ( - "encoding/binary" - "io" - - "pggat2/lib/pnet" - "pggat2/lib/pnet/packet" - "pggat2/lib/util/decorator" -) - -type Writer struct { - noCopy decorator.NoCopy - writer io.Writer - // header buffer for writing packet headers - // (allocating within Write would escape to heap) - header [5]byte - - buf packet.OutBuf -} - -func MakeWriter(writer io.Writer) Writer { - return Writer{ - writer: writer, - } -} - -func NewWriter(writer io.Writer) *Writer { - v := MakeWriter(writer) - return &v -} - -// Write gives you a packet.Out -// Calling Write will invalidate all other packet.Out's for this Writer -func (T *Writer) Write() packet.Out { - T.buf.Reset() - - return packet.MakeOut( - &T.buf, - ) -} - -func (T *Writer) Send(typ packet.Type, payload []byte) error { - /* if typ != packet.None { - log.Printf("write typed packet %c %v\n", typ, payload) - } else { - log.Println("write untyped packet", payload) - } */ - - // prepare header - T.header[0] = byte(typ) - binary.BigEndian.PutUint32(T.header[1:], uint32(len(payload)+4)) - - // write header - if typ != packet.None { - _, err := T.writer.Write(T.header[:]) - if err != nil { - return err - } - } else { - _, err := T.writer.Write(T.header[1:]) - if err != nil { - return err - } - } - - // write payload - _, err := T.writer.Write(payload) - if err != nil { - return err - } - - return nil -} - -func (T *Writer) WriteByte(b byte) error { - T.header[0] = b - _, err := T.writer.Write(T.header[:1]) - return err -} - -var _ pnet.Writer = (*Writer)(nil) diff --git a/lib/pnet/proxy.go b/lib/pnet/proxy.go deleted file mode 100644 index bebee64ba0ae906199c3778b6895aecbc4735e27..0000000000000000000000000000000000000000 --- a/lib/pnet/proxy.go +++ /dev/null @@ -1,17 +0,0 @@ -package pnet - -import "pggat2/lib/pnet/packet" - -func ProxyPacket(writer Writer, in packet.In) error { - out := writer.Write() - packet.Proxy(out, in) - return writer.Send(out.Finish()) -} - -func Proxy(writer Writer, reader Reader) error { - in, err := reader.Read() - if err != nil { - return err - } - return ProxyPacket(writer, in) -} diff --git a/lib/pnet/reader.go b/lib/pnet/reader.go deleted file mode 100644 index 259cc33bcdddb9880ab354cba63b5d463c7d3624..0000000000000000000000000000000000000000 --- a/lib/pnet/reader.go +++ /dev/null @@ -1,8 +0,0 @@ -package pnet - -import "pggat2/lib/pnet/packet" - -type Reader interface { - Read() (packet.In, error) - ReadUntyped() (packet.In, error) -} diff --git a/lib/pnet/writer.go b/lib/pnet/writer.go deleted file mode 100644 index bd92c1f566931c54f7e6ae642acace146d3052c0..0000000000000000000000000000000000000000 --- a/lib/pnet/writer.go +++ /dev/null @@ -1,14 +0,0 @@ -package pnet - -import ( - "io" - - "pggat2/lib/pnet/packet" -) - -type Writer interface { - io.ByteWriter - - Write() packet.Out - Send(packet.Type, []byte) error -} diff --git a/lib/util/slices/clear.go b/lib/util/slices/clear.go new file mode 100644 index 0000000000000000000000000000000000000000..972b344e17a12fc785276b5c5948685ebe1fa1e8 --- /dev/null +++ b/lib/util/slices/clear.go @@ -0,0 +1,7 @@ +package slices + +func Clear[T any](slice []T) { + for i := 0; i < len(slice); i++ { + slice[i] = *new(T) + } +} diff --git a/lib/zap/buf.go b/lib/zap/buf.go new file mode 100644 index 0000000000000000000000000000000000000000..3145731f5e7b3c0d3ad589a475429e6a296483af --- /dev/null +++ b/lib/zap/buf.go @@ -0,0 +1,297 @@ +package zap + +import ( + "encoding/binary" + "io" + "log" + "math" + + "pggat2/lib/util/decorator" + "pggat2/lib/util/slices" +) + +type Buf struct { + noCopy decorator.NoCopy + + pos int + buf []byte + rev int +} + +func (T *Buf) assertRev(rev int) { + // this check can be turned off when in production mode (for dev, this is helpful though) + if T.rev != rev { + panic("use after resource release") + } +} + +func (T *Buf) ReadByte(reader io.Reader) (byte, error) { + T.rev++ + T.pos = 0 + + T.buf = slices.Resize(T.buf, 1) + _, err := io.ReadFull(reader, T.buf) + if err != nil { + return 0, err + } + return T.buf[0], nil +} + +func (T *Buf) Read(reader io.Reader, typed bool) (In, error) { + T.rev++ + T.pos = 0 + + // read header + T.buf = slices.Resize(T.buf, 5) + var err error + if typed { + _, err = io.ReadFull(reader, T.buf) + } else { + _, err = io.ReadFull(reader, T.buf[1:]) + } + if err != nil { + return In{}, err + } + + // extract length + length := binary.BigEndian.Uint32(T.buf[1:]) + + // read payload + T.buf = slices.Resize(T.buf, int(length)+5) + _, err = io.ReadFull(reader, T.buf[5:]) + if err != nil { + return In{}, err + } + + log.Printf("read packet %c %v\n", T.readType(), T.remaining()) + + return In{ + buf: T, + rev: T.rev, + }, nil +} + +func (T *Buf) WriteByte(writer io.Writer, b byte) error { + T.rev++ + T.pos = 0 + + T.buf = slices.Resize(T.buf, 1) + T.buf[0] = b + _, err := writer.Write(T.buf) + return err +} + +func (T *Buf) Write() Out { + T.rev++ + T.pos = 0 + + T.buf = slices.Resize(T.buf, 5) + + return Out{ + buf: T, + rev: T.rev, + } +} + +func (T *Buf) full() []byte { + // put length + binary.BigEndian.PutUint32(T.buf[1:], uint32(len(T.buf)-1)) + + log.Printf("write packet %c %v\n", T.readType(), T.buf[5:]) + + if T.readType() == 0 { + // untyped + return T.buf[1:] + } else { + // typed + return T.buf + } +} + +// read methods + +func (T *Buf) resetRead() { + T.pos = 0 +} + +func (T *Buf) readType() Type { + return Type(T.buf[0]) +} + +func (T *Buf) remaining() []byte { + return T.buf[T.pos+5:] +} + +func (T *Buf) readUint8() (uint8, bool) { + rem := T.remaining() + if len(rem) < 1 { + return 0, false + } + T.pos += 1 + return rem[0], true +} + +func (T *Buf) readUint16() (uint16, bool) { + rem := T.remaining() + if len(rem) < 2 { + return 0, false + } + T.pos += 2 + return binary.BigEndian.Uint16(rem), true +} + +func (T *Buf) readUint32() (uint32, bool) { + rem := T.remaining() + if len(rem) < 4 { + return 0, false + } + T.pos += 4 + return binary.BigEndian.Uint32(rem), true +} + +func (T *Buf) readUint64() (uint64, bool) { + rem := T.remaining() + if len(rem) < 8 { + return 0, false + } + T.pos += 8 + return binary.BigEndian.Uint64(rem), true +} + +func (T *Buf) readInt8() (int8, bool) { + v, ok := T.readUint8() + if !ok { + return 0, false + } + return int8(v), true +} + +func (T *Buf) readInt16() (int16, bool) { + v, ok := T.readUint16() + if !ok { + return 0, false + } + return int16(v), true +} + +func (T *Buf) readInt32() (int32, bool) { + v, ok := T.readUint32() + if !ok { + return 0, false + } + return int32(v), true +} + +func (T *Buf) readInt64() (int64, bool) { + v, ok := T.readUint64() + if !ok { + return 0, false + } + return int64(v), true +} + +func (T *Buf) readFloat32() (float32, bool) { + v, ok := T.readUint32() + if !ok { + return 0, false + } + return math.Float32frombits(v), true +} + +func (T *Buf) readFloat64() (float64, bool) { + v, ok := T.readUint64() + if !ok { + return 0, false + } + return math.Float64frombits(v), true +} + +func (T *Buf) readString() (string, bool) { + rem := T.remaining() + for i, c := range rem { + if c == 0 { + T.pos += i + 1 + return string(rem[:i]), true + } + } + return "", false +} + +func (T *Buf) readBytes(b []byte) bool { + rem := T.remaining() + if len(rem) < len(b) { + return false + } + T.pos += len(b) + copy(b, rem) + return true +} + +func (T *Buf) readUnsafeBytes(count int) ([]byte, bool) { + rem := T.remaining() + if len(rem) < count { + return nil, false + } + T.pos += count + return rem[:count], true +} + +// write methods + +func (T *Buf) resetWrite() { + T.buf = slices.Resize(T.buf, 5) + slices.Clear(T.buf) +} + +func (T *Buf) writeType(typ Type) { + T.buf[0] = byte(typ) +} + +func (T *Buf) writeUint8(v uint8) { + T.buf = append(T.buf, v) +} + +func (T *Buf) writeUint16(v uint16) { + T.buf = binary.BigEndian.AppendUint16(T.buf, v) +} + +func (T *Buf) writeUint32(v uint32) { + T.buf = binary.BigEndian.AppendUint32(T.buf, v) +} + +func (T *Buf) writeUint64(v uint64) { + T.buf = binary.BigEndian.AppendUint64(T.buf, v) +} + +func (T *Buf) writeInt8(v int8) { + T.writeUint8(uint8(v)) +} + +func (T *Buf) writeInt16(v int16) { + T.writeUint16(uint16(v)) +} + +func (T *Buf) writeInt32(v int32) { + T.writeUint32(uint32(v)) +} + +func (T *Buf) writeInt64(v int64) { + T.writeUint64(uint64(v)) +} + +func (T *Buf) writeFloat32(v float32) { + T.writeUint32(math.Float32bits(v)) +} + +func (T *Buf) writeFloat64(v float64) { + T.writeUint64(math.Float64bits(v)) +} + +func (T *Buf) writeString(v string) { + T.buf = append(T.buf, v...) + T.buf = append(T.buf, 0) +} + +func (T *Buf) writeBytes(v []byte) { + T.buf = append(T.buf, v...) +} diff --git a/lib/zap/in.go b/lib/zap/in.go new file mode 100644 index 0000000000000000000000000000000000000000..6cc3b9f62a58a3a412aa723b7db551ff509d502e --- /dev/null +++ b/lib/zap/in.go @@ -0,0 +1,86 @@ +package zap + +type In struct { + buf *Buf + rev int +} + +func (T In) Reset() { + T.buf.assertRev(T.rev) + T.buf.resetRead() +} + +func (T In) Remaining() []byte { + T.buf.assertRev(T.rev) + return T.buf.remaining() +} + +func (T In) Type() Type { + T.buf.assertRev(T.rev) + return T.buf.readType() +} + +func (T In) Int8() (int8, bool) { + T.buf.assertRev(T.rev) + return T.buf.readInt8() +} + +func (T In) Int16() (int16, bool) { + T.buf.assertRev(T.rev) + return T.buf.readInt16() +} + +func (T In) Int32() (int32, bool) { + T.buf.assertRev(T.rev) + return T.buf.readInt32() +} + +func (T In) Int64() (int64, bool) { + T.buf.assertRev(T.rev) + return T.buf.readInt64() +} + +func (T In) Uint8() (uint8, bool) { + T.buf.assertRev(T.rev) + return T.buf.readUint8() +} + +func (T In) Uint16() (uint16, bool) { + T.buf.assertRev(T.rev) + return T.buf.readUint16() +} + +func (T In) Uint32() (uint32, bool) { + T.buf.assertRev(T.rev) + return T.buf.readUint32() +} + +func (T In) Uint64() (uint64, bool) { + T.buf.assertRev(T.rev) + return T.buf.readUint64() +} + +func (T In) Float32() (float32, bool) { + T.buf.assertRev(T.rev) + return T.buf.readFloat32() +} + +func (T In) Float64() (float64, bool) { + T.buf.assertRev(T.rev) + return T.buf.readFloat64() +} + +func (T In) String() (string, bool) { + T.buf.assertRev(T.rev) + return T.buf.readString() +} + +func (T In) Bytes(b []byte) bool { + T.buf.assertRev(T.rev) + return T.buf.readBytes(b) +} + +func (T In) UnsafeBytes(count int) ([]byte, bool) { + T.buf.assertRev(T.rev) + return T.buf.readUnsafeBytes(count) +} diff --git a/lib/zap/out.go b/lib/zap/out.go new file mode 100644 index 0000000000000000000000000000000000000000..9aec94afd08cd8aaf7a9a3c95a28aa59b5a6de1a --- /dev/null +++ b/lib/zap/out.go @@ -0,0 +1,81 @@ +package zap + +type Out struct { + buf *Buf + rev int +} + +func (T Out) Reset() { + T.buf.assertRev(T.rev) + T.buf.resetWrite() +} + +func (T Out) Full() []byte { + T.buf.assertRev(T.rev) + return T.buf.full() +} + +func (T Out) Type(typ Type) { + T.buf.assertRev(T.rev) + T.buf.writeType(typ) +} + +func (T Out) Int8(v int8) { + T.buf.assertRev(T.rev) + T.buf.writeInt8(v) +} + +func (T Out) Int16(v int16) { + T.buf.assertRev(T.rev) + T.buf.writeInt16(v) +} + +func (T Out) Int32(v int32) { + T.buf.assertRev(T.rev) + T.buf.writeInt32(v) +} + +func (T Out) Int64(v int64) { + T.buf.assertRev(T.rev) + T.buf.writeInt64(v) +} + +func (T Out) Uint8(v uint8) { + T.buf.assertRev(T.rev) + T.buf.writeUint8(v) +} + +func (T Out) Uint16(v uint16) { + T.buf.assertRev(T.rev) + T.buf.writeUint16(v) +} + +func (T Out) Uint32(v uint32) { + T.buf.assertRev(T.rev) + T.buf.writeUint32(v) +} + +func (T Out) Uint64(v uint64) { + T.buf.assertRev(T.rev) + T.buf.writeUint64(v) +} + +func (T Out) Float32(v float32) { + T.buf.assertRev(T.rev) + T.buf.writeFloat32(v) +} + +func (T Out) Float64(v float64) { + T.buf.assertRev(T.rev) + T.buf.writeFloat64(v) +} + +func (T Out) String(v string) { + T.buf.assertRev(T.rev) + T.buf.writeString(v) +} + +func (T Out) Bytes(v []byte) { + T.buf.assertRev(T.rev) + T.buf.writeBytes(v) +} diff --git a/lib/zap/packets/v3.0/authenticationcleartext.go b/lib/zap/packets/v3.0/authenticationcleartext.go new file mode 100644 index 0000000000000000000000000000000000000000..9b3ebdbc407014b18ae819bc278d301f60f0b79d --- /dev/null +++ b/lib/zap/packets/v3.0/authenticationcleartext.go @@ -0,0 +1,26 @@ +package packets + +import ( + "pggat2/lib/zap" +) + +func ReadAuthenticationCleartext(in zap.In) bool { + in.Reset() + if in.Type() != Authentication { + return false + } + method, ok := in.Int32() + if !ok { + return false + } + if method != 3 { + return false + } + return true +} + +func WriteAuthenticationCleartext(out zap.Out) { + out.Reset() + out.Type(Authentication) + out.Int32(3) +} diff --git a/lib/pnet/packet/packets/v3.0/authenticationmd5.go b/lib/zap/packets/v3.0/authenticationmd5.go similarity index 58% rename from lib/pnet/packet/packets/v3.0/authenticationmd5.go rename to lib/zap/packets/v3.0/authenticationmd5.go index bde2d1968d22ed9ce9aa108bb04dc641801f8a89..2bcef712c0335e3774aabb430ff0662fd1c83c13 100644 --- a/lib/pnet/packet/packets/v3.0/authenticationmd5.go +++ b/lib/zap/packets/v3.0/authenticationmd5.go @@ -1,10 +1,12 @@ package packets -import "pggat2/lib/pnet/packet" +import ( + "pggat2/lib/zap" +) -func ReadAuthenticationMD5(in packet.In) ([4]byte, bool) { +func ReadAuthenticationMD5(in zap.In) ([4]byte, bool) { in.Reset() - if in.Type() != packet.Authentication { + if in.Type() != Authentication { return [4]byte{}, false } method, ok := in.Int32() @@ -22,9 +24,9 @@ func ReadAuthenticationMD5(in packet.In) ([4]byte, bool) { return salt, true } -func WriteAuthenticationMD5(out packet.Out, salt [4]byte) { +func WriteAuthenticationMD5(out zap.Out, salt [4]byte) { out.Reset() - out.Type(packet.Authentication) + out.Type(Authentication) out.Uint32(5) out.Bytes(salt[:]) } diff --git a/lib/zap/packets/v3.0/authenticationok.go b/lib/zap/packets/v3.0/authenticationok.go new file mode 100644 index 0000000000000000000000000000000000000000..cd682ec5a31f4bb49cb0fa3d6c82b275ee46ec16 --- /dev/null +++ b/lib/zap/packets/v3.0/authenticationok.go @@ -0,0 +1,26 @@ +package packets + +import ( + "pggat2/lib/zap" +) + +func ReadAuthenticationOk(in zap.In) bool { + in.Reset() + if in.Type() != Authentication { + return false + } + method, ok := in.Int32() + if !ok { + return false + } + if method != 0 { + return false + } + return true +} + +func WriteAuthenticationOk(out zap.Out) { + out.Reset() + out.Type(Authentication) + out.Int32(0) +} diff --git a/lib/zap/packets/v3.0/authenticationresponse.go b/lib/zap/packets/v3.0/authenticationresponse.go new file mode 100644 index 0000000000000000000000000000000000000000..1dd93e0247ee1d66426f1c56bf356ae2742f3f88 --- /dev/null +++ b/lib/zap/packets/v3.0/authenticationresponse.go @@ -0,0 +1,19 @@ +package packets + +import ( + "pggat2/lib/zap" +) + +func ReadAuthenticationResponse(in zap.In) ([]byte, bool) { + in.Reset() + if in.Type() != AuthenticationResponse { + return nil, false + } + return in.Remaining(), true +} + +func WriteAuthenticationResponse(out zap.Out, resp []byte) { + out.Reset() + out.Type(AuthenticationResponse) + out.Bytes(resp) +} diff --git a/lib/pnet/packet/packets/v3.0/authenticationsasl.go b/lib/zap/packets/v3.0/authenticationsasl.go similarity index 75% rename from lib/pnet/packet/packets/v3.0/authenticationsasl.go rename to lib/zap/packets/v3.0/authenticationsasl.go index 9c5589b2b127fabf69158d6909d33974a93f6d30..5d6ba59fab4be8c8402f394ee3ba2117fb83ebef 100644 --- a/lib/pnet/packet/packets/v3.0/authenticationsasl.go +++ b/lib/zap/packets/v3.0/authenticationsasl.go @@ -1,10 +1,12 @@ package packets -import "pggat2/lib/pnet/packet" +import ( + "pggat2/lib/zap" +) -func ReadAuthenticationSASL(in packet.In) ([]string, bool) { +func ReadAuthenticationSASL(in zap.In) ([]string, bool) { in.Reset() - if in.Type() != packet.Authentication { + if in.Type() != Authentication { return nil, false } @@ -44,9 +46,9 @@ func ReadAuthenticationSASL(in packet.In) ([]string, bool) { return mechanisms, true } -func WriteAuthenticationSASL(out packet.Out, mechanisms []string) { +func WriteAuthenticationSASL(out zap.Out, mechanisms []string) { out.Reset() - out.Type(packet.Authentication) + out.Type(Authentication) out.Int32(10) for _, mechanism := range mechanisms { out.String(mechanism) diff --git a/lib/zap/packets/v3.0/authenticationsaslcontinue.go b/lib/zap/packets/v3.0/authenticationsaslcontinue.go new file mode 100644 index 0000000000000000000000000000000000000000..269a373feb431f9050e088fbc45f7fcf1574ba42 --- /dev/null +++ b/lib/zap/packets/v3.0/authenticationsaslcontinue.go @@ -0,0 +1,27 @@ +package packets + +import ( + "pggat2/lib/zap" +) + +func ReadAuthenticationSASLContinue(in zap.In) ([]byte, bool) { + in.Reset() + if in.Type() != Authentication { + return nil, false + } + method, ok := in.Int32() + if !ok { + return nil, false + } + if method != 11 { + return nil, false + } + return in.Remaining(), true +} + +func WriteAuthenticationSASLContinue(out zap.Out, resp []byte) { + out.Reset() + out.Type(Authentication) + out.Int32(11) + out.Bytes(resp) +} diff --git a/lib/zap/packets/v3.0/authenticationsaslfinal.go b/lib/zap/packets/v3.0/authenticationsaslfinal.go new file mode 100644 index 0000000000000000000000000000000000000000..747a95091d0e0d87d67f679dad1a0785dd51642f --- /dev/null +++ b/lib/zap/packets/v3.0/authenticationsaslfinal.go @@ -0,0 +1,27 @@ +package packets + +import ( + "pggat2/lib/zap" +) + +func ReadAuthenticationSASLFinal(in zap.In) ([]byte, bool) { + in.Reset() + if in.Type() != Authentication { + return nil, false + } + method, ok := in.Int32() + if !ok { + return nil, false + } + if method != 12 { + return nil, false + } + return in.Remaining(), true +} + +func WriteAuthenticationSASLFinal(out zap.Out, resp []byte) { + out.Reset() + out.Type(Authentication) + out.Int32(12) + out.Bytes(resp) +} diff --git a/lib/pnet/packet/packets/v3.0/backendkeydata.go b/lib/zap/packets/v3.0/backendkeydata.go similarity index 51% rename from lib/pnet/packet/packets/v3.0/backendkeydata.go rename to lib/zap/packets/v3.0/backendkeydata.go index c41ebd139031b08875840bf4e7efc65fca044f3a..feb05bac9571bfc2c4df9cc10dbf49d6653d70f4 100644 --- a/lib/pnet/packet/packets/v3.0/backendkeydata.go +++ b/lib/zap/packets/v3.0/backendkeydata.go @@ -1,10 +1,12 @@ package packets -import "pggat2/lib/pnet/packet" +import ( + "pggat2/lib/zap" +) -func ReadBackendKeyData(in packet.In) ([8]byte, bool) { +func ReadBackendKeyData(in zap.In) ([8]byte, bool) { in.Reset() - if in.Type() != packet.BackendKeyData { + if in.Type() != BackendKeyData { return [8]byte{}, false } var cancellationKey [8]byte @@ -15,8 +17,8 @@ func ReadBackendKeyData(in packet.In) ([8]byte, bool) { return cancellationKey, true } -func WriteBackendKeyData(out packet.Out, cancellationKey [8]byte) { +func WriteBackendKeyData(out zap.Out, cancellationKey [8]byte) { out.Reset() - out.Type(packet.BackendKeyData) + out.Type(BackendKeyData) out.Bytes(cancellationKey[:]) } diff --git a/lib/pnet/packet/packets/v3.0/bind.go b/lib/zap/packets/v3.0/bind.go similarity index 83% rename from lib/pnet/packet/packets/v3.0/bind.go rename to lib/zap/packets/v3.0/bind.go index cb28e3e96ebda0a0267a78ef1ffda50901536877..caa0d871620b1d1789c171e1ebc5eb311194d340 100644 --- a/lib/pnet/packet/packets/v3.0/bind.go +++ b/lib/zap/packets/v3.0/bind.go @@ -1,10 +1,12 @@ package packets -import "pggat2/lib/pnet/packet" +import ( + "pggat2/lib/zap" +) -func ReadBind(in packet.In) (destination string, source string, parameterFormatCodes []int16, parameterValues [][]byte, resultFormatCodes []int16, ok bool) { +func ReadBind(in zap.In) (destination string, source string, parameterFormatCodes []int16, parameterValues [][]byte, resultFormatCodes []int16, ok bool) { in.Reset() - if in.Type() != packet.Bind { + if in.Type() != Bind { return } destination, ok = in.String() @@ -65,9 +67,9 @@ func ReadBind(in packet.In) (destination string, source string, parameterFormatC return } -func WriteBind(out packet.Out, destination, source string, parameterFormatCodes []int16, parameterValues [][]byte, resultFormatCodes []int16) { +func WriteBind(out zap.Out, destination, source string, parameterFormatCodes []int16, parameterValues [][]byte, resultFormatCodes []int16) { out.Reset() - out.Type(packet.Bind) + out.Type(Bind) out.String(destination) out.String(source) out.Int16(int16(len(parameterFormatCodes))) diff --git a/lib/zap/packets/v3.0/close.go b/lib/zap/packets/v3.0/close.go new file mode 100644 index 0000000000000000000000000000000000000000..05e11bf9beb948e5ba639f7dbee8b3d5f9bcd6c6 --- /dev/null +++ b/lib/zap/packets/v3.0/close.go @@ -0,0 +1,28 @@ +package packets + +import ( + "pggat2/lib/zap" +) + +func ReadClose(in zap.In) (which uint8, target string, ok bool) { + in.Reset() + if in.Type() != Close { + return + } + which, ok = in.Uint8() + if !ok { + return + } + target, ok = in.String() + if !ok { + return + } + return +} + +func WriteClose(out zap.Out, which uint8, target string) { + out.Reset() + out.Type(Close) + out.Uint8(which) + out.String(target) +} diff --git a/lib/zap/packets/v3.0/describe.go b/lib/zap/packets/v3.0/describe.go new file mode 100644 index 0000000000000000000000000000000000000000..906abfbce91f265e1b1a729d8d8ece43a7300ccb --- /dev/null +++ b/lib/zap/packets/v3.0/describe.go @@ -0,0 +1,28 @@ +package packets + +import ( + "pggat2/lib/zap" +) + +func ReadDescribe(in zap.In) (which uint8, target string, ok bool) { + in.Reset() + if in.Type() != Describe { + return + } + which, ok = in.Uint8() + if !ok { + return + } + target, ok = in.String() + if !ok { + return + } + return +} + +func WriteDescribe(out zap.Out, which uint8, target string) { + out.Reset() + out.Type(Describe) + out.Uint8(which) + out.String(target) +} diff --git a/lib/pnet/packet/packets/v3.0/errorresponse.go b/lib/zap/packets/v3.0/errorresponse.go similarity index 81% rename from lib/pnet/packet/packets/v3.0/errorresponse.go rename to lib/zap/packets/v3.0/errorresponse.go index 60ee0ca58507ddf24c975981b842848a074bf3d9..2fae634108448d360bebf29b3c1de3fdcf514d83 100644 --- a/lib/pnet/packet/packets/v3.0/errorresponse.go +++ b/lib/zap/packets/v3.0/errorresponse.go @@ -2,12 +2,12 @@ package packets import ( "pggat2/lib/perror" - "pggat2/lib/pnet/packet" + "pggat2/lib/zap" ) -func ReadErrorResponse(in packet.In) (perror.Error, bool) { +func ReadErrorResponse(in zap.In) (perror.Error, bool) { in.Reset() - if in.Type() != packet.ErrorResponse { + if in.Type() != ErrorResponse { return nil, false } @@ -54,9 +54,9 @@ func ReadErrorResponse(in packet.In) (perror.Error, bool) { ), true } -func WriteErrorResponse(out packet.Out, err perror.Error) { +func WriteErrorResponse(out zap.Out, err perror.Error) { out.Reset() - out.Type(packet.ErrorResponse) + out.Type(ErrorResponse) out.Uint8('S') out.String(string(err.Severity())) diff --git a/lib/zap/packets/v3.0/errors.go b/lib/zap/packets/v3.0/errors.go new file mode 100644 index 0000000000000000000000000000000000000000..7fe488210c45ea31a7423b59c7de9da07c77515e --- /dev/null +++ b/lib/zap/packets/v3.0/errors.go @@ -0,0 +1,16 @@ +package packets + +import "pggat2/lib/perror" + +var ( + ErrBadFormat = perror.New( + perror.FATAL, + perror.ProtocolViolation, + "Bad packet format", + ) + ErrUnexpectedPacket = perror.New( + perror.FATAL, + perror.ProtocolViolation, + "unexpected packet", + ) +) diff --git a/lib/zap/packets/v3.0/execute.go b/lib/zap/packets/v3.0/execute.go new file mode 100644 index 0000000000000000000000000000000000000000..84fa064d11d75af53bc9b7c556fdbf481c4d57ef --- /dev/null +++ b/lib/zap/packets/v3.0/execute.go @@ -0,0 +1,28 @@ +package packets + +import ( + "pggat2/lib/zap" +) + +func ReadExecute(in zap.In) (target string, maxRows int32, ok bool) { + in.Reset() + if in.Type() != Execute { + return + } + target, ok = in.String() + if !ok { + return + } + maxRows, ok = in.Int32() + if !ok { + return + } + return +} + +func WriteExecute(out zap.Out, target string, maxRows int32) { + out.Reset() + out.Type(Execute) + out.String(target) + out.Int32(maxRows) +} diff --git a/lib/pnet/packet/packets/v3.0/negotiateprotocolversion.go b/lib/zap/packets/v3.0/negotiateprotocolversion.go similarity index 65% rename from lib/pnet/packet/packets/v3.0/negotiateprotocolversion.go rename to lib/zap/packets/v3.0/negotiateprotocolversion.go index 4ba56adc24013796b2f44f2346d50f971913c2b8..db2df2b807345d331eb041bc8a976c3ae5f5c93d 100644 --- a/lib/pnet/packet/packets/v3.0/negotiateprotocolversion.go +++ b/lib/zap/packets/v3.0/negotiateprotocolversion.go @@ -1,10 +1,12 @@ package packets -import "pggat2/lib/pnet/packet" +import ( + "pggat2/lib/zap" +) -func ReadNegotiateProtocolVersion(in packet.In) (minorProtocolVersion int32, unrecognizedOptions []string, ok bool) { +func ReadNegotiateProtocolVersion(in zap.In) (minorProtocolVersion int32, unrecognizedOptions []string, ok bool) { in.Reset() - if in.Type() != packet.NegotiateProtocolVersion { + if in.Type() != NegotiateProtocolVersion { return } minorProtocolVersion, ok = in.Int32() @@ -29,9 +31,9 @@ func ReadNegotiateProtocolVersion(in packet.In) (minorProtocolVersion int32, unr return } -func WriteNegotiateProtocolVersion(out packet.Out, minorProtocolVersion int32, unrecognizedOptions []string) { +func WriteNegotiateProtocolVersion(out zap.Out, minorProtocolVersion int32, unrecognizedOptions []string) { out.Reset() - out.Type(packet.NegotiateProtocolVersion) + out.Type(NegotiateProtocolVersion) out.Int32(minorProtocolVersion) out.Int32(int32(len(unrecognizedOptions))) for _, option := range unrecognizedOptions { diff --git a/lib/zap/packets/v3.0/parameterstatus.go b/lib/zap/packets/v3.0/parameterstatus.go new file mode 100644 index 0000000000000000000000000000000000000000..09b304cf4700148761935b123d1077f2b72074aa --- /dev/null +++ b/lib/zap/packets/v3.0/parameterstatus.go @@ -0,0 +1,28 @@ +package packets + +import ( + "pggat2/lib/zap" +) + +func ReadParameterStatus(in zap.In) (key, value string, ok bool) { + in.Reset() + if in.Type() != ParameterStatus { + return + } + key, ok = in.String() + if !ok { + return + } + value, ok = in.String() + if !ok { + return + } + return +} + +func WriteParameterStatus(out zap.Out, key, value string) { + out.Reset() + out.Type(ParameterStatus) + out.String(key) + out.String(value) +} diff --git a/lib/pnet/packet/packets/v3.0/parse.go b/lib/zap/packets/v3.0/parse.go similarity index 70% rename from lib/pnet/packet/packets/v3.0/parse.go rename to lib/zap/packets/v3.0/parse.go index 3055e77d59bcd2faf7a2c67abf0b4a9ff3498428..087fe350b2a1bda4044575527f5aa5e1ca71d6cc 100644 --- a/lib/pnet/packet/packets/v3.0/parse.go +++ b/lib/zap/packets/v3.0/parse.go @@ -1,10 +1,12 @@ package packets -import "pggat2/lib/pnet/packet" +import ( + "pggat2/lib/zap" +) -func ReadParse(in packet.In) (destination string, query string, parameterDataTypes []int32, ok bool) { +func ReadParse(in zap.In) (destination string, query string, parameterDataTypes []int32, ok bool) { in.Reset() - if in.Type() != packet.Parse { + if in.Type() != Parse { return } destination, ok = in.String() @@ -32,9 +34,9 @@ func ReadParse(in packet.In) (destination string, query string, parameterDataTyp return } -func WriteParse(out packet.Out, destination string, query string, parameterDataTypes []int32) { +func WriteParse(out zap.Out, destination string, query string, parameterDataTypes []int32) { out.Reset() - out.Type(packet.Parse) + out.Type(Parse) out.String(destination) out.String(query) out.Int16(int16(len(parameterDataTypes))) diff --git a/lib/zap/packets/v3.0/passwordmessage.go b/lib/zap/packets/v3.0/passwordmessage.go new file mode 100644 index 0000000000000000000000000000000000000000..89d16ad41ebf1915f4699c0a8d80bc814bb64fa1 --- /dev/null +++ b/lib/zap/packets/v3.0/passwordmessage.go @@ -0,0 +1,23 @@ +package packets + +import ( + "pggat2/lib/zap" +) + +func ReadPasswordMessage(in zap.In) (string, bool) { + in.Reset() + if in.Type() != AuthenticationResponse { + return "", false + } + password, ok := in.String() + if !ok { + return "", false + } + return password, true +} + +func WritePasswordMessage(out zap.Out, password string) { + out.Reset() + out.Type(AuthenticationResponse) + out.String(password) +} diff --git a/lib/zap/packets/v3.0/readyforquery.go b/lib/zap/packets/v3.0/readyforquery.go new file mode 100644 index 0000000000000000000000000000000000000000..b6d5ea82b71a5f2fd7d8df989e3b75f62a58b98b --- /dev/null +++ b/lib/zap/packets/v3.0/readyforquery.go @@ -0,0 +1,23 @@ +package packets + +import ( + "pggat2/lib/zap" +) + +func ReadReadyForQuery(in zap.In) (byte, bool) { + in.Reset() + if in.Type() != ReadyForQuery { + return 0, false + } + state, ok := in.Uint8() + if !ok { + return 0, false + } + return state, true +} + +func WriteReadyForQuery(out zap.Out, state uint8) { + out.Reset() + out.Type(ReadyForQuery) + out.Uint8(state) +} diff --git a/lib/pnet/packet/packets/v3.0/saslinitialresponse.go b/lib/zap/packets/v3.0/saslinitialresponse.go similarity index 60% rename from lib/pnet/packet/packets/v3.0/saslinitialresponse.go rename to lib/zap/packets/v3.0/saslinitialresponse.go index 75cb65040980d0084de544ed36c2a2c0416e9982..4946f9bebd8b963501ae8d36b93069b9ac5bba35 100644 --- a/lib/pnet/packet/packets/v3.0/saslinitialresponse.go +++ b/lib/zap/packets/v3.0/saslinitialresponse.go @@ -1,10 +1,12 @@ package packets -import "pggat2/lib/pnet/packet" +import ( + "pggat2/lib/zap" +) -func ReadSASLInitialResponse(in packet.In) (mechanism string, initialResponse []byte, ok bool) { +func ReadSASLInitialResponse(in zap.In) (mechanism string, initialResponse []byte, ok bool) { in.Reset() - if in.Type() != packet.AuthenticationResponse { + if in.Type() != AuthenticationResponse { return } @@ -26,9 +28,9 @@ func ReadSASLInitialResponse(in packet.In) (mechanism string, initialResponse [] return } -func WriteSASLInitialResponse(out packet.Out, mechanism string, initialResponse []byte) { +func WriteSASLInitialResponse(out zap.Out, mechanism string, initialResponse []byte) { out.Reset() - out.Type(packet.AuthenticationResponse) + out.Type(AuthenticationResponse) out.String(mechanism) if initialResponse == nil { out.Int32(-1) diff --git a/lib/zap/packets/v3.0/types.go b/lib/zap/packets/v3.0/types.go new file mode 100644 index 0000000000000000000000000000000000000000..68b3740658189194077803a62ce5e3d9e9d545a5 --- /dev/null +++ b/lib/zap/packets/v3.0/types.go @@ -0,0 +1,43 @@ +package packets + +import "pggat2/lib/zap" + +const ( + None zap.Type = 0 + Authentication zap.Type = 'R' + BackendKeyData zap.Type = 'K' + Bind zap.Type = 'B' + BindComplete zap.Type = '2' + Close zap.Type = 'C' + CloseComplete zap.Type = '3' + CommandComplete zap.Type = 'C' + CopyData zap.Type = 'd' + CopyDone zap.Type = 'c' + CopyFail zap.Type = 'f' + CopyInResponse zap.Type = 'G' + CopyOutResponse zap.Type = 'H' + CopyBothResponse zap.Type = 'W' + DataRow zap.Type = 'D' + Describe zap.Type = 'D' + EmptyQueryResponse zap.Type = 'I' + ErrorResponse zap.Type = 'E' + Execute zap.Type = 'E' + Flush zap.Type = 'H' + FunctionCall zap.Type = 'F' + FunctionCallResponse zap.Type = 'V' + AuthenticationResponse zap.Type = 'p' + NegotiateProtocolVersion zap.Type = 'v' + NoData zap.Type = 'n' + NoticeResponse zap.Type = 'N' + NotificationResponse zap.Type = 'A' + ParameterDescription zap.Type = 't' + ParameterStatus zap.Type = 'S' + Parse zap.Type = 'P' + ParseComplete zap.Type = '1' + PortalSuspended zap.Type = 's' + Query zap.Type = 'Q' + ReadyForQuery zap.Type = 'Z' + RowDescription zap.Type = 'T' + Sync zap.Type = 'S' + Terminate zap.Type = 'X' +) diff --git a/lib/zap/reader.go b/lib/zap/reader.go new file mode 100644 index 0000000000000000000000000000000000000000..aa4f149623f0546bed8bf70f83426039669e7a02 --- /dev/null +++ b/lib/zap/reader.go @@ -0,0 +1,10 @@ +package zap + +import "io" + +type Reader interface { + io.ByteReader + + Read() (In, error) + ReadUntyped() (In, error) +} diff --git a/lib/pnet/readwriter.go b/lib/zap/readwriter.go similarity index 78% rename from lib/pnet/readwriter.go rename to lib/zap/readwriter.go index 81d125660a867ab52c11808e17355925925ed053..22b2a309250d2e694b5a5c9ef842a57780499e85 100644 --- a/lib/pnet/readwriter.go +++ b/lib/zap/readwriter.go @@ -1,4 +1,4 @@ -package pnet +package zap type ReadWriter interface { Reader diff --git a/lib/zap/regender.go b/lib/zap/regender.go new file mode 100644 index 0000000000000000000000000000000000000000..9adb2ee7a3471c1b00320be04f6d750b93c28e7c --- /dev/null +++ b/lib/zap/regender.go @@ -0,0 +1,15 @@ +package zap + +func InToOut(in In) Out { + return Out{ + buf: in.buf, + rev: in.rev, + } +} + +func OutToIn(out Out) In { + return In{ + buf: out.buf, + rev: out.rev, + } +} diff --git a/lib/zap/type.go b/lib/zap/type.go new file mode 100644 index 0000000000000000000000000000000000000000..e26e5d617631afcbe8116694f1b01d219c8862cb --- /dev/null +++ b/lib/zap/type.go @@ -0,0 +1,3 @@ +package zap + +type Type byte diff --git a/lib/zap/writer.go b/lib/zap/writer.go new file mode 100644 index 0000000000000000000000000000000000000000..90e9354e4b0d2c255b661a943c25052fbf977c31 --- /dev/null +++ b/lib/zap/writer.go @@ -0,0 +1,10 @@ +package zap + +import "io" + +type Writer interface { + io.ByteWriter + + Write() Out + Send(Out) error +} diff --git a/lib/zap/zio/reader.go b/lib/zap/zio/reader.go new file mode 100644 index 0000000000000000000000000000000000000000..0cd39047df35a6c505e417d46adead69ef311c82 --- /dev/null +++ b/lib/zap/zio/reader.go @@ -0,0 +1,32 @@ +package zio + +import ( + "io" + + "pggat2/lib/zap" +) + +type Reader struct { + reader io.Reader + buf zap.Buf +} + +func MakeReader(reader io.Reader) Reader { + return Reader{ + reader: reader, + } +} + +func (T *Reader) ReadByte() (byte, error) { + return T.buf.ReadByte(T.reader) +} + +func (T *Reader) Read() (zap.In, error) { + return T.buf.Read(T.reader, true) +} + +func (T *Reader) ReadUntyped() (zap.In, error) { + return T.buf.Read(T.reader, false) +} + +var _ zap.Reader = (*Reader)(nil) diff --git a/lib/zap/zio/readwriter.go b/lib/zap/zio/readwriter.go new file mode 100644 index 0000000000000000000000000000000000000000..3a4d853de71a71b0b445b8ca421b78d06053286f --- /dev/null +++ b/lib/zap/zio/readwriter.go @@ -0,0 +1,45 @@ +package zio + +import ( + "io" + + "pggat2/lib/zap" +) + +type ReadWriter struct { + rw io.ReadWriter + buf zap.Buf +} + +func MakeReadWriter(rw io.ReadWriter) ReadWriter { + return ReadWriter{ + rw: rw, + } +} + +func (T *ReadWriter) ReadByte() (byte, error) { + return T.buf.ReadByte(T.rw) +} + +func (T *ReadWriter) Read() (zap.In, error) { + return T.buf.Read(T.rw, true) +} + +func (T *ReadWriter) ReadUntyped() (zap.In, error) { + return T.buf.Read(T.rw, false) +} + +func (T *ReadWriter) WriteByte(b byte) error { + return T.buf.WriteByte(T.rw, b) +} + +func (T *ReadWriter) Write() zap.Out { + return T.buf.Write() +} + +func (T *ReadWriter) Send(out zap.Out) error { + _, err := T.rw.Write(out.Full()) + return err +} + +var _ zap.ReadWriter = (*ReadWriter)(nil) diff --git a/lib/zap/zio/writer.go b/lib/zap/zio/writer.go new file mode 100644 index 0000000000000000000000000000000000000000..8b5c7a3e5b4f663362db1b62b33c1c1b711969bc --- /dev/null +++ b/lib/zap/zio/writer.go @@ -0,0 +1,33 @@ +package zio + +import ( + "io" + + "pggat2/lib/zap" +) + +type Writer struct { + writer io.Writer + buf zap.Buf +} + +func MakeWriter(writer io.Writer) Writer { + return Writer{ + writer: writer, + } +} + +func (T *Writer) WriteByte(b byte) error { + return T.buf.WriteByte(T.writer, b) +} + +func (T *Writer) Write() zap.Out { + return T.buf.Write() +} + +func (T *Writer) Send(out zap.Out) error { + _, err := T.writer.Write(out.Full()) + return err +} + +var _ zap.Writer = (*Writer)(nil)