1#ifdef CONF_UPNP
2
3#include "upnp.h"
4
5#include <base/system.h>
6
7#include <engine/shared/config.h>
8
9#include <game/version.h>
10
11#include <miniupnpc/miniupnpc.h>
12#include <miniupnpc/upnpcommands.h>
13#include <miniupnpc/upnperrors.h>
14
15#include <cstdlib>
16
17void CUPnP::Open(NETADDR Address)
18{
19 if(g_Config.m_SvUseUPnP)
20 {
21 m_Enabled = false;
22 m_Addr = Address;
23 m_pUPnPUrls = (struct UPNPUrls *)malloc(size: sizeof(struct UPNPUrls));
24 m_pUPnPData = (struct IGDdatas *)malloc(size: sizeof(struct IGDdatas));
25
26 char aLanAddr[64];
27 char aPort[6];
28 int Error;
29
30 m_pUPnPDevice = upnpDiscover(delay: 2000, NULL, NULL, localport: 0, ipv6: 0, ttl: 2, error: &Error);
31
32#if MINIUPNPC_API_VERSION > 17
33 char aWanAddr[64];
34 int Status = UPNP_GetValidIGD(devlist: m_pUPnPDevice, urls: m_pUPnPUrls, data: m_pUPnPData, lanaddr: aLanAddr, lanaddrlen: sizeof(aLanAddr), wanaddr: aWanAddr, wanaddrlen: sizeof(aWanAddr));
35 dbg_msg(sys: "upnp", fmt: "status=%d, lan_addr=%s, wan_addr=%s", Status, aLanAddr, aWanAddr);
36#else
37 int Status = UPNP_GetValidIGD(m_pUPnPDevice, m_pUPnPUrls, m_pUPnPData, aLanAddr, sizeof(aLanAddr));
38 dbg_msg("upnp", "status=%d, lan_addr=%s", Status, aLanAddr);
39#endif
40
41 if(Status == 1)
42 {
43 m_Enabled = true;
44 dbg_msg(sys: "upnp", fmt: "found valid IGD: %s", m_pUPnPUrls->controlURL);
45 str_format(buffer: aPort, buffer_size: sizeof(aPort), format: "%d", m_Addr.port);
46 Error = UPNP_AddPortMapping(controlURL: m_pUPnPUrls->controlURL, servicetype: m_pUPnPData->first.servicetype,
47 extPort: aPort, inPort: aPort, inClient: aLanAddr,
48 desc: "DDNet Server " GAME_RELEASE_VERSION,
49 proto: "UDP", NULL, leaseDuration: "0");
50
51 if(Error)
52 dbg_msg(sys: "upnp", fmt: "failed to map port, error: %s", strupnperror(err: Error));
53 else
54 dbg_msg(sys: "upnp", fmt: "successfully mapped port");
55 }
56 else
57 dbg_msg(sys: "upnp", fmt: "no valid IGD found, disabled");
58 }
59}
60
61void CUPnP::Shutdown()
62{
63 if(g_Config.m_SvUseUPnP)
64 {
65 if(m_Enabled)
66 {
67 char aPort[6];
68 str_format(buffer: aPort, buffer_size: sizeof(aPort), format: "%d", m_Addr.port);
69 int Error = UPNP_DeletePortMapping(controlURL: m_pUPnPUrls->controlURL, servicetype: m_pUPnPData->first.servicetype, extPort: aPort, proto: "UDP", NULL);
70
71 if(Error != 0)
72 {
73 dbg_msg(sys: "upnp", fmt: "failed to delete port mapping on shutdown: %s", strupnperror(err: Error));
74 }
75 FreeUPNPUrls(urls: m_pUPnPUrls);
76 freeUPNPDevlist(devlist: m_pUPnPDevice);
77 }
78 free(ptr: m_pUPnPUrls);
79 free(ptr: m_pUPnPData);
80 m_pUPnPUrls = NULL;
81 m_pUPnPData = NULL;
82 }
83}
84
85#endif
86