refactor packet sending functions

This commit is contained in:
wish
2024-10-10 22:27:12 +11:00
parent 62fe5cf277
commit 830834c5b5
7 changed files with 38 additions and 140 deletions

View File

@@ -4,7 +4,6 @@ import (
"crypto/rand" "crypto/rand"
"encoding/hex" "encoding/hex"
_config "erupe-ce/config" _config "erupe-ce/config"
"erupe-ce/network"
"erupe-ce/network/binpacket" "erupe-ce/network/binpacket"
"erupe-ce/network/mhfpacket" "erupe-ce/network/mhfpacket"
"erupe-ce/utils/byteframe" "erupe-ce/utils/byteframe"
@@ -181,41 +180,33 @@ func parseChatCommand(s *Session, command string) {
if commands["Reload"].Enabled || s.isOp() { if commands["Reload"].Enabled || s.isOp() {
sendServerChatMessage(s, s.server.i18n.commands.reload) sendServerChatMessage(s, s.server.i18n.commands.reload)
var temp mhfpacket.MHFPacket var temp mhfpacket.MHFPacket
deleteNotif := byteframe.NewByteFrame()
for _, object := range s.stage.objects { for _, object := range s.stage.objects {
if object.ownerCharID == s.charID { if object.ownerCharID == s.charID {
continue continue
} }
temp = &mhfpacket.MsgSysDeleteObject{ObjID: object.id} temp = &mhfpacket.MsgSysDeleteObject{ObjID: object.id}
deleteNotif.WriteUint16(uint16(temp.Opcode())) s.QueueSendMHF(temp)
temp.Build(deleteNotif)
} }
for _, session := range s.server.sessions { for _, session := range s.server.sessions {
if s == session { if s == session {
continue continue
} }
temp = &mhfpacket.MsgSysDeleteUser{CharID: session.charID} temp = &mhfpacket.MsgSysDeleteUser{CharID: session.charID}
deleteNotif.WriteUint16(uint16(temp.Opcode())) s.QueueSendMHF(temp)
temp.Build(deleteNotif)
} }
deleteNotif.WriteUint16(uint16(network.MSG_SYS_END))
s.QueueSend(deleteNotif.Data())
time.Sleep(500 * time.Millisecond) time.Sleep(500 * time.Millisecond)
reloadNotif := byteframe.NewByteFrame()
for _, session := range s.server.sessions { for _, session := range s.server.sessions {
if s == session { if s == session {
continue continue
} }
temp = &mhfpacket.MsgSysInsertUser{CharID: session.charID} temp = &mhfpacket.MsgSysInsertUser{CharID: session.charID}
reloadNotif.WriteUint16(uint16(temp.Opcode())) s.QueueSendMHF(temp)
temp.Build(reloadNotif)
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
temp = &mhfpacket.MsgSysNotifyUserBinary{ temp = &mhfpacket.MsgSysNotifyUserBinary{
CharID: session.charID, CharID: session.charID,
BinaryType: uint8(i + 1), BinaryType: uint8(i + 1),
} }
reloadNotif.WriteUint16(uint16(temp.Opcode())) s.QueueSendMHF(temp)
temp.Build(reloadNotif)
} }
} }
for _, obj := range s.stage.objects { for _, obj := range s.stage.objects {
@@ -230,11 +221,8 @@ func parseChatCommand(s *Session, command string) {
Unk0: 0, Unk0: 0,
OwnerCharID: obj.ownerCharID, OwnerCharID: obj.ownerCharID,
} }
reloadNotif.WriteUint16(uint16(temp.Opcode())) s.QueueSendMHF(temp)
temp.Build(reloadNotif)
} }
reloadNotif.WriteUint16(uint16(network.MSG_SYS_END))
s.QueueSend(reloadNotif.Data())
} else { } else {
sendDisabledCommandMessage(s, commands["Reload"]) sendDisabledCommandMessage(s, commands["Reload"])
} }

View File

@@ -116,25 +116,17 @@ func (s *Session) notifyRavi() {
return return
} }
var temp mhfpacket.MHFPacket var temp mhfpacket.MHFPacket
raviNotif := byteframe.NewByteFrame() for i := 0; i < 3; i++ {
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 0x40000} temp = &mhfpacket.MsgSysLoadRegister{RegisterID: uint32(0x40000 + i*0x10000)}
raviNotif.WriteUint16(uint16(temp.Opcode())) if s.server.erupeConfig.GameplayOptions.LowLatencyRaviente {
temp.Build(raviNotif) for session := range sema.clients {
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 0x50000} session.QueueSendMHF(temp)
raviNotif.WriteUint16(uint16(temp.Opcode())) }
temp.Build(raviNotif) } else {
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 0x60000} for session := range sema.clients {
raviNotif.WriteUint16(uint16(temp.Opcode())) if session.charID == s.charID {
temp.Build(raviNotif) session.QueueSendMHF(temp)
raviNotif.WriteUint16(0x0010) // End it. }
if s.server.erupeConfig.GameplayOptions.LowLatencyRaviente {
for session := range sema.clients {
session.QueueSend(raviNotif.Data())
}
} else {
for session := range sema.clients {
if session.charID == s.charID {
session.QueueSend(raviNotif.Data())
} }
} }
} }

