feat(go): Port full Ananta private server to Go architecture
This commit is contained in:
1 parent
ca2e80f9b7
commit
c73d744649
28 files changed
+3585
-57
No files matched your search
@@ -0,0 +1,132 @@
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"ananta-ps/pkg/crypto/chacha8"
|
||||
)
|
||||
|
||||
type Frame struct {
|
||||
Mode byte
|
||||
Payload []byte
|
||||
}
|
||||
|
||||
func ReadFrame(r io.Reader, cryptor *chacha8.UxChaCha8) (*Frame, error) {
|
||||
head := make([]byte, 5)
|
||||
if _, err := io.ReadFull(r, head); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cryptor != nil {
|
||||
cryptor.XorInPlace(head)
|
||||
}
|
||||
|
||||
payloadLength := int(binary.LittleEndian.Uint32(head[0:4]))
|
||||
if payloadLength < 0 || payloadLength > 16*1024*1024 {
|
||||
return nil, errors.New("invalid frame payload length after decrypt")
|
||||
}
|
||||
|
||||
payload := make([]byte, payloadLength)
|
||||
if payloadLength > 0 {
|
||||
if _, err := io.ReadFull(r, payload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cryptor != nil {
|
||||
cryptor.XorInPlace(payload)
|
||||
}
|
||||
}
|
||||
|
||||
return &Frame{
|
||||
Mode: head[4],
|
||||
Payload: payload,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func WriteFrame(w io.Writer, mode byte, payload []byte, cryptor *chacha8.UxChaCha8) error {
|
||||
buf := make([]byte, 5+len(payload))
|
||||
binary.LittleEndian.PutUint32(buf[0:4], uint32(len(payload)))
|
||||
buf[4] = mode
|
||||
copy(buf[5:], payload)
|
||||
|
||||
if cryptor != nil {
|
||||
cryptor.XorInPlace(buf)
|
||||
}
|
||||
|
||||
_, err := w.Write(buf)
|
||||
return err
|
||||
}
|
||||
|
||||
func ParseRpcPacket(payload []byte) RpcPacket {
|
||||
if len(payload) < 5 {
|
||||
return RpcPacket{Kind: PacketKindUnknown, Body: payload}
|
||||
}
|
||||
|
||||
tag := payload[0]
|
||||
methodID := binary.LittleEndian.Uint32(payload[1:5])
|
||||
|
||||
switch tag {
|
||||
case 0x03: // Notify
|
||||
return RpcPacket{
|
||||
Kind: PacketKindNotify,
|
||||
MethodID: methodID,
|
||||
Body: payload[5:],
|
||||
}
|
||||
case 0x01: // Invoke
|
||||
if len(payload) >= 9 {
|
||||
invokeID := int32(binary.LittleEndian.Uint32(payload[5:9]))
|
||||
return RpcPacket{
|
||||
Kind: PacketKindInvoke,
|
||||
MethodID: methodID,
|
||||
InvokeID: invokeID,
|
||||
Body: payload[9:],
|
||||
}
|
||||
}
|
||||
case 0x02: // Return
|
||||
if len(payload) >= 13 {
|
||||
invokeID := int32(binary.LittleEndian.Uint32(payload[5:9]))
|
||||
errCode := int32(binary.LittleEndian.Uint32(payload[9:13]))
|
||||
return RpcPacket{
|
||||
Kind: PacketKindReturn,
|
||||
MethodID: methodID,
|
||||
InvokeID: invokeID,
|
||||
Error: errCode,
|
||||
Body: payload[13:],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return RpcPacket{
|
||||
Kind: PacketKindUnknown,
|
||||
MethodID: methodID,
|
||||
Body: payload,
|
||||
}
|
||||
}
|
||||
|
||||
func BuildNotify(methodID uint32, body []byte) []byte {
|
||||
buf := make([]byte, 5+len(body))
|
||||
buf[0] = 0x03
|
||||
binary.LittleEndian.PutUint32(buf[1:5], methodID)
|
||||
copy(buf[5:], body)
|
||||
return buf
|
||||
}
|
||||
|
||||
func BuildInvoke(methodID uint32, invokeID int32, body []byte) []byte {
|
||||
buf := make([]byte, 9+len(body))
|
||||
buf[0] = 0x01
|
||||
binary.LittleEndian.PutUint32(buf[1:5], methodID)
|
||||
binary.LittleEndian.PutUint32(buf[5:9], uint32(invokeID))
|
||||
copy(buf[9:], body)
|
||||
return buf
|
||||
}
|
||||
|
||||
func BuildReturn(methodID uint32, invokeID int32, errCode int32, body []byte) []byte {
|
||||
buf := make([]byte, 13+len(body))
|
||||
buf[0] = 0x02
|
||||
binary.LittleEndian.PutUint32(buf[1:5], methodID)
|
||||
binary.LittleEndian.PutUint32(buf[5:9], uint32(invokeID))
|
||||
binary.LittleEndian.PutUint32(buf[9:13], uint32(errCode))
|
||||
copy(buf[13:], body)
|
||||
return buf
|
||||
}
|
||||
Reference in new issue
Block a user