mapTcpAndUdp

suspend fun mapTcpAndUdp(client: HttpClient, igd: IgdControl, externalPort: Int, internalPort: Int, internalClient: String, leaseSeconds: Int = DEFAULT_LEASE_SECONDS, description: String = "KiteTorrent"): UpnpMapping

(Re)map both the TCP and UDP halves of a peer port on the gateway described by igd. The call is idempotent: re-issuing the same AddPortMapping refreshes the lease (this is exactly how the engine's lease-refresh timer keeps the mapping alive, mirroring upnp::update_map re-adding before expiry).

Returns an UpnpMapping handle recording which protocols succeeded; the engine keeps it to drive removeMapping on shutdown and to schedule the next refresh after leaseSeconds.