View File

@@ -66,7 +66,6 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
doAckSimpleSucceed(s, ackHandle, []byte{0x00, 0x00, 0x00, 0x00}) doAckSimpleSucceed(s, ackHandle, []byte{0x00, 0x00, 0x00, 0x00})
var temp mhfpacket.MHFPacket var temp mhfpacket.MHFPacket
newNotif := byteframe.NewByteFrame()
// Cast existing user data to new user // Cast existing user data to new user
if !s.userEnteredStage { if !s.userEnteredStage {
@@ -77,15 +76,13 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
continue continue
} }
temp = &mhfpacket.MsgSysInsertUser{CharID: session.charID} temp = &mhfpacket.MsgSysInsertUser{CharID: session.charID}
newNotif.WriteUint16(uint16(temp.Opcode())) s.QueueSendMHF(temp)
temp.Build(newNotif)
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
temp = &mhfpacket.MsgSysNotifyUserBinary{ temp = &mhfpacket.MsgSysNotifyUserBinary{
CharID: session.charID, CharID: session.charID,
BinaryType: uint8(i + 1), BinaryType: uint8(i + 1),
} }
newNotif.WriteUint16(uint16(temp.Opcode())) s.QueueSendMHF(temp)
temp.Build(newNotif)
} }
} }
} }
@@ -94,7 +91,6 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
// Notify the client to duplicate the existing objects. // Notify the client to duplicate the existing objects.
s.logger.Info(fmt.Sprintf("Sending existing stage objects to %s", s.Name)) s.logger.Info(fmt.Sprintf("Sending existing stage objects to %s", s.Name))
s.stage.RLock() s.stage.RLock()
var temp mhfpacket.MHFPacket
for _, obj := range s.stage.objects { for _, obj := range s.stage.objects {
if obj.ownerCharID == s.charID { if obj.ownerCharID == s.charID {
continue continue
@@ -107,16 +103,10 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
Unk0: 0, Unk0: 0,
OwnerCharID: obj.ownerCharID, OwnerCharID: obj.ownerCharID,
} }
newNotif.WriteUint16(uint16(temp.Opcode())) s.QueueSendMHF(temp)
temp.Build(newNotif)
} }
s.stage.RUnlock() s.stage.RUnlock()
} }
newNotif.WriteUint16(0x0010) // End it.
if len(newNotif.Data()) > 2 {
s.QueueSend(newNotif.Data())
}
} }
func destructEmptyStages(s *Session) { func destructEmptyStages(s *Session) {

View File

@@ -288,16 +288,7 @@ func (s *Server) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session)
if session == ignoredSession { if session == ignoredSession {
continue continue
} }
session.QueueSendMHF(pkt)
// Make the header
bf := byteframe.NewByteFrame()
bf.WriteUint16(uint16(pkt.Opcode()))
// Build the packet onto the byteframe.
pkt.Build(bf)
// Enqueue in a non-blocking way that drops the packet if the connections send buffer channel is full.
session.QueueSendNonBlocking(bf.Data())
} }
} }

View File

@@ -2,8 +2,6 @@ package channelserver
import ( import (
"erupe-ce/network/mhfpacket" "erupe-ce/network/mhfpacket"
"erupe-ce/utils/byteframe"
"sync" "sync"
) )
@@ -45,15 +43,6 @@ func (s *Semaphore) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Sessio
if session == ignoredSession { if session == ignoredSession {
continue continue
} }
session.QueueSendMHF(pkt)
// Make the header
bf := byteframe.NewByteFrame()
bf.WriteUint16(uint16(pkt.Opcode()))
// Build the packet onto the byteframe.
pkt.Build(bf)
// Enqueue in a non-blocking way that drops the packet if the connections send buffer channel is full.
session.QueueSendNonBlocking(bf.Data())
} }
} }

View File

