Support chat validation
This commit is contained in:
@ -1,47 +0,0 @@
|
|||||||
package msg
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/Tnze/go-mc/chat/sign"
|
|
||||||
)
|
|
||||||
|
|
||||||
type signatureCache struct {
|
|
||||||
signatures [128]*sign.Signature
|
|
||||||
signIndexes map[sign.Signature]int
|
|
||||||
cachedBuffer []*sign.Signature
|
|
||||||
}
|
|
||||||
|
|
||||||
func newSignatureCache() signatureCache {
|
|
||||||
return signatureCache{
|
|
||||||
signIndexes: make(map[sign.Signature]int),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *signatureCache) popOrInsert(self *sign.Signature, lastSeen []sign.PackedSignature) error {
|
|
||||||
var tmp *sign.Signature
|
|
||||||
s.cachedBuffer = s.cachedBuffer[:0] // clear buffer
|
|
||||||
if self != nil {
|
|
||||||
s.cachedBuffer = append(s.cachedBuffer, self)
|
|
||||||
}
|
|
||||||
for _, v := range lastSeen {
|
|
||||||
if v.Signature != nil {
|
|
||||||
s.cachedBuffer = append(s.cachedBuffer, v.Signature)
|
|
||||||
} else if v.ID >= 0 && int(v.ID) < len(s.signatures) {
|
|
||||||
s.cachedBuffer = append(s.cachedBuffer, s.signatures[v.ID])
|
|
||||||
} else {
|
|
||||||
return InvalidChatPacket
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := 0; i < len(s.cachedBuffer) && i < len(s.signatures); i++ {
|
|
||||||
v := s.cachedBuffer[i]
|
|
||||||
if i, ok := s.signIndexes[*v]; ok {
|
|
||||||
s.signatures[i] = nil
|
|
||||||
}
|
|
||||||
tmp, s.signatures[i] = s.signatures[i], v
|
|
||||||
s.signIndexes[*v] = i
|
|
||||||
if tmp != nil {
|
|
||||||
s.cachedBuffer = append(s.cachedBuffer, tmp)
|
|
||||||
delete(s.signIndexes, *tmp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
135
bot/msg/chat.go
135
bot/msg/chat.go
@ -4,9 +4,10 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
|
||||||
"github.com/Tnze/go-mc/bot"
|
"github.com/Tnze/go-mc/bot"
|
||||||
"github.com/Tnze/go-mc/bot/basic"
|
"github.com/Tnze/go-mc/bot/basic"
|
||||||
"github.com/Tnze/go-mc/bot/playerlist"
|
"github.com/Tnze/go-mc/bot/playerlist"
|
||||||
@ -17,11 +18,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
c *bot.Client
|
c *bot.Client
|
||||||
p *basic.Player
|
p *basic.Player
|
||||||
pl *playerlist.PlayerList
|
pl *playerlist.PlayerList
|
||||||
|
events EventsHandler
|
||||||
|
|
||||||
signatureCache
|
sign.SignatureCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(c *bot.Client, p *basic.Player, pl *playerlist.PlayerList, events EventsHandler) *Manager {
|
func New(c *bot.Client, p *basic.Player, pl *playerlist.PlayerList, events EventsHandler) *Manager {
|
||||||
@ -29,58 +31,86 @@ func New(c *bot.Client, p *basic.Player, pl *playerlist.PlayerList, events Event
|
|||||||
c: c,
|
c: c,
|
||||||
p: p,
|
p: p,
|
||||||
pl: pl,
|
pl: pl,
|
||||||
signatureCache: newSignatureCache(),
|
events: events,
|
||||||
|
SignatureCache: sign.NewSignatureCache(),
|
||||||
}
|
}
|
||||||
m.attachPlayerMsg(c, p, pl, events.PlayerChatMessage)
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Manager) attachPlayerMsg(c *bot.Client, p *basic.Player, pl *playerlist.PlayerList, handler func(msg chat.Message) error) {
|
|
||||||
c.Events.AddListener(
|
c.Events.AddListener(
|
||||||
bot.PacketHandler{
|
bot.PacketHandler{
|
||||||
Priority: 64, ID: packetid.ClientboundPlayerChat,
|
Priority: 64, ID: packetid.ClientboundPlayerChat,
|
||||||
F: func(packet pk.Packet) error {
|
F: m.handlePacket,
|
||||||
var (
|
},
|
||||||
sender pk.UUID
|
)
|
||||||
index pk.VarInt
|
return m
|
||||||
signature pk.Option[sign.Signature, *sign.Signature]
|
}
|
||||||
body sign.PackedMessageBody
|
|
||||||
unsignedContent pk.Option[chat.Message, *chat.Message]
|
|
||||||
filter sign.FilterMask
|
|
||||||
chatType chat.Type
|
|
||||||
)
|
|
||||||
if err := packet.Scan(&sender, &index, &signature, &body, &unsignedContent, &filter, &chatType); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
//senderInfo, ok := pl.PlayerInfos[uuid.UUID(sender)]
|
func (m *Manager) handlePacket(packet pk.Packet) error {
|
||||||
//if !ok {
|
var (
|
||||||
// return bot.DisconnectErr(chat.TranslateMsg("multiplayer.disconnect.chat_validation_failed"))
|
sender pk.UUID
|
||||||
//}
|
index pk.VarInt
|
||||||
//senderInfo.ChatSession.Update()
|
signature pk.Option[sign.Signature, *sign.Signature]
|
||||||
//if err := senderInfo.ChatSession.Validate(); err != nil {
|
body sign.PackedMessageBody
|
||||||
// return bot.DisconnectErr(chat.TranslateMsg("multiplayer.disconnect.chat_validation_failed"))
|
unsignedContent pk.Option[chat.Message, *chat.Message]
|
||||||
//}
|
filter sign.FilterMask
|
||||||
// store signature into signatureCache
|
chatType chat.Type
|
||||||
//if err := m.popOrInsert(signature.Pointer(), body.LastSeen); err != nil {
|
)
|
||||||
// return err
|
if err := packet.Scan(&sender, &index, &signature, &body, &unsignedContent, &filter, &chatType); err != nil {
|
||||||
//}
|
return err
|
||||||
var content chat.Message
|
}
|
||||||
if unsignedContent.Has {
|
|
||||||
content = unsignedContent.Val
|
|
||||||
} else {
|
|
||||||
content = chat.Text(body.PlainMsg)
|
|
||||||
}
|
|
||||||
|
|
||||||
ct := p.WorldInfo.RegistryCodec.ChatType.FindByID(chatType.ID)
|
unpackedMsg, err := body.Unpack(&m.SignatureCache)
|
||||||
if ct == nil {
|
if err != nil {
|
||||||
return fmt.Errorf("chat type %d not found", chatType.ID)
|
return InvalidChatPacket
|
||||||
}
|
}
|
||||||
|
senderInfo, ok := m.pl.PlayerInfos[uuid.UUID(sender)]
|
||||||
|
if !ok {
|
||||||
|
return InvalidChatPacket
|
||||||
|
}
|
||||||
|
ct := m.p.WorldInfo.RegistryCodec.ChatType.FindByID(chatType.ID)
|
||||||
|
if ct == nil {
|
||||||
|
return InvalidChatPacket
|
||||||
|
}
|
||||||
|
|
||||||
msg := chatType.Decorate(content, &ct.Chat)
|
var message sign.Message
|
||||||
return handler(msg)
|
if senderInfo.ChatSession != nil {
|
||||||
},
|
message.Prev = sign.Prev{
|
||||||
})
|
Index: int(index),
|
||||||
|
Sender: uuid.UUID(sender),
|
||||||
|
Session: senderInfo.ChatSession.SessionID,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.Prev = sign.Prev{
|
||||||
|
Index: 0,
|
||||||
|
Sender: uuid.UUID(sender),
|
||||||
|
Session: uuid.Nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
message.Signature = signature.Pointer()
|
||||||
|
message.MessageBody = unpackedMsg
|
||||||
|
message.Unsigned = unsignedContent.Pointer()
|
||||||
|
message.FilterMask = filter
|
||||||
|
|
||||||
|
var validated bool
|
||||||
|
if senderInfo.ChatSession != nil {
|
||||||
|
if !senderInfo.ChatSession.VerifyAndUpdate(&message) {
|
||||||
|
return ValidationFailed
|
||||||
|
}
|
||||||
|
validated = true
|
||||||
|
// store signature into signatureCache
|
||||||
|
m.PopOrInsert(signature.Pointer(), message.LastSeen)
|
||||||
|
}
|
||||||
|
|
||||||
|
var content chat.Message
|
||||||
|
if unsignedContent.Has {
|
||||||
|
content = unsignedContent.Val
|
||||||
|
} else {
|
||||||
|
content = chat.Text(body.PlainMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.events.PlayerChatMessage == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
msg := chatType.Decorate(content, &ct.Chat)
|
||||||
|
return m.events.PlayerChatMessage(msg, validated)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendMessage send chat message to server.
|
// SendMessage send chat message to server.
|
||||||
@ -108,4 +138,7 @@ func (m *Manager) SendMessage(msg string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var InvalidChatPacket = errors.New("invalid chat packet")
|
var (
|
||||||
|
InvalidChatPacket = errors.New("invalid chat packet")
|
||||||
|
ValidationFailed error = bot.DisconnectErr(chat.TranslateMsg("multiplayer.disconnect.chat_validation_failed"))
|
||||||
|
)
|
||||||
|
@ -3,5 +3,5 @@ package msg
|
|||||||
import "github.com/Tnze/go-mc/chat"
|
import "github.com/Tnze/go-mc/chat"
|
||||||
|
|
||||||
type EventsHandler struct {
|
type EventsHandler struct {
|
||||||
PlayerChatMessage func(msg chat.Message) error
|
PlayerChatMessage func(msg chat.Message, validated bool) error
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,12 @@ func (pl *PlayerList) handlePlayerInfoUpdatePacket(p pk.Packet) error {
|
|||||||
if _, err := chatSession.ReadFrom(r); err != nil {
|
if _, err := chatSession.ReadFrom(r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
player.ChatSession = chatSession.Pointer()
|
if chatSession.Has {
|
||||||
|
player.ChatSession = chatSession.Pointer()
|
||||||
|
player.ChatSession.InitValidate()
|
||||||
|
} else {
|
||||||
|
player.ChatSession = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// update gamemode
|
// update gamemode
|
||||||
if action.Get(2) {
|
if action.Get(2) {
|
||||||
|
42
chat/sign/cache.go
Normal file
42
chat/sign/cache.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package sign
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SignatureCache struct {
|
||||||
|
signatures [128]*Signature
|
||||||
|
signIndexes map[Signature]int
|
||||||
|
cachedBuffer []*Signature
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSignatureCache() SignatureCache {
|
||||||
|
return SignatureCache{
|
||||||
|
signIndexes: make(map[Signature]int),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SignatureCache) PopOrInsert(self *Signature, lastSeen []*Signature) {
|
||||||
|
var tmp *Signature
|
||||||
|
s.cachedBuffer = s.cachedBuffer[:0] // clear buffer
|
||||||
|
if self != nil {
|
||||||
|
s.cachedBuffer = append(s.cachedBuffer, self)
|
||||||
|
}
|
||||||
|
for _, v := range lastSeen {
|
||||||
|
s.cachedBuffer = append(s.cachedBuffer, v)
|
||||||
|
}
|
||||||
|
for i := 0; i < len(s.cachedBuffer) && i < len(s.signatures); i++ {
|
||||||
|
v := s.cachedBuffer[i]
|
||||||
|
if i, ok := s.signIndexes[*v]; ok {
|
||||||
|
s.signatures[i] = nil
|
||||||
|
}
|
||||||
|
tmp, s.signatures[i] = s.signatures[i], v
|
||||||
|
s.signIndexes[*v] = i
|
||||||
|
if tmp != nil {
|
||||||
|
s.cachedBuffer = append(s.cachedBuffer, tmp)
|
||||||
|
delete(s.signIndexes, *tmp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var UncachedSignature = errors.New("uncached signature")
|
@ -1,36 +1,24 @@
|
|||||||
package msg
|
package sign
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/Tnze/go-mc/chat/sign"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSignatureCache(t *testing.T) {
|
func TestSignatureCache(t *testing.T) {
|
||||||
cache := newSignatureCache()
|
cache := NewSignatureCache()
|
||||||
s1 := &sign.Signature{1}
|
s1 := &Signature{1}
|
||||||
s2 := &sign.Signature{2}
|
s2 := &Signature{2}
|
||||||
s3 := &sign.Signature{3}
|
s3 := &Signature{3}
|
||||||
s4 := &sign.Signature{4}
|
s4 := &Signature{4}
|
||||||
// t.Logf("%p, %p, %p, %p", s1, s2, s3, s4)
|
// t.Logf("%p, %p, %p, %p", s1, s2, s3, s4)
|
||||||
err := cache.popOrInsert(nil, []sign.PackedSignature{
|
cache.PopOrInsert(nil, []*Signature{s1, s2, s3})
|
||||||
{Signature: s1},
|
|
||||||
{Signature: s2},
|
|
||||||
{Signature: s3},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
// cache: [s1, s2, s3, nil...]
|
// cache: [s1, s2, s3, nil...]
|
||||||
if cache.signatures[0] != s1 || cache.signatures[1] != s2 || cache.signatures[2] != s3 {
|
if cache.signatures[0] != s1 || cache.signatures[1] != s2 || cache.signatures[2] != s3 {
|
||||||
t.Log(cache.signatures)
|
t.Log(cache.signatures)
|
||||||
t.Fatal("insert s1~3 error")
|
t.Fatal("insert s1~3 error")
|
||||||
}
|
}
|
||||||
err = cache.popOrInsert(s4, []sign.PackedSignature{{Signature: s3}})
|
cache.PopOrInsert(s4, []*Signature{s3})
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
// cache: [s4, s3, s1, s2, nil...]
|
// cache: [s4, s3, s1, s2, nil...]
|
||||||
if cache.signatures[0] != s4 {
|
if cache.signatures[0] != s4 {
|
||||||
t.Log(cache.signatures)
|
t.Log(cache.signatures)
|
||||||
@ -47,36 +35,29 @@ func TestSignatureCache(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSignatureCache_2(t *testing.T) {
|
func TestSignatureCache_2(t *testing.T) {
|
||||||
cache := newSignatureCache()
|
cache := NewSignatureCache()
|
||||||
signs := make([]sign.PackedSignature, len(cache.signatures)+5)
|
signs := make([]*Signature, len(cache.signatures)+5)
|
||||||
for i := range signs {
|
for i := range signs {
|
||||||
newSign := new(sign.Signature)
|
signs[i] = new(Signature)
|
||||||
_, _ = rand.Read(newSign[:])
|
_, _ = rand.Read(signs[i][:])
|
||||||
signs[i] = sign.PackedSignature{Signature: newSign}
|
|
||||||
}
|
}
|
||||||
err := cache.popOrInsert(nil, signs[:len(cache.signatures)])
|
cache.PopOrInsert(nil, signs[:len(cache.signatures)])
|
||||||
if !signatureEquals(cache.signatures[:], signs[:len(cache.signatures)]) {
|
if !signatureEquals(cache.signatures[:], signs[:len(cache.signatures)]) {
|
||||||
t.Fatal("insert error")
|
t.Fatal("insert error")
|
||||||
}
|
}
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
insert2 := signs[len(cache.signatures)-5:]
|
insert2 := signs[len(cache.signatures)-5:]
|
||||||
err = cache.popOrInsert(nil, insert2)
|
cache.PopOrInsert(nil, insert2)
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if !signatureEquals(cache.signatures[:10], insert2) {
|
if !signatureEquals(cache.signatures[:10], insert2) {
|
||||||
t.Fatal("insert and pop error")
|
t.Fatal("insert and pop error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func signatureEquals(a []*sign.Signature, b []sign.PackedSignature) bool {
|
func signatureEquals(a, b []*Signature) bool {
|
||||||
if len(a) != len(b) {
|
if len(a) != len(b) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for i := range a {
|
for i := range a {
|
||||||
if a[i] != b[i].Signature {
|
if a[i] != b[i] {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package sign
|
package sign
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/binary"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
@ -11,40 +13,81 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Message struct {
|
type Message struct {
|
||||||
Link struct {
|
Prev Prev
|
||||||
Index int
|
Signature *Signature
|
||||||
Sender uuid.UUID
|
*MessageBody
|
||||||
Session uuid.UUID
|
|
||||||
}
|
|
||||||
Signature []byte
|
|
||||||
PackedMessageBody
|
|
||||||
Unsigned *chat.Message
|
Unsigned *chat.Message
|
||||||
FilterMask
|
FilterMask
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Prev struct {
|
||||||
|
Index int
|
||||||
|
Sender uuid.UUID
|
||||||
|
Session uuid.UUID
|
||||||
|
}
|
||||||
|
|
||||||
type Session struct {
|
type Session struct {
|
||||||
sessionID uuid.UUID
|
SessionID uuid.UUID
|
||||||
publicKey user.PublicKey
|
PublicKey user.PublicKey
|
||||||
|
|
||||||
|
valid bool
|
||||||
|
lastMsg *Message
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Session) WriteTo(w io.Writer) (n int64, err error) {
|
func (s Session) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
n1, err := pk.UUID(s.sessionID).WriteTo(w)
|
n1, err := pk.UUID(s.SessionID).WriteTo(w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n1, err
|
return n1, err
|
||||||
}
|
}
|
||||||
n2, err := s.publicKey.WriteTo(w)
|
n2, err := s.PublicKey.WriteTo(w)
|
||||||
return n1 + n2, err
|
return n1 + n2, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Session) ReadFrom(r io.Reader) (n int64, err error) {
|
func (s *Session) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
n1, err := ((*pk.UUID)(&s.sessionID)).ReadFrom(r)
|
n1, err := ((*pk.UUID)(&s.SessionID)).ReadFrom(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n1, err
|
return n1, err
|
||||||
}
|
}
|
||||||
n2, err := s.publicKey.ReadFrom(r)
|
n2, err := s.PublicKey.ReadFrom(r)
|
||||||
return n1 + n2, err
|
return n1 + n2, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Session) Update(msg Message) bool {
|
func (s *Session) InitValidate() {
|
||||||
panic("todo")
|
s.valid = true
|
||||||
|
s.lastMsg = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Session) VerifyAndUpdate(msg *Message) bool {
|
||||||
|
s.valid = s.valid && s.verifyHash(msg) && s.verifyChain(msg)
|
||||||
|
if s.valid {
|
||||||
|
s.lastMsg = msg
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Session) verifyHash(msg *Message) bool {
|
||||||
|
h := sha256.New()
|
||||||
|
// 1
|
||||||
|
_ = binary.Write(h, binary.BigEndian, int32(1))
|
||||||
|
// Prev
|
||||||
|
_, _ = h.Write(msg.Prev.Sender[:])
|
||||||
|
_, _ = h.Write(msg.Prev.Session[:])
|
||||||
|
_ = binary.Write(h, binary.BigEndian, msg.Prev.Index)
|
||||||
|
// Body
|
||||||
|
_ = binary.Write(h, binary.BigEndian, msg.Salt)
|
||||||
|
_ = binary.Write(h, binary.BigEndian, msg.Timestamp.Unix())
|
||||||
|
content := []byte(msg.PlainMsg)
|
||||||
|
_ = binary.Write(h, binary.BigEndian, int32(len(content)))
|
||||||
|
_, _ = h.Write(content)
|
||||||
|
// Body.LastSeen
|
||||||
|
_ = binary.Write(h, binary.BigEndian, int32(len(msg.LastSeen)))
|
||||||
|
for _, v := range msg.LastSeen {
|
||||||
|
_, _ = h.Write((*v)[:])
|
||||||
|
}
|
||||||
|
return s.PublicKey.VerifyMessage(h.Sum(nil), msg.Signature[:]) == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Session) verifyChain(msg *Message) bool {
|
||||||
|
return s.lastMsg != nil && (msg.Prev.Index < s.lastMsg.Prev.Index || msg.Prev.Sender != s.lastMsg.Prev.Sender || msg.Prev.Session != s.lastMsg.Prev.Session)
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,13 @@ import (
|
|||||||
pk "github.com/Tnze/go-mc/net/packet"
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type MessageBody struct {
|
||||||
|
PlainMsg string
|
||||||
|
Timestamp time.Time
|
||||||
|
Salt int64
|
||||||
|
LastSeen []*Signature
|
||||||
|
}
|
||||||
|
|
||||||
type PackedMessageBody struct {
|
type PackedMessageBody struct {
|
||||||
PlainMsg string
|
PlainMsg string
|
||||||
Timestamp time.Time
|
Timestamp time.Time
|
||||||
@ -37,6 +44,25 @@ func (m *PackedMessageBody) ReadFrom(r io.Reader) (n int64, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *PackedMessageBody) Unpack(cache *SignatureCache) (*MessageBody, error) {
|
||||||
|
LastSeen := make([]*Signature, len(m.LastSeen))
|
||||||
|
for i, v := range m.LastSeen {
|
||||||
|
if v.Signature != nil {
|
||||||
|
LastSeen[i] = v.Signature
|
||||||
|
} else if v.ID >= 0 && int(v.ID) < len(cache.signatures) {
|
||||||
|
LastSeen[i] = cache.signatures[v.ID]
|
||||||
|
} else {
|
||||||
|
return nil, UncachedSignature
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &MessageBody{
|
||||||
|
PlainMsg: m.PlainMsg,
|
||||||
|
Timestamp: m.Timestamp,
|
||||||
|
Salt: m.Salt,
|
||||||
|
LastSeen: LastSeen,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
type HistoryMessage struct {
|
type HistoryMessage struct {
|
||||||
Sender uuid.UUID
|
Sender uuid.UUID
|
||||||
Signature []byte
|
Signature []byte
|
||||||
|
@ -116,8 +116,12 @@ func onGameStart() error {
|
|||||||
return nil // if err isn't nil, HandleGame() will return it.
|
return nil // if err isn't nil, HandleGame() will return it.
|
||||||
}
|
}
|
||||||
|
|
||||||
func onPlayerMsg(msg chat.Message) error {
|
func onPlayerMsg(msg chat.Message, validated bool) error {
|
||||||
log.Printf("Player: %v", msg)
|
var prefix string
|
||||||
|
if !validated {
|
||||||
|
prefix = "[Not Secure] "
|
||||||
|
}
|
||||||
|
log.Printf("%sPlayer: %v", prefix, msg)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user