This commit is contained in:
jdl 2024-12-14 07:38:21 +01:00
parent 485003204f
commit b4a6149cee
2 changed files with 170 additions and 0 deletions

32
peer/packets-helpers.go Normal file
View File

@ -0,0 +1,32 @@
package peer
import (
"log"
)
func unmarshalPacket(nonce Nonce, data []byte) Packet {
var packet Packet
switch nonce.PacketType {
case PACKET_TYPE_PING:
packet = &Ping{}
case PACKET_TYPE_PONG:
packet = &Pong{}
case PACKET_TYPE_LIST_ADDR_REQ:
packet = &AddrListReq{}
case PACKET_TYPE_LIST_ADDR_RESP:
packet = &AddrListResp{}
default:
// TODO: Log.
return nil
}
if len(data) < packet.Size() {
log.Printf("Short packet[%d]: %d", nonce.PacketType, len(data))
return nil
}
packet.Parse(data[:packet.Size()])
return packet
}

138
peer/packets.go Normal file
View File

@ -0,0 +1,138 @@
package peer
import "unsafe"
const (
PACKET_TYPE_DATA = 0
PACKET_TYPE_PING = 1
PACKET_TYPE_PONG = 2
PACKET_TYPE_CONN_REQ = 3
PACKET_TYPE_CONN_RESP = 4
PACKET_TYPE_CONN_RESP_ACK = 5
PACKET_TYPE_LIST_ADDR_REQ = 6
PACKET_TYPE_LIST_ADDR_RESP = 7
CONN_REQ_SIZE = 24
CONN_RESP_SIZE = 8
CONN_RESP_ACK_SIZE = 8
)
type Packet interface {
Size() int
Parse(buf []byte)
Marshal(buf []byte) []byte
}
// ----------------------------------------------------------------------------
type AddrListReq struct{} // Nothing.
func (r *AddrListReq) Size() int { return 0 }
func (r *AddrListReq) Parse(buf []byte) {}
func (r *AddrListReq) Marshal(buf []byte) []byte { return buf[:0] }
// ----------------------------------------------------------------------------
type AddrListResp struct {
Addrs [][16]byte // All addresses are IPv6 or mapped IPv6.
Ports []uint16 // Ports.
}
func (r *AddrListResp) Size() int {
return 18 * MAX_IP
}
func (r *AddrListResp) Parse(buf []byte) {
r.Addrs = unsafe.Slice((*[16]byte)(unsafe.Pointer(&buf[0])), MAX_IP)
r.Ports = unsafe.Slice((*uint16)(unsafe.Pointer(&buf[16*MAX_IP])), MAX_IP)
}
func (r *AddrListResp) Marshal(buf []byte) []byte {
buf = buf[:18:MAX_IP]
addrs := unsafe.Slice((*[16]byte)(unsafe.Pointer(&buf[0])), MAX_IP)
copy(addrs, r.Addrs)
ports := unsafe.Slice((*uint16)(unsafe.Pointer(&buf[16*MAX_IP])), MAX_IP)
copy(ports, r.Ports)
return buf
}
// ----------------------------------------------------------------------------
type ConnReq struct {
ReqID uint64
SentAt int64
Tiebreaker int64 // To determine which side is client or server.
}
func (r *ConnReq) Parse(buf []byte) {
r.ReqID = *(*uint64)(unsafe.Pointer(&buf[0]))
r.SentAt = *(*int64)(unsafe.Pointer(&buf[8]))
r.Tiebreaker = *(*int64)(unsafe.Pointer(&buf[16]))
}
func (r ConnReq) Marshal(buf []byte) []byte {
buf = buf[:24]
*(*uint64)(unsafe.Pointer(&buf[0])) = r.ReqID
*(*int64)(unsafe.Pointer(&buf[8])) = r.SentAt
*(*int64)(unsafe.Pointer(&buf[16])) = r.Tiebreaker
return buf
}
// ----------------------------------------------------------------------------
type ConnResp struct {
ReqID uint64
}
func (r *ConnResp) Parse(buf []byte) {
r.ReqID = *(*uint64)(unsafe.Pointer(&buf[0]))
}
func (r ConnResp) Marshal(buf []byte) {
*(*uint64)(unsafe.Pointer(&buf[0])) = r.ReqID
}
// ----------------------------------------------------------------------------
type ConnRespAck = ConnResp
// ----------------------------------------------------------------------------
type Ping struct {
SentAt int64 // unix milli
}
func (p *Ping) Size() int { return 8 }
func (p *Ping) Parse(buf []byte) {
p.SentAt = *(*int64)(unsafe.Pointer(&buf[0]))
}
func (p *Ping) Marshal(buf []byte) []byte {
buf = buf[:8]
*(*int64)(unsafe.Pointer(&buf[0])) = p.SentAt
return buf
}
// ----------------------------------------------------------------------------
type Pong struct {
SentAt int64 // unix mili
RecvdAt int64 // unix mili
}
func (p *Pong) Size() int { return 16 }
func (p *Pong) Parse(buf []byte) {
p.SentAt = *(*int64)(unsafe.Pointer(&buf[0]))
p.RecvdAt = *(*int64)(unsafe.Pointer(&buf[8]))
}
func (p *Pong) Marshal(buf []byte) []byte {
buf = buf[:16]
*(*int64)(unsafe.Pointer(&buf[0])) = p.SentAt
*(*int64)(unsafe.Pointer(&buf[8])) = p.RecvdAt
return buf
}