msnet

package module
v1.0.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 19, 2025 License: MIT Imports: 18 Imported by: 0

README

msnet

msnet is a pure Golang networking package for MapleStory

Installation

$ go get github.com/zhyonc/msnet@latest

Quick Start

package main

import (
	"log/slog"
	"net"

	"github.com/zhyonc/msnet"
)

type server struct {
	addr string
	lis  net.Listener
}

func NewServer(addr string) *server {
	s := &server{
		addr: addr,
	}
	return s
}

func (s *server) Run() {
	lis, err := net.Listen("tcp", s.addr)
	if err != nil {
		slog.Error("Failed to create tcp listener", "err", err)
		return
	}
	slog.Info("TCPListener is starting on " + s.addr)
	s.lis = lis
	for {
		if s.lis == nil {
			slog.Warn("TCPListener is nil")
			break
		}
		conn, err := s.lis.Accept()
		if err != nil {
			slog.Error("Failed to accept conn", "err", err)
			continue
		}
		slog.Info("New client connected", "addr", conn.RemoteAddr())
		cs := msnet.NewCClientSocket(conn, nil, nil, s)
		go cs.OnRead()
		cs.OnConnect()
	}
}

func (s *server) Shutdown() {
	s.lis.Close()
	s.lis = nil
}

func main() {
	msnet.New(&msnet.Setting{
		MSRegion: 8,
		MSVersion: 95,
		MSMinorVersion: "1",
	})
	s := NewServer("127.0.0.1:8484")
	s.Run()
}

Setting

  • MSRegion: MapleStory Regions including KMS(1)/KMST(2)/JMS(3)/CMS(4)/TMS(6)/MSEA(7)/GMS(8)/BMS(9)
  • MSVersion: MapleStory Client Version
  • MSMinorVersion: MapleStory Client Minor Version
  • RecvXOR: The server must use the same XOR key to recover the original packet
  • SendXOR: The client must use the same XOR key to recover the original packet
  • IsCycleAESKey:
    • Default is false, old AES key will be used, which is compatible with most earlier versions
    • If set true, cycle AES key will be used, which is compatible with newer versions
  • CustomAESKey(optional): It's used to instead of old AES key and cycle AES key
    • Decrypt: A 32-byte array used for decrypting data in CInPacket::DecryptData
    • Encrypt: A 32-byte array used for encrypting data in COutPacket::MakeBufferList

Packet

Header AESOFB Note
4 Bytes Any Bytes Except for the first packet
Decode

Decode packet length using XOR of two little-endian uint16 values from header
PacketLen = (Header[0]+Header[1]*0x100) ^ (Header[2]+Header[3]*0x100)

Encode

Encode packet length using little-endian XOR with sVersion and sendIV

  • sVersion = (^clientVer >> 8 & 0xFF) | ((^clientVer << 8) & 0xFF00)
  • a = int(sendIV[3])
  • a |= int(sendIV[2])<<8
  • a ^= sVersion
  • b = ((PacketLen << 8) & 0xFF00) | (PacketLen >> 8)
  • c = a ^ b
  • Header = [a>>8, a, c>>8, b]
Format
Opcode Data Note
2 Bytes Any Bytes Except for the connect packet
Connect Packet
Name PacketLen Version MinorVersionLen MinorVersion RecvIV SendIV Region Note
Connect 2 Bytes 2 Bytes 2 Bytes 1 Byte 4 Bytes 4 Bytes 1 Bytes The connect packet

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetLangBuf added in v1.0.2

func GetLangBuf(s string) []byte

func GetLangStr added in v1.0.2

func GetLangStr(buf []byte) string

func New

func New(setting *Setting)

func SetLogger

func SetLogger(backupDir string, filename string, level slog.Level, done chan bool)

Types

type CClientSocket

type CClientSocket interface {
	OnMigrateCommand(LP_MigrateCommand int16, ip string, port int16)
	OnConnect()
	Flush()
	OnAliveReq(LP_AliveReq int16)
	XORRecv(buf []byte)
	XORSend(buf []byte)
	OnRead()
	SendPacket(oPacket COutPacket)
	OnError(err error)
	Close()
	GetAddr() string
}

func NewCClientSocket

func NewCClientSocket(conn net.Conn, rcvIV []byte, sndIV []byte, impl CClientSocketImpl) CClientSocket

type CClientSocketImpl

type CClientSocketImpl interface {
	DebugInPacketLog(iPacket CInPacket)
	DebugOutPacketLog(oPacket COutPacket)
	ProcessPacket(cs CClientSocket, iPacket CInPacket)
	SocketClose()
}

type CInPacket

type CInPacket interface {
	AppendBuffer(pBuff []byte, bEnc bool)
	DecryptData(dwKey []byte)
	GetType() int16
	GetRemain() int
	GetLength() int
	DecodeBool() bool
	Decode1() int8
	Decode2() int16
	Decode4() int32
	Decode8() int64
	DecodeFT() time.Time
	DecodeStr() string
	DecodeLocalStr() string
	DecodeLocalName() string
	DecodeBuffer(uSize int) []byte
	DumpString(nSize int) string
	Clear()
}

func NewCInPacket

func NewCInPacket(buf []byte) CInPacket

type COutPacket

type COutPacket interface {
	GetType() int16
	GetSendBuffer() []byte
	GetLength() int
	EncodeBool(b bool)
	Encode1(n int8)
	Encode2(n int16)
	Encode4(n int32)
	Encode8(n int64)
	EncodeFT(t time.Time)
	EncodeStr(s string)
	EncodeLocalStr(s string)
	EncodeLocalName(s string)
	EncodeBuffer(buf []byte)
	MakeBufferList(uSeqBase uint16, bEnc bool, dwKey []byte) []byte
	DumpString(nSize int) string
}

func NewCOutPacket

func NewCOutPacket(nType int16) COutPacket

type Setting

type Setting struct {
	MSRegion       uint8
	MSVersion      uint16
	MSMinorVersion string
	RecvXOR        uint8
	SendXOR        uint8
	IsCycleAESKey  bool
	AESKeyDecrypt  [32]byte
	AESKeyEncrypt  [32]byte
}

Directories

Path Synopsis
internal
opcode
Code generated by opcode_test, DO NOT EDIT.
Code generated by opcode_test, DO NOT EDIT.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL