File: adding_deleting_pinhole.py

package info (click to toggle)
async-upnp-client 0.44.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,072 kB
  • sloc: python: 11,921; xml: 2,826; sh: 32; makefile: 6
file content (88 lines) | stat: -rw-r--r-- 2,542 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#!/usr/bin/env python3
"""Example of adding and deleting a port mapping."""

import asyncio
import ipaddress
import sys
from datetime import timedelta
from typing import cast

from async_upnp_client.aiohttp import AiohttpRequester
from async_upnp_client.client_factory import UpnpFactory
from async_upnp_client.profiles.igd import IgdDevice
from async_upnp_client.utils import CaseInsensitiveDict, get_local_ip

SOURCE = ("0.0.0.0", 0)


async def discover_igd_devices() -> set[CaseInsensitiveDict]:
    """Discover IGD devices."""
    # Do the search, this blocks for timeout (4 seconds, default).
    discoveries = await IgdDevice.async_search(source=SOURCE)
    if not discoveries:
        print("Could not find device")
        sys.exit(1)

    return discoveries


async def build_igd_device(discovery: CaseInsensitiveDict) -> IgdDevice:
    """Find and construct device."""
    location = discovery["location"]
    requester = AiohttpRequester()
    factory = UpnpFactory(requester, non_strict=True)
    device = await factory.async_create_device(description_url=location)
    return IgdDevice(device, None)


async def async_add_pinhole(igd_device: IgdDevice) -> int:
    """Add Pinhole."""
    remote_host: ipaddress.IPv6Address = ipaddress.ip_address("::1")
    internal_client: ipaddress.IPv6Address = ipaddress.ip_address("fe80::1")
    protocol = 6  # TCP=6, UDP=17
    pinhole_id = await igd_device.async_add_pinhole(
        remote_host=remote_host,
        remote_port=43210,
        internal_client=internal_client,
        internal_port=54321,
        protocol=protocol,
        lease_time=timedelta(seconds=7200),
    )
    return pinhole_id


async def async_del_pinhole(igd_device: IgdDevice, pinhole_id: int) -> None:
    """Delete port mapping."""
    await igd_device.async_delete_pinhole(
        pinhole_id=pinhole_id,
    )


async def async_main() -> None:
    """Async main."""
    discoveries = await discover_igd_devices()
    print(f"Discoveries: {discoveries}")
    discovery = list(discoveries)[0]
    print(f"Using device at location: {discovery['location']}")
    igd_device = await build_igd_device(discovery)

    print("Creating pinhole")
    pinhole_id = await async_add_pinhole(igd_device)
    print("Pinhole ID:", pinhole_id)

    await asyncio.sleep(5)

    print("Deleting pinhole")
    await async_del_pinhole(igd_device, pinhole_id)


def main() -> None:
    """Main."""
    try:
        asyncio.run(async_main())
    except KeyboardInterrupt:
        pass


if __name__ == "__main__":
    main()