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