Cleanup StunSrvList
[novacoin.git] / src / stun.cpp
1 /*
2  * Get External IP address by STUN protocol
3  *
4  * Based on project Minimalistic STUN client "ministun"
5  * https://code.google.com/p/ministun/
6  *
7  * This program is free software, distributed under the terms of
8  * the GNU General Public License Version 2. See the LICENSE file
9  * at the top of the source tree.
10  *
11  * STUN is described in RFC3489 and it is based on the exchange
12  * of UDP packets between a client and one or more servers to
13  * determine the externally visible address (and port) of the client
14  * once it has gone through the NAT boxes that connect it to the
15  * outside.
16  * The simplest request packet is just the header defined in
17  * struct stun_header, and from the response we may just look at
18  * one attribute, STUN_MAPPED_ADDRESS, that we find in the response.
19  * By doing more transactions with different server addresses we
20  * may determine more about the behaviour of the NAT boxes, of
21  * course - the details are in the RFC.
22  *
23  * All STUN packets start with a simple header made of a type,
24  * length (excluding the header) and a 16-byte random transaction id.
25  * Following the header we may have zero or more attributes, each
26  * structured as a type, length and a value (whose format depends
27  * on the type, but often contains addresses).
28  * Of course all fields are in network format.
29  */
30
31 #include <stdio.h>
32 #include <inttypes.h>
33 #include <limits>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/types.h>
37 #ifdef WIN32
38 #include <winsock2.h>
39 #else
40 #include <sys/socket.h>
41 #include <netinet/in.h>
42 #include <arpa/inet.h>
43 #include <netdb.h>
44 #endif
45 #ifndef WIN32
46 #include <unistd.h>
47 #endif
48 #include <time.h>
49 #include <errno.h>
50
51 #include "ministun.h"
52 #include "netbase.h"
53
54 extern int GetRandInt(int nMax);
55 extern uint64_t GetRand(uint64_t nMax);
56
57 /*---------------------------------------------------------------------*/
58
59 struct StunSrv {
60     char     name[36];
61     uint16_t port;
62 };
63
64 /*---------------------------------------------------------------------*/
65 // STUN server list from 2019-06-27
66 static const int StunSrvListQty = 619; // Must be PRIME!!!!!
67
68 static struct StunSrv StunSrvList[619] = {
69   {"iphone-stun.strato-iphone.de",      3478},
70   {"stun.1-voip.com",   3478},
71   {"stun.12connect.com",        3478},
72   {"stun.12voip.com",   3478},
73   {"stun.1531.ru",      3478},
74   {"stun.1cbit.ru",     3478},
75   {"stun.1und1.de",     3478},
76   {"stun.3cx.com",      3478},
77   {"stun.3deluxe.de",   3478},
78   {"stun.3wayint.com",  3478},
79   {"stun.5sn.com",      3478},
80   {"stun.a-mm.tv",      3478},
81   {"stun.aa.net.uk",    3478},
82   {"stun.aaisp.co.uk",  3478},
83   {"stun.ab-hamm.de",   3478},
84   {"stun.aceweb.com",   3478},
85   {"stun.acquageraci.it",       3478},
86   {"stun.acrobits.cz",  3478},
87   {"stun.acronis.com",  3478},
88   {"stun.actionvoip.com",       3478},
89   {"stun.adafrance.ru", 3478},
90   {"stun.advfn.com",    3478},
91   {"stun.aeta-audio.com",       3478},
92   {"stun.aeta.com",     3478},
93   {"stun.alberon.cz",   3478},
94   {"stun.allflac.com",  3478},
95   {"stun.alphacron.de", 3478},
96   {"stun.alpirsbacher.de",      3478},
97   {"stun.anlx.net",     3478},
98   {"stun.ansur.no",     3478},
99   {"stun.antisip.com",  3478},
100   {"stun.arkh-edu.ru",  3478},
101   {"stun.artrage.com",  3478},
102   {"stun.atagverwarming.nl",    3478},
103   {"stun.atmapro.ru",   3478},
104   {"stun.autosystem.com",       3478},
105   {"stun.avigora.com",  3478},
106   {"stun.avigora.fr",   3478},
107   {"stun.avoxi.com",    3478},
108   {"stun.axeos.nl",     3478},
109   {"stun.axialys.net",  3478},
110   {"stun.azurecoast.com",       3478},
111   {"stun.b2b2c.ca",     3478},
112   {"stun.babelforce.com",       3478},
113   {"stun.bahnhof.net",  3478},
114   {"stun.baltmannsweiler.de",   3478},
115   {"stun.bandyer.com",  3478},
116   {"stun.barbaratabita.it",     3478},
117   {"stun.bau-ha.us",    3478},
118   {"stun.bearstech.com",        3478},
119   {"stun.beckhallmalham.com",   3478},
120   {"stun.beebeetle.com",        3478},
121   {"stun.bekkurso.info",        3478},
122   {"stun.bergophor.de", 3478},
123   {"stun.bernardoprovenzano.net",       3478},
124   {"stun.bernies-bergwelt.com", 3478},
125   {"stun.bethesda.net", 3478},
126   {"stun.biamp.com",    3478},
127   {"stun.bimp.fr",      3478},
128   {"stun.bitburger.de", 3478},
129   {"stun.bluesip.net",  3478},
130   {"stun.botonakis.com",        3478},
131   {"stun.bridesbay.com",        3478},
132   {"stun.budgetsip.com",        3478},
133   {"stun.bultest.org",  3478},
134   {"stun.business-isp.nl",      3478},
135   {"stun.cablenet-as.net",      3478},
136   {"stun.call.me",      3478},
137   {"stun.callromania.ro",       3478},
138   {"stun.callwithus.com",       3478},
139   {"stun.canwe.ca",     3478},
140   {"stun.careerarc.com",        3478},
141   {"stun.carlovizzini.it",      3478},
142   {"stun.cdosea.org",   3478},
143   {"stun.cellmail.com", 3478},
144   {"stun.chaosmos.de",  3478},
145   {"stun.chatous.com",  3478},
146   {"stun.cheapvoip.com",        3478},
147   {"stun.chewinggum.nl",        3478},
148   {"stun.cibercloud.com.br",    3478},
149   {"stun.circledoo.com",        3478},
150   {"stun.clickphone.ro",        3478},
151   {"stun.cloopen.com",  3478},
152   {"stun.club-galicia-bonn.de", 3478},
153   {"stun.cnj.gov.br",   3478},
154   {"stun.cnj.jus.br",   3478},
155   {"stun.coffee-sen.com",       3478},
156   {"stun.comrex.com",   3478},
157   {"stun.comtube.com",  3478},
158   {"stun.comtube.ru",   3478},
159   {"stun.connecteddata.com",    3478},
160   {"stun.cope.es",      3478},
161   {"stun.counterpath.com",      3478},
162   {"stun.counterpath.net",      3478},
163   {"stun.cozy.org",     3478},
164   {"stun.createweb.de", 3478},
165   {"stun.crimeastar.net",       3478},
166   {"stun.crononauta.com",       3478},
167   {"stun.cros.net",     3478},
168   {"stun.csforall.org", 3478},
169   {"stun.ctafauni.it",  3478},
170   {"stun.databay.de",   3478},
171   {"stun.dcalling.de",  3478},
172   {"stun.deepfinesse.com",      3478},
173   {"stun.degaronline.com",      3478},
174   {"stun.demos.ru",     3478},
175   {"stun.demos.su",     3478},
176   {"stun.deutscherskiverband.de",       3478},
177   {"stun.diallog.com",  3478},
178   {"stun.dincloud.com", 3478},
179   {"stun.dls.net",      3478},
180   {"stun.dokom.net",    3478},
181   {"stun.dorfbrunnen.eu",       3478},
182   {"stun.dorisgraf.de", 3478},
183   {"stun.dowlatow.ru",  3478},
184   {"stun.draci.info",   3478},
185   {"stun.dreifaltigkeit-stralsund.de",  3478},
186   {"stun.dsin-berufsschulen.de",        3478},
187   {"stun.dsin-blog.de", 3478},
188   {"stun.dukun.de",     3478},
189   {"stun.dunyatelekom.com",     3478},
190   {"stun.dus.net",      3478},
191   {"stun.eaclipt.org",  3478},
192   {"stun.easter-eggs.com",      3478},
193   {"stun.easycall.pl",  3478},
194   {"stun.easyvoip.com", 3478},
195   {"stun.edwin-wiegele.at",     3478},
196   {"stun.effexx.com",   3478},
197   {"stun.einfachcallback.de",   3478},
198   {"stun.ekir.de",      3478},
199   {"stun.eleusi.com",   3478},
200   {"stun.elitetele.com",        3478},
201   {"stun.engineeredarts.co.uk", 3478},
202   {"stun.eol.co.nz",    3478},
203   {"stun.eoni.com",     3478},
204   {"stun.epygi.com",    3478},
205   {"stun.eurescom.de",  3478},
206   {"stun.eurosys.be",   3478},
207   {"stun.evolution-movement.com",       3478},
208   {"stun.exoplatform.org",      3478},
209   {"stun.expandable.io",        3478},
210   {"stun.extrasaltmobile.com",  3478},
211   {"stun.faceflow.com", 3478},
212   {"stun.faelix.net",   3478},
213   {"stun.fairytel.at",  3478},
214   {"stun.faktortel.com.au",     3478},
215   {"stun.fathomvoice.com",      3478},
216   {"stun.fbsbx.com",    3478},
217   {"stun.feuerwehrmuseum.at",   3478},
218   {"stun.fiberpipe.net",        3478},
219   {"stun.files.fm",     3478},
220   {"stun.finbolt.eu",   3478},
221   {"stun.finsterwalder.com",    3478},
222   {"stun.fitauto.ru",   3478},
223   {"stun.fixup.net",    3478},
224   {"stun.fmo.de",       3478},
225   {"stun.foad.me.uk",   3478},
226   {"stun.fondazioneroccochinnici.it",   3478},
227   {"stun.framasoft.org",        3478},
228   {"stun.framatalk.org",        3478},
229   {"stun.freecall.com", 3478},
230   {"stun.freeswitch.org",       3478},
231   {"stun.freevoipdeal.com",     3478},
232   {"stun.frozenmountain.com",   3478},
233   {"stun.funwithelectronics.com",       3478},
234   {"stun.futurasp.es",  3478},
235   {"stun.galeriemagnet.at",     3478},
236   {"stun.galerievorspann.com",  3478},
237   {"stun.geekyboo.com", 3478},
238   {"stun.geesthacht.de",        3478},
239   {"stun.genymotion.com",       3478},
240   {"stun.geonet.ro",    3478},
241   {"stun.getzoop.com",  3478},
242   {"stun.gigaset.net",  3478},
243   {"stun.gkarnet.org",  3478},
244   {"stun.globalmeet.com",       3478},
245   {"stun.gmx.de",       3478},
246   {"stun.gmx.net",      3478},
247   {"stun.gntel.nl",     3478},
248   {"stun.godatenow.com",        3478},
249   {"stun.goldener-internetpreis.de",    3478},
250   {"stun.goldfish.ie",  3478},
251   {"stun.gotye.com.cn", 3478},
252   {"stun.graftlab.com", 3478},
253   {"stun.gravitel.ru",  3478},
254   {"stun.grazertrinkwasseringefahr.at", 3478},
255   {"stun.groenewold-newmedia.de",       3478},
256   {"stun.gruene.at",    3478},
257   {"stun.guenzburg.de", 3478},
258   {"stun.gulfsip.com",  3478},
259   {"stun.h4v.eu",       3478},
260   {"stun.hacknology.de",        3478},
261   {"stun.halonet.pl",   3478},
262   {"stun.hanacke.net",  3478},
263   {"stun.hardt-ware.de",        3478},
264   {"stun.healthtap.com",        3478},
265   {"stun.heeds.eu",     3478},
266   {"stun.hicare.net",   3478},
267   {"stun.hide.me",      3478},
268   {"stun.highfidelity.io",      3478},
269   {"stun.hinet.net",    3478},
270   {"stun.histocaffe.com",       3478},
271   {"stun.hitv.com",     3478},
272   {"stun.hobby-drechselei.de",  3478},
273   {"stun.hoiio.com",    3478},
274   {"stun.hosteurope.de",        3478},
275   {"stun.hot-chilli.net",       3478},
276   {"stun.hotelparadisebeach.it",        3478},
277   {"stun.ica-net.it",   3478},
278   {"stun.ideasip.com",  3478},
279   {"stun.ihk.cn",       3478},
280   {"stun.imafex.sk",    3478},
281   {"stun.imp.ch",       3478},
282   {"stun.ines-seidel.de",       3478},
283   {"stun.infra.net",    3478},
284   {"stun.innotel.com.au",       3478},
285   {"stun.innovaphone.com",      3478},
286   {"stun.innovaphone.de",       3478},
287   {"stun.instantteleseminar.com",       3478},
288   {"stun.internetcalls.com",    3478},
289   {"stun.interplanet.it",       3478},
290   {"stun.intervoip.com",        3478},
291   {"stun.invaluable.com",       3478},
292   {"stun.ippi.com",     3478},
293   {"stun.ippi.fr",      3478},
294   {"stun.ipshka.com",   3478},
295   {"stun.irishvoip.com",        3478},
296   {"stun.isp.net.au",   3478},
297   {"stun.issabel.org",  3478},
298   {"stun.istitutogramscisiciliano.it",  3478},
299   {"stun.it1.hr",       3478},
300   {"stun.ivao.aero",    3478},
301   {"stun.ivao.co.uk",   3478},
302   {"stun.ivi.at",       3478},
303   {"stun.ixc.ua",       3478},
304   {"stun.jabber.dk",    3478},
305   {"stun.jabbim.cz",    3478},
306   {"stun.janmedia.pl",  3478},
307   {"stun.jay.net",      3478},
308   {"stun.jowisoftware.de",      3478},
309   {"stun.jpluso.cz",    3478},
310   {"stun.julienschmidt.com",    3478},
311   {"stun.julosoft.net", 3478},
312   {"stun.jumblo.com",   3478},
313   {"stun.junet.se",     3478},
314   {"stun.justvoip.com", 3478},
315   {"stun.kanojo.de",    3478},
316   {"stun.kaseya.com",   3478},
317   {"stun.katholischekirche-ruegen.de",  3478},
318   {"stun.kaznpu.kz",    3478},
319   {"stun.kedr.io",      3478},
320   {"stun.kendama.ru",   3478},
321   {"stun.kiesler.at",   3478},
322   {"stun.kitamaebune.com",      3478},
323   {"stun.ko2100.at",    3478},
324   {"stun.komsa.de",     3478},
325   {"stun.kore.com",     3478},
326   {"stun.kostenloses-forum.com",        3478},
327   {"stun.kotter.net",   3478},
328   {"stun.kreis-bergstrasse.de", 3478},
329   {"stun.l.google.com", 19302},
330   {"stun.l.google.com", 19305},
331   {"stun.labs.net",     3478},
332   {"stun.lacompagnieducode.org",        3478},
333   {"stun.ladridiricette.it",    3478},
334   {"stun.landvast.nl",  3478},
335   {"stun.ldiglobal.org",        3478},
336   {"stun.le-space.de",  3478},
337   {"stun.lebendigefluesse.at",  3478},
338   {"stun.leibergmbh.de",        3478},
339   {"stun.leonde.org",   3478},
340   {"stun.lerros.com",   3478},
341   {"stun.leucotron.com.br",     3478},
342   {"stun.levigo.de",    3478},
343   {"stun.lindab.com",   3478},
344   {"stun.lineaencasa.com",      3478},
345   {"stun.linphone.org", 3478},
346   {"stun.linuxtrent.it",        3478},
347   {"stun.liveo.fr",     3478},
348   {"stun.lleida.net",   3478},
349   {"stun.localphone.com",       3478},
350   {"stun.logenex.com",  3478},
351   {"stun.logic.ky",     3478},
352   {"stun.londonweb.net",        3478},
353   {"stun.lovense.com",  3478},
354   {"stun.lowratevoip.com",      3478},
355   {"stun.lundimatin.fr",        3478},
356   {"stun.m-online.net", 3478},
357   {"stun.madavi.de",    3478},
358   {"stun.mage.com.vn",  3478},
359   {"stun.magnocall.com",        3478},
360   {"stun.magyarphone.eu",       3478},
361   {"stun.malemotion.com",       3478},
362   {"stun.mangotele.com",        3478},
363   {"stun.marble.io",    3478},
364   {"stun.marcelproust.it",      3478},
365   {"stun.mda.gov.br",   3478},
366   {"stun.mdaemon.com",  3478},
367   {"stun.medvc.eu",     3478},
368   {"stun.meetangee.com",        3478},
369   {"stun.meetwife.com", 3478},
370   {"stun.megakosmos.com.br",    3478},
371   {"stun.megatel.si",   3478},
372   {"stun.meowsbox.com", 3478},
373   {"stun.millenniumarts.org",   3478},
374   {"stun.mit.de",       3478},
375   {"stun.miwifi.com",   3478},
376   {"stun.mixvoip.com",  3478},
377   {"stun.mls.com.br",   3478},
378   {"stun.mobile-italia.com",    3478},
379   {"stun.modulus.gr",   3478},
380   {"stun.mondiaspora.net",      3478},
381   {"stun.mondiaspora.org",      3478},
382   {"stun.moonlight-stream.org", 3478},
383   {"stun.mot-net.com",  3478},
384   {"stun.mrmondialisation.org", 3478},
385   {"stun.muoversi.net", 3478},
386   {"stun.museumsguetesiegel.at",        3478},
387   {"stun.myfreecams.com",       3478},
388   {"stun.myfriends.ru", 3478},
389   {"stun.myhowto.org",  3478},
390   {"stun.mylio.com",    3478},
391   {"stun.myspeciality.com",     3478},
392   {"stun.myvoipapp.com",        3478},
393   {"stun.myvoiptraffic.com",    3478},
394   {"stun.mywatson.it",  3478},
395   {"stun.nabto.com",    3478},
396   {"stun.nanocosmos.de",        3478},
397   {"stun.naturfakta.com",       3478},
398   {"stun.nautile.nc",   3478},
399   {"stun.ncic.com",     3478},
400   {"stun.neomedia.it",  3478},
401   {"stun.nerathor.com", 3478},
402   {"stun.net-mag.cz",   3478},
403   {"stun.netappel.com", 3478},
404   {"stun.newrocktech.com",      3478},
405   {"stun.nexphone.ch",  3478},
406   {"stun.next-gen.ro",  3478},
407   {"stun.nextcloud.com",        3478},
408   {"stun.nexxtmobile.de",       3478},
409   {"stun.nfon.net",     3478},
410   {"stun.nicokrause.com",       3478},
411   {"stun.nieuwland.cc", 3478},
412   {"stun.niksteknoloji.com",    3478},
413   {"stun.nonoh.net",    3478},
414   {"stun.nosapps.com",  3478},
415   {"stun.nottingham.ac.uk",     3478},
416   {"stun.nova.is",      3478},
417   {"stun.nstelcom.com", 3478},
418   {"stun.obovsem.com",  3478},
419   {"stun.odr.de",       3478},
420   {"stun.officinabit.com",      3478},
421   {"stun.olimontel.it", 3478},
422   {"stun.omnitor.se",   3478},
423   {"stun.oncloud7.ch",  3478},
424   {"stun.onesuite.com", 3478},
425   {"stun.onthenet.com.au",      3478},
426   {"stun.ooma.com",     3478},
427   {"stun.openjobs.hu",  3478},
428   {"stun.openvoip.it",  3478},
429   {"stun.optdyn.com",   3478},
430   {"stun.orszaczky.com",        3478},
431   {"stun.ortopediacoam.it",     3478},
432   {"stun.osbid.cz",     3478},
433   {"stun.otos.pl",      3478},
434   {"stun.pados.hu",     3478},
435   {"stun.palava.tv",    3478},
436   {"stun.parcodeinebrodi.it",   3478},
437   {"stun.pbo.ru",       3478},
438   {"stun.peeters.com",  3478},
439   {"stun.peethultra.be",        3478},
440   {"stun.penserpouragir.org",   3478},
441   {"stun.peoplefone.ch",        3478},
442   {"stun.personal-voip.de",     3478},
443   {"stun.phone.com",    3478},
444   {"stun.photojim.ca",  3478},
445   {"stun.phytter.com",  3478},
446   {"stun.piratecinema.org",     3478},
447   {"stun.piratenbrandenburg.de",        3478},
448   {"stun.pjsip.org",    3478},
449   {"stun.planetarium.com.br",   3478},
450   {"stun.plexicomm.net",        3478},
451   {"stun.pobeda-club.ru",       3478},
452   {"stun.poetamatusel.org",     3478},
453   {"stun.poivy.com",    3478},
454   {"stun.potsdamvibes.de",      3478},
455   {"stun.powervoip.com",        3478},
456   {"stun.ppdi.com",     3478},
457   {"stun.provectio.fr", 3478},
458   {"stun.pruefplan.com",        3478},
459   {"stun.psipsi.com.br",        3478},
460   {"stun.pure-ip.com",  3478},
461   {"stun.qbictechnology.com",   3478},
462   {"stun.qcol.net",     3478},
463   {"stun.qq.com",       3478},
464   {"stun.qwant.com",    3478},
465   {"stun.rackco.com",   3478},
466   {"stun.racknine.net", 3478},
467   {"stun.radiojar.com", 3478},
468   {"stun.ransquawk.com",        3478},
469   {"stun.readyforsky.com",      3478},
470   {"stun.realgarant.com",       3478},
471   {"stun.redworks.nl",  3478},
472   {"stun.revreso.de",   3478},
473   {"stun.ringostat.com",        3478},
474   {"stun.ringvoz.com",  3478},
475   {"stun.rmf.pl",       3478},
476   {"stun.robocup.at",   3478},
477   {"stun.rockenstein.de",       3478},
478   {"stun.rolmail.net",  3478},
479   {"stun.romaaeterna.nl",       3478},
480   {"stun.romancecompass.com",   3478},
481   {"stun.root-1.de",    3478},
482   {"stun.ru-brides.com",        3478},
483   {"stun.rudtp.ru",     3478},
484   {"stun.rynga.com",    3478},
485   {"stun.sacko.com.au", 3478},
486   {"stun.samy.pl",      3478},
487   {"stun.saooti.com",   3478},
488   {"stun.savemgo.com",  3478},
489   {"stun.scalix.com",   3478},
490   {"stun.schlund.de",   3478},
491   {"stun.schoeffel.de", 3478},
492   {"stun.schulinformatik.at",   3478},
493   {"stun.selasky.org",  3478},
494   {"stun.semiocast.com",        3478},
495   {"stun.senstar.com",  3478},
496   {"stun.sewan.fr",     3478},
497   {"stun.sg-slope.com", 3478},
498   {"stun.shadrinsk.net",        3478},
499   {"stun.sharpbai.com", 3478},
500   {"stun.shy.cz",       3478},
501   {"stun.siedle.com",   3478},
502   {"stun.sigmavoip.com",        3478},
503   {"stun.signalwire.com",       3478},
504   {"stun.simlar.org",   3478},
505   {"stun.sip.us",       3478},
506   {"stun.sipdiscount.com",      3478},
507   {"stun.sipgate.net",  10000},
508   {"stun.sipgate.net",  3478},
509   {"stun.sipglobalphone.com",   3478},
510   {"stun.siplogin.de",  3478},
511   {"stun.sipnet.com",   3478},
512   {"stun.siportal.it",  3478},
513   {"stun.sippeer.dk",   3478},
514   {"stun.sipthor.net",  3478},
515   {"stun.siptraffic.com",       3478},
516   {"stun.siptrunk.com", 3478},
517   {"stun.sipy.cz",      3478},
518   {"stun.sius.com",     3478},
519   {"stun.sketch.io",    3478},
520   {"stun.skrumble.com", 3478},
521   {"stun.sky.od.ua",    3478},
522   {"stun.skydrone.aero",        3478},
523   {"stun.slackline.at", 3478},
524   {"stun.sma.de",       3478},
525   {"stun.smartvoip.com",        3478},
526   {"stun.smdr.ru",      3478},
527   {"stun.smsdiscount.com",      3478},
528   {"stun.smslisto.com", 3478},
529   {"stun.soho66.co.uk", 3478},
530   {"stun.sokoll.com",   3478},
531   {"stun.solcon.nl",    3478},
532   {"stun.solnet.ch",    3478},
533   {"stun.solomo.de",    3478},
534   {"stun.sonetel.com",  3478},
535   {"stun.sonetel.net",  3478},
536   {"stun.sovtest.ru",   3478},
537   {"stun.sparvoip.de",  3478},
538   {"stun.speedy.com.ar",        3478},
539   {"stun.splicecom.com",        3478},
540   {"stun.spoiltheprincess.com", 3478},
541   {"stun.spreed.me",    3478},
542   {"stun.srce.hr",      3478},
543   {"stun.stadtwerke-eutin.de",  3478},
544   {"stun.stbuehler.de", 3478},
545   {"stun.steinbeis-smi.de",     3478},
546   {"stun.stochastix.de",        3478},
547   {"stun.stratusvideo.com",     3478},
548   {"stun.streamix.live",        3478},
549   {"stun.streamnow.ch", 3478},
550   {"stun.studio-link.de",       3478},
551   {"stun.studio71.it",  3478},
552   {"stun.stunprotocol.org",     3478},
553   {"stun.stuttgart-ix.de",      3478},
554   {"stun.surjaring.it", 3478},
555   {"stun.surrealnetworks.com",  3478},
556   {"stun.swissquote.com",       3478},
557   {"stun.swrag.de",     3478},
558   {"stun.sylaps.com",   3478},
559   {"stun.symonics.com", 3478},
560   {"stun.syncthing.net",        3478},
561   {"stun.synergiejobs.be",      3478},
562   {"stun.syrex.co.za",  3478},
563   {"stun.t-online.de",  3478},
564   {"stun.talk.by",      3478},
565   {"stun.talkho.com",   3478},
566   {"stun.talks.by",     3478},
567   {"stun.taxsee.com",   3478},
568   {"stun.teamfon.de",   3478},
569   {"stun.technosens.fr",        3478},
570   {"stun.teconisy.com", 3478},
571   {"stun.tel.lu",       3478},
572   {"stun.tel2.co.uk",   3478},
573   {"stun.telbo.com",    3478},
574   {"stun.tele2.net",    3478},
575   {"stun.telemar.it",   3478},
576   {"stun.teliax.com",   3478},
577   {"stun.telnyx.com",   3478},
578   {"stun.telonline.com",        3478},
579   {"stun.telviva.com",  3478},
580   {"stun.telzio.com",   3478},
581   {"stun.testreach.com",        3478},
582   {"stun.textz.com",    3478},
583   {"stun.thebrassgroup.it",     3478},
584   {"stun.thfree.ru",    3478},
585   {"stun.thinkrosystem.com",    3478},
586   {"stun.threema.ch",   3478},
587   {"stun.tichiamo.it",  3478},
588   {"stun.tng.de",       3478},
589   {"stun.totalcom.info",        3478},
590   {"stun.touchcast.com",        3478},
591   {"stun.training-online.eu",   3478},
592   {"stun.trainingspace.online", 3478},
593   {"stun.trivenet.it",  3478},
594   {"stun.ttmath.org",   3478},
595   {"stun.tula.nu",      3478},
596   {"stun.twt.it",       3478},
597   {"stun.uabrides.com", 3478},
598   {"stun.uavia.eu",     3478},
599   {"stun.uiltucssicilia.it",    3478},
600   {"stun.ukh.de",       3478},
601   {"stun.uls.co.za",    3478},
602   {"stun.unseen.is",    3478},
603   {"stun.url.net.au",   3478},
604   {"stun.vadacom.co.nz",        3478},
605   {"stun.var6.cn",      3478},
606   {"stun.vavadating.com",       3478},
607   {"stun.verbo.be",     3478},
608   {"stun.viagenie.ca",  3478},
609   {"stun.villapalagonia.it",    3478},
610   {"stun.vincross.com", 3478},
611   {"stun.viptel.sk",    3478},
612   {"stun.visocon.com",  3478},
613   {"stun.viva.gr",      3478},
614   {"stun.vivox.com",    3478},
615   {"stun.vnc.biz",      3478},
616   {"stun.vo.lu",        3478},
617   {"stun.voicetech.se", 3478},
618   {"stun.voicetrading.com",     3478},
619   {"stun.voip.aebc.com",        3478},
620   {"stun.voip.blackberry.com",  3478},
621   {"stun.voip.eutelia.it",      3478},
622   {"stun.voiparound.com",       3478},
623   {"stun.voipblast.com",        3478},
624   {"stun.voipbuster.com",       3478},
625   {"stun.voipbusterpro.com",    3478},
626   {"stun.voipcheap.com",        3478},
627   {"stun.voipconnect.com",      3478},
628   {"stun.voipdiscount.com",     3478},
629   {"stun.voipfibre.com",        3478},
630   {"stun.voipgain.com", 3478},
631   {"stun.voipgate.com", 3478},
632   {"stun.voipgrid.nl",  3478},
633   {"stun.voipia.net",   3478},
634   {"stun.voipinfocenter.com",   3478},
635   {"stun.voippro.com",  3478},
636   {"stun.voipraider.com",       3478},
637   {"stun.voiprakyat.or.id",     3478},
638   {"stun.voipstreet.com",       3478},
639   {"stun.voipstunt.com",        3478},
640   {"stun.voipvoice.it", 3478},
641   {"stun.voipwise.com", 3478},
642   {"stun.voipxs.nl",    3478},
643   {"stun.voipzoom.com", 3478},
644   {"stun.vomessen.de",  3478},
645   {"stun.voxox.com",    3478},
646   {"stun.voys.nl",      3478},
647   {"stun.vozelia.com",  3478},
648   {"stun.voztele.com",  3478},
649   {"stun.voztovoice.org",       3478},
650   {"stun.waterpolopalermo.it",  3478},
651   {"stun.wcoil.com",    3478},
652   {"stun.webcalldirect.com",    3478},
653   {"stun.webfreak.org", 3478},
654   {"stun.webitel.ua",   3478},
655   {"stun.webmatrix.com.br",     3478},
656   {"stun.webscience-journal.net",       3478},
657   {"stun.weepee.org",   3478},
658   {"stun.wemag.com",    3478},
659   {"stun.westtel.ky",   3478},
660   {"stun.whc.net",      3478},
661   {"stun.wia.cz",       3478},
662   {"stun.wifirst.net",  3478},
663   {"stun.wtfismyip.com",        3478},
664   {"stun.wxnz.net",     3478},
665   {"stun.xn----8sbcoa5btidn9i.xn--p1ai",        3478},
666   {"stun.xten.com",     3478},
667   {"stun.xtratelecom.es",       3478},
668   {"stun.yangutu.com",  3478},
669   {"stun.yesdates.com", 3478},
670   {"stun.yeymo.com",    3478},
671   {"stun.yollacalls.com",       3478},
672   {"stun.yy.com",       3478},
673   {"stun.zadarma.com",  3478},
674   {"stun.zentauron.de", 3478},
675   {"stun.zepter.ru",    3478},
676   {"stun.zombiegrinder.com",    3478},
677   {"stun.zottel.net",   3478},
678   {"stun.zuckschwerdt.org",     3478},
679   {"stun1.faktortel.com.au",    3478},
680   {"stun1.l.google.com",        19302},
681   {"stun1.l.google.com",        19305},
682   {"stun2.l.google.com",        19302},
683   {"stun2.l.google.com",        19305},
684   {"stun3.l.google.com",        19302},
685   {"stun3.l.google.com",        19305},
686   {"stun4.l.google.com",        19302},
687   {"stun4.l.google.com",        19305}
688 };
689
690
691 /* wrapper to send an STUN message */
692 static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
693 {
694     return sendto(s, (const char *)resp, ntohs(resp->msglen) + sizeof(*resp), 0,
695                   (struct sockaddr *)dst, sizeof(*dst));
696 }
697
698 /* helper function to generate a random request id */
699 static uint64_t randfiller = GetRand(std::numeric_limits<uint64_t>::max());
700 static void stun_req_id(struct stun_header *req)
701 {
702     const uint64_t *S_block = (const uint64_t *)StunSrvList;
703     req->id.id[0] = GetRandInt(std::numeric_limits<int32_t>::max());
704     req->id.id[1] = GetRandInt(std::numeric_limits<int32_t>::max());
705     req->id.id[2] = GetRandInt(std::numeric_limits<int32_t>::max());
706     req->id.id[3] = GetRandInt(std::numeric_limits<int32_t>::max());
707
708     req->id.id[0] |= 0x55555555;
709     req->id.id[1] &= 0x55555555;
710     req->id.id[2] |= 0x55555555;
711     req->id.id[3] &= 0x55555555;
712     char x = 20;
713     do {
714         uint32_t s_elm = S_block[(uint8_t)randfiller];
715         randfiller ^= (randfiller << 5) | (randfiller >> (64 - 5));
716         randfiller += s_elm ^ x;
717         req->id.id[x & 3] ^= randfiller + (randfiller >> 13);
718     } while(--x);
719 }
720
721 /* callback type to be invoked on stun responses. */
722 typedef int (stun_cb_f)(struct stun_attr *attr, void *arg);
723
724 /* handle an incoming STUN message.
725  *
726  * Do some basic sanity checks on packet size and content,
727  * try to extract a bit of information, and possibly reply.
728  * At the moment this only processes BIND requests, and returns
729  * the externally visible address of the request.
730  * If a callback is specified, invoke it with the attribute.
731  */
732 static int stun_handle_packet(int s, struct sockaddr_in *src,
733                               unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
734 {
735     struct stun_header *hdr = (struct stun_header *)data;
736     struct stun_attr *attr;
737     int ret = len;
738     unsigned int x;
739
740     /* On entry, 'len' is the length of the udp payload. After the
741    * initial checks it becomes the size of unprocessed options,
742    * while 'data' is advanced accordingly.
743    */
744     if (len < sizeof(struct stun_header))
745         return -20;
746
747     len -= sizeof(struct stun_header);
748     data += sizeof(struct stun_header);
749     x = ntohs(hdr->msglen); /* len as advertised in the message */
750     if(x < len)
751         len = x;
752
753     while (len) {
754         if (len < sizeof(struct stun_attr)) {
755             ret = -21;
756             break;
757         }
758         attr = (struct stun_attr *)data;
759         /* compute total attribute length */
760         x = ntohs(attr->len) + sizeof(struct stun_attr);
761         if (x > len) {
762             ret = -22;
763             break;
764         }
765         stun_cb(attr, arg);
766         //if (stun_process_attr(&st, attr)) {
767         //  ret = -23;
768         //  break;
769         // }
770         /* Clear attribute id: in case previous entry was a string,
771      * this will act as the terminator for the string.
772      */
773         attr->attr = 0;
774         data += x;
775         len -= x;
776     } // while
777     /* Null terminate any string.
778    * XXX NOTE, we write past the size of the buffer passed by the
779    * caller, so this is potentially dangerous. The only thing that
780    * saves us is that usually we read the incoming message in a
781    * much larger buffer
782    */
783     *data = '\0';
784
785     /* Now prepare to generate a reply, which at the moment is done
786    * only for properly formed (len == 0) STUN_BINDREQ messages.
787    */
788
789     return ret;
790 }
791
792 /* Extract the STUN_MAPPED_ADDRESS from the stun response.
793  * This is used as a callback for stun_handle_response
794  * when called from stun_request.
795  */
796 static int stun_get_mapped(struct stun_attr *attr, void *arg)
797 {
798     struct stun_addr *addr = (struct stun_addr *)(attr + 1);
799     struct sockaddr_in *sa = (struct sockaddr_in *)arg;
800
801     if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8)
802         return 1; /* not us. */
803     sa->sin_port = addr->port;
804     sa->sin_addr.s_addr = addr->addr;
805     return 0;
806 }
807
808 /*---------------------------------------------------------------------*/
809
810 static int StunRequest2(int sock, struct sockaddr_in *server, struct sockaddr_in *mapped) {
811
812     struct stun_header *req;
813     unsigned char reqdata[1024];
814
815     req = (struct stun_header *)reqdata;
816     stun_req_id(req);
817     unsigned short reqlen = 0;
818     req->msgtype = 0;
819     req->msglen = 0;
820     req->msglen = htons(reqlen);
821     req->msgtype = htons(STUN_BINDREQ);
822
823     unsigned char reply_buf[1024];
824     fd_set rfds;
825     struct timeval to = { STUN_TIMEOUT, 0 };
826     struct sockaddr_in src;
827 #ifdef WIN32
828     int srclen;
829 #else
830     socklen_t srclen;
831 #endif
832
833     int res = stun_send(sock, server, req);
834     if(res < 0)
835         return -10;
836     FD_ZERO(&rfds);
837     FD_SET(sock, &rfds);
838     res = select(sock + 1, &rfds, NULL, NULL, &to);
839     if (res <= 0)  /* timeout or error */
840         return -11;
841     memset(&src, 0, sizeof(src));
842     srclen = sizeof(src);
843     /* XXX pass -1 in the size, because stun_handle_packet might
844    * write past the end of the buffer.
845    */
846     res = recvfrom(sock, (char *)reply_buf, sizeof(reply_buf) - 1,
847                    0, (struct sockaddr *)&src, &srclen);
848     if (res <= 0)
849         return -12;
850     memset(mapped, 0, sizeof(struct sockaddr_in));
851     return stun_handle_packet(sock, &src, reply_buf, res, stun_get_mapped, mapped);
852 } // StunRequest2
853
854 /*---------------------------------------------------------------------*/
855 static int StunRequest(const char *host, uint16_t port, struct sockaddr_in *mapped) {
856     struct hostent *hostinfo = gethostbyname(host);
857     if(hostinfo == NULL)
858         return -1;
859
860     SOCKET sock = INVALID_SOCKET;
861     struct sockaddr_in server, client;
862     memset(&server, 0, sizeof(server));
863     memset(&client, 0, sizeof(client));
864     server.sin_family = client.sin_family = AF_INET;
865
866     server.sin_addr = *(struct in_addr*) hostinfo->h_addr;
867     server.sin_port = htons(port);
868
869     sock = socket(AF_INET, SOCK_DGRAM, 0);
870     if(sock == INVALID_SOCKET)
871         return -2;
872
873     client.sin_addr.s_addr = htonl(INADDR_ANY);
874
875     int rc = -3;
876     if(bind(sock, (struct sockaddr*)&client, sizeof(client)) >= 0)
877         rc = StunRequest2(sock, &server, mapped);
878     CloseSocket(sock);
879     return rc;
880 } // StunRequest
881
882 /*---------------------------------------------------------------------*/
883 // Input: two random values (pos, step) for generate uniuqe way over server
884 // list
885 // Output: populate struct struct mapped
886 // Retval:
887
888 int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv) {
889     randfiller    = rnd;
890     uint16_t pos  = rnd;
891     uint16_t step;
892     do {
893         rnd = (rnd >> 8) | 0xff00000000000000LL;
894         step = rnd % StunSrvListQty;
895     } while(step == 0);
896
897     uint16_t attempt;
898     for(attempt = 1; attempt < StunSrvListQty * 2; attempt++) {
899         pos = (pos + step) % StunSrvListQty;
900         int rc = StunRequest(*srv = StunSrvList[pos].name, StunSrvList[pos].port, mapped);
901         if(rc >= 0)
902             return attempt;
903         // fprintf(stderr, "Lookup: %s:%u\t%s\t%d\n", StunSrvList[pos].name,
904         // StunSrvList[pos].port, inet_ntoa(mapped->sin_addr), rc);
905     }
906     return -1;
907 }