@@ -20,11 +20,6 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
type packet struct {
data []byte
nonBlocking bool
}
// Session holds state for the channel server connection. // Session holds state for the channel server connection.
type Session struct { type Session struct {
sync.Mutex sync.Mutex
@@ -32,7 +27,7 @@ type Session struct {
server *Server server *Server
rawConn net.Conn rawConn net.Conn
cryptConn *network.CryptConn cryptConn *network.CryptConn
sendPackets chan packet sendPackets chan mhfpacket.MHFPacket
lastPacket time.Time lastPacket time.Time
objectIndex uint16 objectIndex uint16
@@ -76,7 +71,7 @@ func NewSession(server *Server, conn net.Conn) *Session {
server: server, server: server,
rawConn: conn, rawConn: conn,
cryptConn: network.NewCryptConn(conn), cryptConn: network.NewCryptConn(conn),
sendPackets: make(chan packet, 20), sendPackets: make(chan mhfpacket.MHFPacket, 20),
lastPacket: time.Now(), lastPacket: time.Now(),
sessionStart: gametime.TimeAdjusted().Unix(), sessionStart: gametime.TimeAdjusted().Unix(),
stageMoveStack: stringstack.New(), stageMoveStack: stringstack.New(),
@@ -96,73 +91,36 @@ func (s *Session) Start() {
go s.recvLoop() go s.recvLoop()
} }
// QueueSend queues a packet (raw []byte) to be sent. // QueueSendMHF queues a MHFPacket to be sent.
func (s *Session) QueueSend(data []byte) { func (s *Session) QueueSendMHF(pkt mhfpacket.MHFPacket) {
s.logMessage(binary.BigEndian.Uint16(data[0:2]), data, "Server", s.Name)
select { select {
case s.sendPackets <- packet{data, false}: case s.sendPackets <- pkt:
// Enqueued data
default:
s.logger.Warn("Packet queue too full, flushing!")
var tempPackets []packet
for len(s.sendPackets) > 0 {
tempPacket := <-s.sendPackets
if !tempPacket.nonBlocking {
tempPackets = append(tempPackets, tempPacket)
}
}
for _, tempPacket := range tempPackets {
s.sendPackets <- tempPacket
}
s.sendPackets <- packet{data, false}
}
}
// QueueSendNonBlocking queues a packet (raw []byte) to be sent, dropping the packet entirely if the queue is full.
func (s *Session) QueueSendNonBlocking(data []byte) {
select {
case s.sendPackets <- packet{data, true}:
s.logMessage(binary.BigEndian.Uint16(data[0:2]), data, "Server", s.Name)
default: default:
s.logger.Warn("Packet queue too full, dropping!") s.logger.Warn("Packet queue too full, dropping!")
} }
} }
// QueueSendMHF queues a MHFPacket to be sent.
func (s *Session) QueueSendMHF(pkt mhfpacket.MHFPacket) {
// Make the header
bf := byteframe.NewByteFrame()
bf.WriteUint16(uint16(pkt.Opcode()))
// Build the packet onto the byteframe.
pkt.Build(bf)
// Queue it.
s.QueueSend(bf.Data())
}
// QueueAck is a helper function to queue an MSG_SYS_ACK with the given ack handle and data.
func (s *Session) QueueAck(ackHandle uint32, data []byte) {
bf := byteframe.NewByteFrame()
bf.WriteUint16(uint16(network.MSG_SYS_ACK))
bf.WriteUint32(ackHandle)
bf.WriteBytes(data)
s.QueueSend(bf.Data())
}
func (s *Session) sendLoop() { func (s *Session) sendLoop() {
var pkt packet var pkt mhfpacket.MHFPacket
var buffer []byte var buffer []byte
end := &mhfpacket.MsgSysEnd{}
for { for {
if s.closed { if s.closed {
return return
} }
for len(s.sendPackets) > 0 { for len(s.sendPackets) > 0 {
pkt = <-s.sendPackets pkt = <-s.sendPackets
buffer = append(buffer, pkt.data...) bf := byteframe.NewByteFrame()
bf.WriteUint16(uint16(pkt.Opcode()))
pkt.Build(bf)
s.logMessage(uint16(pkt.Opcode()), bf.Data()[2:], "Server", s.Name)
buffer = append(buffer, bf.Data()...)
} }
bf := byteframe.NewByteFrame()
bf.WriteUint16(uint16(end.Opcode()))
buffer = append(buffer, bf.Data()...)
if len(buffer) > 0 { if len(buffer) > 0 {
err := s.cryptConn.SendPacket(append(buffer, []byte{0x00, 0x10}...)) err := s.cryptConn.SendPacket(buffer)
if err != nil { if err != nil {
s.logger.Warn("Failed to send packet") s.logger.Warn("Failed to send packet")
} }

View File

@@ -4,7 +4,6 @@ import (
"sync" "sync"
"erupe-ce/network/mhfpacket" "erupe-ce/network/mhfpacket"
"erupe-ce/utils/byteframe"
) )
// Object holds infomation about a specific object. // Object holds infomation about a specific object.
@@ -72,16 +71,7 @@ func (s *Stage) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) {
if session == ignoredSession { if session == ignoredSession {
continue continue
} }
session.QueueSendMHF(pkt)
// Make the header
bf := byteframe.NewByteFrame()
bf.WriteUint16(uint16(pkt.Opcode()))
// Build the packet onto the byteframe.
pkt.Build(bf)
// Enqueue in a non-blocking way that drops the packet if the connections send buffer channel is full.
session.QueueSendNonBlocking(bf.Data())
} }
} }