Files
bitchat/bitchat/Models/RequestSyncPacket.swift
T
2ac01db9c4 SYNC_REQUEST 2 (#616)
* wip

* woohooo

* Plumtree gossip: don't subset REQUEST_SYNC fanout; make RequestSyncPacket.encode use const

* bloom -> gcs [wip]

* fix build

* fix broadcast

* prune old messages too

* faster sync

* prune better

* adjust parameters

* fix(sync): make cap a constant in GCSFilter.buildFilter to silence 'never mutated' warning

* fix(mesh): surface self-origin public messages recovered via sync; only ignore self when TTL != 0 in handleMessage

* sync: allow self messages via GCS restore and relax TTL==0 acceptance\n- Bypass dedup for self TTL==0 packets in handleReceivedPacket\n- Accept self TTL==0 in handleMessage and set nickname\n- Accept unknown senders for TTL==0 with anon# prefix to restore history

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-09-15 13:57:09 +02:00

64 lines
2.0 KiB
Swift

import Foundation
// REQUEST_SYNC payload TLV (type, length16, value)
// - 0x01: P (uint8) — Golomb-Rice parameter
// - 0x02: M (uint32, big-endian) — hash range (N * 2^P)
// - 0x03: data (opaque) — GR bitstream bytes (MSB-first)
struct RequestSyncPacket {
let p: Int
let m: UInt32
let data: Data
func encode() -> Data {
var out = Data()
func putTLV(_ t: UInt8, _ v: Data) {
out.append(t)
let len = UInt16(v.count)
out.append(UInt8((len >> 8) & 0xFF))
out.append(UInt8(len & 0xFF))
out.append(v)
}
// P
putTLV(0x01, Data([UInt8(p & 0xFF)]))
// M (uint32)
var mBE = m.bigEndian
putTLV(0x02, withUnsafeBytes(of: &mBE) { Data($0) })
// data
putTLV(0x03, data)
return out
}
static func decode(from data: Data, maxAcceptBytes: Int = 1024) -> RequestSyncPacket? {
var off = 0
var p: Int? = nil
var m: UInt32? = nil
var payload: Data? = nil
while off + 3 <= data.count {
let t = Int(data[off]); off += 1
guard off + 2 <= data.count else { return nil }
let len = (Int(data[off]) << 8) | Int(data[off+1]); off += 2
guard off + len <= data.count else { return nil }
let v = data.subdata(in: off..<(off+len)); off += len
switch t {
case 0x01:
if v.count == 1 { p = Int(v[0]) }
case 0x02:
if v.count == 4 {
var mm: UInt32 = 0
for b in v { mm = (mm << 8) | UInt32(b) }
m = mm
}
case 0x03:
if v.count > maxAcceptBytes { return nil }
payload = v
default:
break // forward compatible; ignore unknown TLVs
}
}
guard let pp = p, let mm = m, let dd = payload, pp >= 1, mm > 0 else { return nil }
return RequestSyncPacket(p: pp, m: mm, data: dd)
}
}