From b4a6149cee6d3d5b84f2bc396350a8fbb5f9be1c Mon Sep 17 00:00:00 2001 From: jdl Date: Sat, 14 Dec 2024 07:38:21 +0100 Subject: [PATCH] WIP --- peer/packets-helpers.go | 32 ++++++++++ peer/packets.go | 138 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 peer/packets-helpers.go create mode 100644 peer/packets.go diff --git a/peer/packets-helpers.go b/peer/packets-helpers.go new file mode 100644 index 0000000..ad1eb65 --- /dev/null +++ b/peer/packets-helpers.go @@ -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 +} diff --git a/peer/packets.go b/peer/packets.go new file mode 100644 index 0000000..1ccd64b --- /dev/null +++ b/peer/packets.go @@ -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 +}