diff --git a/Makefile b/Makefile
index abb09ff..9c55ae6 100644
--- a/Makefile
+++ b/Makefile
@@ -11,10 +11,10 @@ CFLAGS += '-DPACKAGE_DATADIR="$(abspath $(DATADIR))"'
CFLAGS += $(USER_CFLAGS)
LDFLAGS = $(USER_LDFLAGS)
-OBJ = chat.o chat_commands.o configdir.o execute.o file_transfers.o notify.o
-OBJ += friendlist.o global_commands.o groupchat.o line_info.o input.o help.o autocomplete.o
-OBJ += log.o misc_tools.o prompt.o settings.o toxic.o toxic_strings.o windows.o message_queue.o
-OBJ += group_commands.o term_mplex.o avatars.o name_lookup.o qr_code.o bootstrap.o
+OBJ = autocomplete.o avatars.o bootstrap.o chat.o chat_commands.o configdir.o curl_util.o execute.o
+OBJ += file_transfers.o friendlist.o global_commands.o group_commands.o groupchat.o help.o input.o
+OBJ += line_info.o log.o message_queue.o misc_tools.o name_lookup.o notify.o prompt.o qr_code.o settings.o
+OBJ += term_mplex.o toxic.o toxic_strings.o windows.o
# Check on wich system we are running
UNAME_S = $(shell uname -s)
diff --git a/cfg/global_vars.mk b/cfg/global_vars.mk
index 2fa9723..0503b90 100644
--- a/cfg/global_vars.mk
+++ b/cfg/global_vars.mk
@@ -16,7 +16,7 @@ MISC_DIR = $(BASE_DIR)/misc
# Project files
MANFILES = toxic.1 toxic.conf.5
-DATAFILES = DHTnodes nameservers toxic.conf.example
+DATAFILES = nameservers toxic.conf.example
DESKFILE = toxic.desktop
SNDFILES = ToxicContactOnline.wav ToxicContactOffline.wav ToxicError.wav
SNDFILES += ToxicRecvMessage.wav ToxicOutgoingCall.wav ToxicIncomingCall.wav
diff --git a/doc/toxic.1 b/doc/toxic.1
index 9878cb1..a5c72eb 100644
--- a/doc/toxic.1
+++ b/doc/toxic.1
@@ -2,12 +2,12 @@
.\" Title: toxic
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1
-.\" Date: 2015-12-07
+.\" Date: 2016-04-25
.\" Manual: Toxic Manual
.\" Source: toxic __VERSION__
.\" Language: English
.\"
-.TH "TOXIC" "1" "2015\-12\-07" "toxic __VERSION__" "Toxic Manual"
+.TH "TOXIC" "1" "2016\-04\-25" "toxic __VERSION__" "Toxic Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -82,8 +82,7 @@ Show help message
.RS 4
Use specified
\fInodes\-file\fR
-for DHT bootstrap nodes, instead of
-\fI__DATADIR__/DHTnodes\fR
+for DHT bootstrap nodes, instead of the default
.RE
.PP
\-o, \-\-noconnect
@@ -122,9 +121,10 @@ Unencrypt a data file\&. A warning will appear if this option is used with a dat
.RE
.SH "FILES"
.PP
-__DATADIR__/DHTnodes
+~/\&.config/tox/DHTnodes
.RS 4
-Default list of DHT bootstrap nodes\&.
+Default location for list of DHT bootstrap nodes (list obtained at
+https://nodes\&.tox\&.chat)\&. This list is automatically updated every 30 days\&.
.RE
.PP
~/\&.config/tox/toxic_profile\&.tox
diff --git a/doc/toxic.1.asc b/doc/toxic.1.asc
index 20d3c00..b97af86 100644
--- a/doc/toxic.1.asc
+++ b/doc/toxic.1.asc
@@ -41,8 +41,7 @@ OPTIONS
Show help message
-n, --nodes nodes-file::
- Use specified 'nodes-file' for DHT bootstrap nodes, instead of
- '{datadir}/DHTnodes'
+ Use specified 'nodes-file' for DHT bootstrap nodes, instead of the default
-o, --noconnect::
Do not connect to the DHT network
@@ -68,8 +67,9 @@ OPTIONS
FILES
-----
-{datadir}/DHTnodes::
- Default list of DHT bootstrap nodes.
+~/.config/tox/DHTnodes::
+ Default location for list of DHT bootstrap nodes (list obtained at https://nodes.tox.chat).
+ This list is automatically updated every 30 days.
~/.config/tox/toxic_profile.tox::
Savestate which contains your personal info (nickname, Tox ID, contacts,
diff --git a/misc/DHTnodes b/misc/DHTnodes
deleted file mode 100644
index bdaefc6..0000000
--- a/misc/DHTnodes
+++ /dev/null
@@ -1 +0,0 @@
-{"last_scan":1474137109,"nodes":[{"ipv4":"tox.zodiaclabs.org","ipv6":"v6.tox.zodiaclabs.org","port":33445,"tcp_ports":[33445,3389],"public_key":"A09162D68618E742FFBCA1C2C70385E6679604B2D80EA6E84AD0996A1AC8A074","maintainer":"stal","location":"US","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"I am the bone of my code;\nNIH is my body and str8c is my blood.\nI have overflowed a thousand buffers.\nUnknown to SIGSEGV, nor to abort();\nHave withstood pain to create fast programs;\nYet my code will always be unsafe.\nSo as I pray, rock solid straight C.","last_ping":1474137098},{"ipv4":"biribiri.org","ipv6":"-","port":33445,"tcp_ports":[33445,3389],"public_key":"F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67","maintainer":"nurupo","location":"US","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Welcome, stranger #3783. I'm up for 1d 14h 23m 12s, running since Sep 16 04:08:25 UTC. If I get outdated, please ping my maintainer at nurupo.contributions@gmail.com","last_ping":1474137098},{"ipv4":"178.62.250.138","ipv6":"2a03:b0c0:2:d0::16:1","port":33445,"tcp_ports":[3389,33445],"public_key":"788236D34978D1D5BD822F0A5BEBD2C53C64CC31CD3149350EE27D4D9A2F9B6B","maintainer":"Impyy","location":"NL","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Impy's kickin' bootstrap node","last_ping":1474137097},{"ipv4":"130.133.110.14","ipv6":"2001:6f8:1c3c:babe::14:1","port":33445,"tcp_ports":[33445],"public_key":"461FA3776EF0FA655F1A05477DF1B3B614F7D6B124F7DB1DD4FE3C08B03B640F","maintainer":"Manolis","location":"DE","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Spline tox bootstrap node","last_ping":1474137101},{"ipv4":"205.185.116.116","ipv6":"-","port":33445,"tcp_ports":[3389,33445],"public_key":"A179B09749AC826FF01F37A9613F6B57118AE014D4196A0E1105A98F93A54702","maintainer":"Busindre","location":"US","status_udp":true,"status_tcp":true,"version":"2014101200","motd":"tox-bootstrapd","last_ping":1474137098},{"ipv4":"198.98.51.198","ipv6":"2605:6400:1:fed5:22:45af:ec10:f329","port":33445,"tcp_ports":[33445,3389,443],"public_key":"1D5A5F2F5D6233058BF0259B09622FB40B482E4FA0931EB8FD3AB8E7BF7DAF6F","maintainer":"Busindre","location":"US","status_udp":true,"status_tcp":true,"version":"2014101200","motd":"tox-bootstrapd","last_ping":1474137098},{"ipv4":"139.162.217.110","ipv6":"-","port":33445,"tcp_ports":[33445,3389],"public_key":"0EEBE6304F4B3F6549F39A87FBB45751929F4833BA6AC5F35B6DFA79D01B4523","maintainer":"Kr9r0x","location":"GB","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox-bootstrapd","last_ping":1474137097},{"ipv4":"194.249.212.109","ipv6":"2001:1470:fbfe::109","port":33445,"tcp_ports":[3389,443,33445],"public_key":"3CEE1F054081E7A011234883BC4FC39F661A55B73637A5AC293DDF1251D9432B","maintainer":"fluke571","location":"SI","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox-bootstrapd","last_ping":1474137098},{"ipv4":"185.25.116.107","ipv6":"2a00:7a60:0:746b::3","port":33445,"tcp_ports":[33445,3389],"public_key":"DA4E4ED4B697F2E9B000EEFE3A34B554ACD3F45F5C96EAEA2516DD7FF9AF7B43","maintainer":"MAH69K","location":"UA","status_udp":true,"status_tcp":true,"version":"","motd":"","last_ping":1474137102},{"ipv4":"192.99.168.140","ipv6":"-","port":33445,"tcp_ports":[33445,3389],"public_key":"6A4D0607A296838434A6A7DDF99F50EF9D60A2C510BBF31FE538A25CB6B4652F","maintainer":"WIeschie","location":"CA","status_udp":true,"status_tcp":true,"version":"2014101200","motd":"tox-bootstrapd","last_ping":1474137098},{"ipv4":"95.215.46.114","ipv6":"2a02:7aa0:1619::bdbd:17b8","port":33445,"tcp_ports":[33445,3389],"public_key":"5823FB947FF24CF83DDFAC3F3BAA18F96EA2018B16CC08429CB97FA502F40C23","maintainer":"Rotkaermota","location":"SE","status_udp":true,"status_tcp":true,"version":"","motd":"","last_ping":1474137102},{"ipv4":"5.189.176.217","ipv6":"2a02:c200:1:10:3:1:605:1337","port":5190,"tcp_ports":[33445,5190,3389],"public_key":"2B2137E094F743AC8BD44652C55F41DFACC502F125E99E4FE24D40537489E32F","maintainer":"tastytea","location":"DE","status_udp":true,"status_tcp":true,"version":"","motd":"","last_ping":1474137101},{"ipv4":"148.251.23.146","ipv6":"2a01:4f8:201:8493::2","port":2306,"tcp_ports":[33445,2306],"public_key":"7AED21F94D82B05774F697B209628CD5A9AD17E0C073D9329076A4C28ED28147","maintainer":"pucetox","location":"DE","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"by pucetox,\n sync your nodes here tox.0x10k.com/bootstrapd-conf , \n for communication: 1D1C0B992DEB6D7F18561176F7F5E572BCC7F2BA5CFA7E9E437B9134122CE96D906A6119F9D2","last_ping":1474137097},{"ipv4":"104.223.122.15","ipv6":"2607:ff48:aa81:800::35eb:1","port":33445,"tcp_ports":[3389,33445],"public_key":"0FB96EEBFB1650DDB52E70CF773DDFCABE25A95CC3BB50FC251082E4B63EF82A","maintainer":"ru_maniac","location":"US","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox id for queries and general info: EBD2A7B649ABB10ED9F47E5113F04000F39D46F087CEB62FCCE1069471FD6915256D197F2A97","last_ping":1474137098},{"ipv4":"tox.verdict.gg","ipv6":"-","port":33445,"tcp_ports":[33445,3389],"public_key":"1C5293AEF2114717547B39DA8EA6F1E331E5E358B35F9B6B5F19317911C5F976","maintainer":"Deliran","location":"DE","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Since 2015","last_ping":1474137098},{"ipv4":"d4rk4.ru","ipv6":"-","port":1813,"tcp_ports":[1813],"public_key":"53737F6D47FA6BD2808F378E339AF45BF86F39B64E79D6D491C53A1D522E7039","maintainer":"D4rk4","location":"RU","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"TOX ID: 35EDC07AEB18B163E07EE33F6CDDA63969F394FF6A617CEAB22A7EBBEAAAF854C0EDFBD46898","last_ping":1474137102},{"ipv4":"81.4.110.149","ipv6":"2a00:d880:3:2::8bdc:f19","port":33445,"tcp_ports":[33445,3389],"public_key":"9E7BD4793FFECA7F32238FA2361040C09025ED3333744483CA6F3039BFF0211E","maintainer":"tibietigni","location":"NL","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Tibietigni.com node. Tox_id for communication: D36CC0B702621F48FDBC540A57124A744E5133C932E65ACCEBCABF2586A02455171717175989","last_ping":1474137097},{"ipv4":"95.31.20.151","ipv6":"-","port":33445,"tcp_ports":[3389],"public_key":"9CA69BB74DE7C056D1CC6B16AB8A0A38725C0349D187D8996766958584D39340","maintainer":"IgorNovgorodov","location":"RU","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"happy-new-year","last_ping":1474137101},{"ipv4":"51.254.84.212","ipv6":"2001:41d0:a:1a3b::18","port":33445,"tcp_ports":[3389,33445],"public_key":"AEC204B9A4501412D5F0BB67D9C81B5DB3EE6ADA64122D32A3E9B093D544327D","maintainer":"a68366","location":"FR","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Since 26.12.2015","last_ping":1474137097},{"ipv4":"5.135.59.163","ipv6":"-","port":33445,"tcp_ports":[3389,33445],"public_key":"2D320F971EF2CA18004416C2AAE7BA52BF7949DB34EA8E2E21AF67BD367BE211","maintainer":"Skey","location":"FR","status_udp":true,"status_tcp":true,"version":"2014101200","motd":"tox-bootstrapd","last_ping":1474137097},{"ipv4":"185.58.206.164","ipv6":"2a02:f680:1:1100::3313","port":33445,"tcp_ports":[3389,33445],"public_key":"24156472041E5F220D1FA11D9DF32F7AD697D59845701CDD7BE7D1785EB9DB39","maintainer":"ru_maniac","location":"RU","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"please note: running on iphy's fork!\nmore info on the matter: goo.gl/Gz5KhK \u0026 goo.gl/i2TZJr\n\ntox id for queries and general info: EBD2A7B649ABB10ED9F47E5113F04000F39D46F087CEB62FCCE1069471FD6915256D197F2A97","last_ping":1474137098},{"ipv4":"128.199.199.197","ipv6":"2400:6180:0:d0::17a:a001","port":33445,"tcp_ports":[3389,33445],"public_key":"B05C8869DBB4EDDD308F43C1A974A20A725A36EACCA123862FDE9945BF9D3E09","maintainer":"wiiaam","location":"SG","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"apt-get install antox","last_ping":1474137098},{"ipv4":"bootybay.club","ipv6":"-","port":33445,"tcp_ports":[3389,33445],"public_key":"0CB9D8D636F8E3D71CF44A3019408A846B7BEDFA2810853355DB58C0A36BFE38","maintainer":"AssPirate","location":"AU","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox-bootstrapd","last_ping":1474137098},{"ipv4":"91.121.66.124","ipv6":"2001:41d0:1:757c::1","port":33445,"tcp_ports":[33445],"public_key":"4E3F7D37295664BBD0741B6DBCB6431D6CD77FC4105338C2FC31567BF5C8224A","maintainer":"h4nt3r","location":"FR","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox id for queries and general info: 3BC3C6875508A2EC86BE3E35E4FA9155E444CFA96671AE7D7D0D2585A0A5FA38E071A5E463E5","last_ping":1474137097},{"ipv4":"195.93.190.6","ipv6":"2a01:d0:ffff:a8a::2","port":33445,"tcp_ports":[33445],"public_key":"FB4CE0DDEFEED45F26917053E5D24BDDA0FA0A3D83A672A9DA2375928B37023D","maintainer":"strngr","location":"UA","status_udp":true,"status_tcp":true,"version":"","motd":"","last_ping":1474137105},{"ipv4":"loki.uplinklabs.net","ipv6":"loki.uplinklabs.net","port":33445,"tcp_ports":[3389,33445],"public_key":"1A56EA3EDF5DF4C0AEABBF3C2E4E603890F87E983CAC8A0D532A335F2C6E3E1F","maintainer":"AbacusAvenger","location":"US","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox-bootstrapd","last_ping":1474137098},{"ipv4":"95.215.44.78","ipv6":"2a02:7aa0:1619::c6fe:d0cb","port":33445,"tcp_ports":[33445,3389],"public_key":"672DBE27B4ADB9D5FB105A6BB648B2F8FDB89B3323486A7A21968316E012023C","maintainer":"HooinKyoma","location":"SE","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Thanx to Hooin Kyoma","last_ping":1474137098},{"ipv4":"tox.ntp.moscow","ipv6":"tox.ntp.moscow","port":33445,"tcp_ports":[33445,3389],"public_key":"80EF8660D9C5ACE1577BAB031375A0F08284CBFD9F810A857955DCC87377FC4D","maintainer":"abbat","location":"RU","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox-easy-bootstrap","last_ping":1474137098},{"ipv4":"146.185.136.123","ipv6":"2a03:b0c0:0:1010::389:1","port":33445,"tcp_ports":[33445,443,3389],"public_key":"09993FAF174DFFDC515B398A2EFC5639C4E6D7B736FC864F89786B50EAF88C1A","maintainer":"LittleVulpix","location":"NL","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"LittleTox - your friendly neighbourhood tox node from the land of windmills!","last_ping":1474137097},{"ipv4":"163.172.136.118","ipv6":"2001:bc8:4400:2100::1c:50f","port":33445,"tcp_ports":[33445,3389],"public_key":"2C289F9F37C20D09DA83565588BF496FAB3764853FA38141817A72E3F18ACA0B","maintainer":"LittleVulpix","location":"FR","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"LittleTox - your friendly neighbourhood tox node!","last_ping":1474137097},{"ipv4":"37.97.185.116","ipv6":"-","port":33445,"tcp_ports":[33445],"public_key":"E59A0E71ADA20D35BD1B0957059D7EF7E7792B3D680AE25C6F4DBBA09114D165","maintainer":"Yani","location":"NL","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Yani's node of pleasure and leisure","last_ping":1474137097},{"ipv4":"193.124.186.205","ipv6":"2a02:f680:1:1100::542a","port":5228,"tcp_ports":[443,3389,33445],"public_key":"9906D65F2A4751068A59D30505C5FC8AE1A95E0843AE9372EAFA3BAB6AC16C2C","maintainer":"Cactus","location":"RU","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox-bootstrapd","last_ping":1474137098},{"ipv4":"80.87.193.193","ipv6":"2a01:230:2:6::46a8","port":33445,"tcp_ports":[33445,3389],"public_key":"B38255EE4B054924F6D79A5E6E5889EC94B6ADF6FE9906F97A3D01E3D083223A","maintainer":"linxon","location":"RU","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Free Linxon's TOX Bootstrap node","last_ping":1474137098},{"ipv4":"initramfs.io","ipv6":"-","port":33445,"tcp_ports":[33445,3389],"public_key":"3F0A45A268367C1BEA652F258C85F4A66DA76BCAA667A49E770BCC4917AB6A25","maintainer":"initramfs","location":"TW","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"initramfs' Tox DHT Node","last_ping":1474137099},{"ipv4":"tox.neverlocate.me","ipv6":"-","port":33445,"tcp_ports":[33445],"public_key":"49183DBF0E865713154069D1C7C7A2732ED78CF32C4D76AF5304FE31C5FEB81A","maintainer":"brandon","location":"US","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox-bootstrapd","last_ping":1474137102},{"ipv4":"shigure.eve.moe","ipv6":"shigure.eve.moe","port":33445,"tcp_ports":[3389,33445],"public_key":"1A480A53FAF2CBBFCC382D786C43E69EEE23F22C7C23A7CFEB6180A373E23E54","maintainer":"EveNeko","location":"GB","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox-bootstrapd@shigure.eve.moe","last_ping":1474137098},{"ipv4":"tox.deadteam.org","ipv6":"tox.deadteam.org","port":33445,"tcp_ports":[33445],"public_key":"C7D284129E83877D63591F14B3F658D77FF9BA9BA7293AEB2BDFBFE1A803AF47","maintainer":"DeadTeam","location":"DE","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Vive le TOX","last_ping":1474137101},{"ipv4":"prok.pw","ipv6":"-","port":33445,"tcp_ports":[3389,33445],"public_key":"69C3FEBB977687B64FA0213BDEB89A43463BB48DED288150CFFB6429EFF82436","maintainer":"Prototik","location":"RU","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Have a nice chatting!","last_ping":1474137098},{"ipv4":"maggie.prok.pw","ipv6":"maggie.prok.pw","port":33445,"tcp_ports":[33445,3389],"public_key":"B75583B6D967DB8AD7C6D3B6F9318194BCC79B2FEF18F69E2DF275B779E7AA30","maintainer":"Prototik","location":"DE","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Maggie wants a pacifier","last_ping":1474137101},{"ipv4":"108.61.165.198","ipv6":"2001:19f0:5000:8121:5054:ff:fe1c:9ded","port":33445,"tcp_ports":[],"public_key":"8E7D0B859922EF569298B4D261A8CCB5FEA14FB91ED412A7603A585A25698832","maintainer":"ray65536","location":"NL","status_udp":true,"status_tcp":false,"version":"2016010100","motd":"Ray's Tox Node","last_ping":1474137101},{"ipv4":"92.54.84.70","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"5625A62618CB4FCA70E147A71B29695F38CC65FF0CBD68AD46254585BE564802","maintainer":"t3mp","location":"RU","status_udp":true,"status_tcp":false,"version":"2016010100","motd":"tox-bootstrapd","last_ping":1474137102},{"ipv4":"srv1.ricin.im","ipv6":"-","port":1337,"tcp_ports":[],"public_key":"3651DAB570D7F60381F87B19D6935EE7F5FE01308DCE71C4B69993150C6A903C","maintainer":"Ricin.im","location":"FR","status_udp":true,"status_tcp":false,"version":"2016010100","motd":"Ricin.im Tox node. Enjoy babes \u003c3","last_ping":1474137101},{"ipv4":"46.101.197.175","ipv6":"2a03:b0c0:3:d0::ac:5001","port":443,"tcp_ports":[443,33445,3389],"public_key":"CD133B521159541FB1D326DE9850F5E56A6C724B5B8E5EB5CD8D950408E95707","maintainer":"clearmartin","location":"DE","status_udp":false,"status_tcp":true,"version":"","motd":"","last_ping":1474137105},{"ipv4":"toxnode.nek0.net","ipv6":"toxnode.nek0.net","port":33445,"tcp_ports":[3389,33445],"public_key":"20965721D32CE50C3E837DD75B33908B33037E6225110BFF209277AEAF3F9639","maintainer":"Phsm","location":"UA","status_udp":false,"status_tcp":true,"version":"","motd":"","last_ping":1474137107},{"ipv4":"sorunome.de","ipv6":"sorunome.de","port":33445,"tcp_ports":[33445,3389],"public_key":"02807CF4F8BB8FB390CC3794BDF1E8449E9A8392C5D3F2200019DA9F1E812E46","maintainer":"Sorunome","location":"DE","status_udp":false,"status_tcp":true,"version":"","motd":"","last_ping":1474137105},{"ipv4":"hibiki.eve.moe","ipv6":"hibiki.eve.moe","port":33445,"tcp_ports":[33445],"public_key":"D3EB45181B343C2C222A5BCF72B760638E15ED87904625AAD351C594EEFAE03E","maintainer":"EveNeko","location":"US","status_udp":false,"status_tcp":true,"version":"","motd":"","last_ping":1474137098},{"ipv4":"46.229.52.198","ipv6":"-","port":33445,"tcp_ports":[33445],"public_key":"813C8F4187833EF0655B10F7752141A352248462A567529A38B6BBF73E979307","maintainer":"Stranger","location":"UA","status_udp":false,"status_tcp":true,"version":"","motd":"","last_ping":1474137109},{"ipv4":"144.76.60.215","ipv6":"2a01:4f8:191:64d6::1","port":33445,"tcp_ports":[],"public_key":"04119E835DF3E78BACF0F84235B300546AF8B936F035185E2A8E9E0A67C8924F","maintainer":"sonOfRa","location":"DE","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"195.154.119.113","ipv6":"2001:bc8:3698:101::1","port":33445,"tcp_ports":[],"public_key":"E398A69646B8CEACA9F0B84F553726C1C49270558C57DF5F3C368F05A7D71354","maintainer":"Munrek","location":"FR","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"46.38.239.179","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"F5A1A38EFB6BD3C2C8AF8B10D85F0F89E931704D349F1D0720C3C4059AF2440A","maintainer":"MartinSchröder","location":"DE","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"104.167.101.29","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"5918AC3C06955962A75AD7DF4F80A5D7C34F7DB9E1498D2E0495DE35B3FE8A57","maintainer":"noisykeyboard","location":"CA","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"80.232.246.79","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"CF6CECA0A14A31717CC8501DA51BE27742B70746956E6676FF423A529F91ED5D","maintainer":"fUNKIAM","location":"LV","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"104.233.104.126","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"EDEE8F2E839A57820DE3DA4156D88350E53D4161447068A3457EE8F59F362414","maintainer":"wildermesser","location":"CA","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"home.vikingmakt.com.br","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"188E072676404ED833A4E947DC1D223DF8EFEBE5F5258573A236573688FB9761","maintainer":"umgeher","location":"BR","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"188.244.38.183","ipv6":"2001:470:de00:2:20c:29ff:fe68:354f","port":33445,"tcp_ports":[],"public_key":"15A0F9684E2423F9F46CFA5A50B562AE42525580D840CC50E518192BF333EE38","maintainer":"gem","location":"RU","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"mrflibble.c4.ee","ipv6":"2a02:16e0:0:12::4","port":33445,"tcp_ports":[],"public_key":"FAAB17014F42F7F20949F61E55F66A73C230876812A9737F5F6D2DCE4D9E4207","maintainer":"mrflibble","location":"GB","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"82.211.31.116","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"AF97B76392A6474AF2FD269220FDCF4127D86A42EF3A242DF53A40A268A2CD7C","maintainer":"Net.Verified","location":"RU","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"tox1.privacydragon.me","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"31910C0497D347FF160D6F3A6C0E317BAFA71E8E03BC4CBB2A185C9D4FB8B31E","maintainer":"PrivacyDragon","location":"US","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"zawertun.net","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"5521952892FBD5C185DF7180DB4DEF69D7844DEEE79B1F75A634ED9DF656756E","maintainer":"ZaWertun","location":"NL","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"87.98.168.93","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"C3F6C06A624FAE086DA94604A7838DB495769807EC055FADA36EBF2D4484FB33","maintainer":"_kinka_","location":"ES","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"185.61.253.189","ipv6":"2a04:ee00:0:9:20c:29ff:fe27:ad96","port":33445,"tcp_ports":[],"public_key":"73EEBCB4CBBE56BF0E0F01881DDD88C6B250BAE92CF487BE3FBE02FD830CE200","maintainer":"MAXL-SPB","location":"RU","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"109.75.40.105","ipv6":"2001:470:70d6::1","port":33445,"tcp_ports":[],"public_key":"2B9CD794424FD579044EC2FC5252B23DF8B4AAF239C25074F70B1090C3F8C83A","maintainer":"nek","location":"AM","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"185.120.34.64","ipv6":"2a06:8ec0:1:bb::3862","port":33445,"tcp_ports":[],"public_key":"728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854","maintainer":"Kostik","location":"GB","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0}]}
diff --git a/src/bootstrap.c b/src/bootstrap.c
index 0e2e1ed..244ecc1 100644
--- a/src/bootstrap.c
+++ b/src/bootstrap.c
@@ -23,23 +23,40 @@
#include
#include
#include
+#include
+#include
#include
#include "line_info.h"
#include "windows.h"
#include "misc_tools.h"
+#include "configdir.h"
+#include "curl_util.h"
extern struct arg_opts arg_opts;
+/* URL that we get the JSON encoded nodes list from. */
+#define NODES_LIST_URL "https://nodes.tox.chat/json"
+
+#define DEFAULT_NODES_FILENAME "DHTnodes"
/* Time to wait between bootstrap attempts */
#define TRY_BOOTSTRAP_INTERVAL 5
+/* Number of nodes to bootstrap to per try */
+#define NUM_BOOTSTRAP_NODES 5
+
+/* How often we should update the nodeslist file. */
+#define NODELIST_UPDATE_TIMEOUT (60*24*30)
+
#define IPv4_MAX_SIZE 64
#define PORT_MAX_SIZE 5
+#define LAST_SCAN_JSON_VALUE "\"last_scan\":"
+#define LAST_SCAN_JSON_VALUE_LEN (sizeof(LAST_SCAN_JSON_VALUE) - 1)
+
#define IPV4_JSON_VALUE "\"ipv4\":\""
#define IPV4_JSON_VALUE_LEN (sizeof(IPV4_JSON_VALUE) - 1)
@@ -62,24 +79,198 @@ static struct toxNodes {
char keys[MAXNODES][TOX_PUBLIC_KEY_SIZE];
} toxNodes;
-/* Load the DHT nodelist to memory from json formatted nodes file obtained at https://nodes.tox.chat/json.
+
+/* Return true if nodeslist pointed to by fp needs to be updated.
+ * This will be the case if the file is empty, has an invalid format,
+ * or if the file is older than the given timeout.
+ */
+static bool nodeslist_needs_update(const char *nodes_path)
+{
+ FILE *fp = fopen(nodes_path, "r+");
+
+ if (fp == NULL) {
+ return false;
+ }
+
+ /* last_scan value should be at beginning of file */
+ char line[LAST_SCAN_JSON_VALUE_LEN + 32];
+
+ if (fgets(line, sizeof(line), fp) == NULL) {
+ fclose(fp);
+ return true;
+ }
+
+ fclose(fp);
+
+ const char *last_scan_val = strstr(line, LAST_SCAN_JSON_VALUE);
+
+ if (last_scan_val == NULL) {
+ return true;
+ }
+
+ last_scan_val += LAST_SCAN_JSON_VALUE_LEN;
+ long long int last_scan = strtoll(last_scan_val, NULL, 10);
+
+ if (timed_out(last_scan, NODELIST_UPDATE_TIMEOUT)) {
+ return true;
+ }
+
+ return false;
+}
+
+/* Fetches the JSON encoded DHT nodeslist from NODES_LIST_URL.
*
* Return 0 on success.
- * Return -1 if nodelist file cannot be opened.
- * Return -2 if nodelist file cannot be parsed.
- * Return -3 if nodelist file does not contain any valid node entries.
+ * Return -1 on failure.
*/
-int load_DHT_nodelist(void)
+static int curl_fetch_nodes_JSON(struct Recv_Data *recv_data)
{
- const char *filename = !arg_opts.nodes_path[0] ? PACKAGE_DATADIR "/DHTnodes" : arg_opts.nodes_path;
- FILE *fp = fopen(filename, "r");
+ CURL *c_handle = curl_easy_init();
- if (fp == NULL)
+ if (c_handle == NULL) {
return -1;
+ }
+
+ struct curl_slist *headers = NULL;
+ headers = curl_slist_append(headers, "Content-Type: application/json");
+ headers = curl_slist_append(headers, "charsets: utf-8");
+
+ curl_easy_setopt(c_handle, CURLOPT_HTTPHEADER, headers);
+ curl_easy_setopt(c_handle, CURLOPT_URL, NODES_LIST_URL);
+ curl_easy_setopt(c_handle, CURLOPT_WRITEFUNCTION, write_lookup_data);
+ curl_easy_setopt(c_handle, CURLOPT_WRITEDATA, recv_data);
+ curl_easy_setopt(c_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
+ curl_easy_setopt(c_handle, CURLOPT_HTTPGET, 1L);
+
+ int proxy_ret = set_curl_proxy(c_handle, arg_opts.proxy_address, arg_opts.proxy_port, arg_opts.proxy_type);
+
+ if (proxy_ret != 0) {
+ fprintf(stderr, "set_curl_proxy() failed with error %d\n", proxy_ret);
+ return -1;
+ }
+
+ int ret = curl_easy_setopt(c_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
+
+ if (ret != CURLE_OK) {
+ fprintf(stderr, "TLSv1.2 could not be set (libcurl error %d)", ret);
+ return -1;
+ }
+
+ ret = curl_easy_setopt(c_handle, CURLOPT_SSL_CIPHER_LIST, TLS_CIPHER_SUITE_LIST);
+
+ if (ret != CURLE_OK) {
+ fprintf(stderr, "Failed to set TLS cipher list (libcurl error %d)", ret);
+ return -1;
+ }
+
+ ret = curl_easy_perform(c_handle);
+
+ if (ret != CURLE_OK) {
+ /* If system doesn't support any of the specified ciphers suites, fall back to default */
+ if (ret == CURLE_SSL_CIPHER) {
+ curl_easy_setopt(c_handle, CURLOPT_SSL_CIPHER_LIST, NULL);
+ ret = curl_easy_perform(c_handle);
+ }
+
+ if (ret != CURLE_OK) {
+ fprintf(stderr, "HTTPS lookup error (libcurl error %d)\n", ret);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/* Attempts to update the DHT nodeslist.
+ *
+ * Return 1 if list was updated successfully.
+ * Return 0 if list does not need to be updated.
+ * Return -1 if file cannot be opened.
+ * Return -2 if http lookup failed.
+ * Return -3 if http reponse was empty.
+ * Return -4 if data could not be written to disk.
+ */
+static int update_DHT_nodeslist(const char *nodes_path)
+{
+ if (!nodeslist_needs_update(nodes_path)) {
+ return 0;
+ }
+
+ FILE *fp = fopen(nodes_path, "r+");
+
+ if (fp == NULL) {
+ return -1;
+ }
+
+ struct Recv_Data recv_data;
+ memset(&recv_data, 0, sizeof(struct Recv_Data));
+
+ if (curl_fetch_nodes_JSON(&recv_data) == -1) {
+ fclose(fp);
+ return -2;
+ }
+
+ if (recv_data.length == 0) {
+ fclose(fp);
+ return -3;
+ }
+
+ if (fwrite(recv_data.data, recv_data.length, 1, fp) != 1) {
+ fclose(fp);
+ return -4;
+ }
+
+ fclose(fp);
+ return 1;
+}
+
+static void get_nodeslist_path(char *buf, size_t buf_size)
+{
+ char *config_dir = NULL;
+
+ if (arg_opts.nodes_path[0]) {
+ snprintf(buf, buf_size, "%s", arg_opts.nodes_path);
+ } else if ((config_dir = get_user_config_dir()) != NULL) {
+ snprintf(buf, buf_size, "%s%s%s", config_dir, CONFIGDIR, DEFAULT_NODES_FILENAME);
+ free(config_dir);
+ } else {
+ snprintf(buf, buf_size, "%s", DEFAULT_NODES_FILENAME);
+ }
+}
+
+/* Load the DHT nodeslist to memory from json encoded nodes file obtained at NODES_LIST_URL.
+ * TODO: Parse json using a proper library?
+ *
+ * Return 0 on success.
+ * Return -1 if nodeslist file cannot be opened or created.
+ * Return -2 if nodeslist file cannot be parsed.
+ * Return -3 if nodeslist file does not contain any valid node entries.
+ */
+int load_DHT_nodeslist(void)
+{
+ char nodes_path[PATH_MAX];
+ get_nodeslist_path(nodes_path, sizeof(nodes_path));
+
+ FILE *fp = NULL;
+
+ if (!file_exists(nodes_path)) {
+ if ((fp = fopen(nodes_path, "w+")) == NULL) {
+ return -1;
+ }
+ } else if ((fp = fopen(nodes_path, "r+")) == NULL) {
+ return -1;
+ }
+
+ int update_err = update_DHT_nodeslist(nodes_path);
+
+ if (update_err < 0) {
+ fprintf(stderr, "update_DHT_nodeslist() failed with error %d\n", update_err);
+ }
char line[MAX_NODELIST_SIZE];
if (fgets(line, sizeof(line), fp) == NULL) {
+ fclose(fp);
return -2;
}
@@ -124,8 +315,9 @@ int load_DHT_nodelist(void)
long int port = strtol(port_string, NULL, 10);
- if (port <= 0 || port > MAX_PORT_RANGE)
+ if (port <= 0 || port > MAX_PORT_RANGE) {
continue;
+ }
/* Extract key */
const char *key_start = strstr(port_start, KEY_JSON_VALUE);
@@ -145,7 +337,7 @@ int load_DHT_nodelist(void)
memcpy(key_string, key_start, TOX_PUBLIC_KEY_SIZE * 2);
key_string[TOX_PUBLIC_KEY_SIZE * 2] = 0;
- /* Add IP-Port-Key to nodes list */
+ /* Add entry to nodes list */
snprintf(toxNodes.nodes[toxNodes.lines], sizeof(toxNodes.nodes[toxNodes.lines]), "%s", ipv4_string);
toxNodes.ports[toxNodes.lines] = port;
@@ -155,34 +347,45 @@ int load_DHT_nodelist(void)
toxNodes.lines++;
}
- fclose(fp);
-
- if (toxNodes.lines == 0)
+ /* If nodeslist does not contain any valid entries we set the last_scan value
+ * to 0 so that it will fetch a new list the next time this function is called.
+ */
+ if (toxNodes.lines == 0) {
+ const char *s = "{\"last_scan\":0}";
+ rewind(fp);
+ fwrite(s, strlen(s), 1, fp); // Not much we can do if it fails
+ fclose(fp);
return -3;
+ }
+ fclose(fp);
return 0;
}
-/* Connects to a random DHT node listed in the DHTnodes file. */
+/* Connects to NUM_BOOTSTRAP_NODES random DHT nodes listed in the DHTnodes file. */
static void DHT_bootstrap(Tox *m)
{
if (toxNodes.lines == 0) {
return;
}
- size_t node = rand() % toxNodes.lines;
+ size_t i;
- TOX_ERR_BOOTSTRAP err;
- tox_bootstrap(m, toxNodes.nodes[node], toxNodes.ports[node], (uint8_t *) toxNodes.keys[node], &err);
+ for (i = 0; i < NUM_BOOTSTRAP_NODES; ++i) {
+ size_t node = rand() % toxNodes.lines;
- if (err != TOX_ERR_BOOTSTRAP_OK) {
- fprintf(stderr, "Failed to bootstrap %s:%d\n", toxNodes.nodes[node], toxNodes.ports[node]);
- }
+ TOX_ERR_BOOTSTRAP err;
+ tox_bootstrap(m, toxNodes.nodes[node], toxNodes.ports[node], (uint8_t *) toxNodes.keys[node], &err);
- tox_add_tcp_relay(m, toxNodes.nodes[node], toxNodes.ports[node], (uint8_t *) toxNodes.keys[node], &err);
+ if (err != TOX_ERR_BOOTSTRAP_OK) {
+ fprintf(stderr, "Failed to bootstrap %s:%d\n", toxNodes.nodes[node], toxNodes.ports[node]);
+ }
- if (err != TOX_ERR_BOOTSTRAP_OK) {
- fprintf(stderr, "Failed to add TCP relay %s:%d\n", toxNodes.nodes[node], toxNodes.ports[node]);
+ tox_add_tcp_relay(m, toxNodes.nodes[node], toxNodes.ports[node], (uint8_t *) toxNodes.keys[node], &err);
+
+ if (err != TOX_ERR_BOOTSTRAP_OK) {
+ fprintf(stderr, "Failed to add TCP relay %s:%d\n", toxNodes.nodes[node], toxNodes.ports[node]);
+ }
}
}
diff --git a/src/bootstrap.h b/src/bootstrap.h
index e3dfab5..0159d3d 100644
--- a/src/bootstrap.h
+++ b/src/bootstrap.h
@@ -23,11 +23,12 @@
/* Manages connection to the Tox DHT network. */
void do_tox_connection(Tox *m);
-/* Load the DHT nodelist to memory from json formatted nodes file obtained attempts https://nodes.tox.chat/json.
+/* Load the DHT nodeslist to memory from json encoded nodes file obtained at NODES_LIST_URL.
+ * TODO: Parse json using a proper library?
*
* Return 0 on success.
- * Return -1 if nodelist file cannot be opened.
- * Return -2 if nodelist file cannot be parsed.
- * Return -3 if nodelist file does not contain any valid node entries.
+ * Return -1 if nodeslist file cannot be opened or created.
+ * Return -2 if nodeslist file cannot be parsed.
+ * Return -3 if nodeslist file does not contain any valid node entries.
*/
-int load_DHT_nodelist(void);
+int load_DHT_nodeslist(void);
diff --git a/src/configdir.c b/src/configdir.c
index d1e5f8d..ee97af3 100644
--- a/src/configdir.c
+++ b/src/configdir.c
@@ -33,7 +33,7 @@
#include "configdir.h"
#include "misc_tools.h"
-/* get the user's home directory */
+/* get the user's home directory. */
void get_home_dir(char *home, int size)
{
struct passwd pwd;
@@ -102,8 +102,10 @@ char *get_user_config_dir(void)
return user_config_dir;
}
-/*
- * Creates the config and chatlog directories.
+/* Creates the config and chatlog directories.
+ *
+ * Returns 0 on success.
+ * Returns -1 on failure.
*/
int create_user_config_dirs(char *path)
{
diff --git a/src/configdir.h b/src/configdir.h
index 69abffd..a5317c3 100644
--- a/src/configdir.h
+++ b/src/configdir.h
@@ -34,8 +34,23 @@
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif
+/**
+ * @brief Get the user's config directory.
+ *
+ * This is without a trailing slash. Resulting string must be freed.
+ *
+ * @return The users config dir or NULL on error.
+ */
char *get_user_config_dir(void);
+
+/* get the user's home directory. */
void get_home_dir(char *home, int size);
+
+/* Creates the config and chatlog directories.
+ *
+ * Returns 0 on success.
+ * Returns -1 on failure.
+ */
int create_user_config_dirs(char *path);
#endif /* #define CONFIGDIR_H */
diff --git a/src/curl_util.c b/src/curl_util.c
new file mode 100644
index 0000000..5ab2944
--- /dev/null
+++ b/src/curl_util.c
@@ -0,0 +1,93 @@
+/* curl_util.c
+ *
+ *
+ * Copyright (C) 2016 Toxic All Rights Reserved.
+ *
+ * This file is part of Toxic.
+ *
+ * Toxic is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Toxic is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Toxic. If not, see .
+ *
+ */
+
+#include
+#include
+
+#include
+#include
+
+#include "curl_util.h"
+
+/* Sets proxy info for given CURL handler.
+ *
+ * Returns 0 on success or if no proxy is set by the client.
+ * Returns -1 if proxy info is invalid.
+ * Returns an int > 0 on curl error (see: https://curl.haxx.se/libcurl/c/libcurl-errors.html)
+ */
+int set_curl_proxy(CURL *c_handle, const char *proxy_address, uint16_t port, uint8_t proxy_type)
+{
+ if (proxy_type == TOX_PROXY_TYPE_NONE)
+ return 0;
+
+ if (proxy_address == NULL || port == 0) {
+ return -1;
+ }
+
+ int ret = curl_easy_setopt(c_handle, CURLOPT_PROXYPORT, (long) port);
+
+ if (ret != CURLE_OK) {
+ return ret;
+ }
+
+ long int type = proxy_type == TOX_PROXY_TYPE_SOCKS5 ? CURLPROXY_SOCKS5_HOSTNAME : CURLPROXY_HTTP;
+
+ ret = curl_easy_setopt(c_handle, CURLOPT_PROXYTYPE, type);
+
+ if (ret != CURLE_OK) {
+ return ret;
+ }
+
+ ret = curl_easy_setopt(c_handle, CURLOPT_PROXY, proxy_address);
+
+ if (ret != CURLE_OK) {
+ return ret;
+ }
+
+ return 0;
+}
+
+/* Callback function for CURL to write received data.
+ *
+ * This function will append data from an http request to the data buffer
+ * until the request is complete or the buffer is full. Buffer will be null terminated.
+ *
+ * Returns number of bytes received from http request on success (don't change this).
+ * Returns 0 if data exceeds buffer size.
+ */
+size_t write_lookup_data(void *data, size_t size, size_t nmemb, void *user_pointer)
+{
+ struct Recv_Data *recv_data = (struct Recv_Data *) user_pointer;
+
+ size_t length = size * nmemb;
+ size_t total_size = length + recv_data->length;
+
+ if (total_size > MAX_RECV_CURL_DATA_SIZE) {
+ return 0;
+ }
+
+ memcpy(recv_data->data + recv_data->length, data, length);
+ recv_data->data[total_size] = '\0';
+ recv_data->length += length;
+
+ return length;
+}
diff --git a/src/curl_util.h b/src/curl_util.h
new file mode 100644
index 0000000..b6b67f1
--- /dev/null
+++ b/src/curl_util.h
@@ -0,0 +1,50 @@
+/* curl_util.h
+ *
+ *
+ * Copyright (C) 2016 Toxic All Rights Reserved.
+ *
+ * This file is part of Toxic.
+ *
+ * Toxic is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Toxic is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Toxic. If not, see .
+ *
+ */
+
+/* List based on Mozilla's recommended configurations for modern browsers */
+#define TLS_CIPHER_SUITE_LIST "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK"
+
+/* Max size of an http response that we can store in Recv_Data */
+#define MAX_RECV_CURL_DATA_SIZE 32767
+
+/* Holds data received from curl lookup */
+struct Recv_Data {
+ char data[MAX_RECV_CURL_DATA_SIZE + 1]; /* Data received from curl write data callback */
+ size_t length; /* Total number of bytes written to data buffer (doesn't include null) */
+};
+
+/* Sets proxy info for given CURL handler.
+ *
+ * Returns 0 on success or if no proxy is set by the client.
+ * Returns -1 if proxy info is invalid.
+ * Returns an int > 0 on curl error (see: https://curl.haxx.se/libcurl/c/libcurl-errors.html)
+ */
+int set_curl_proxy(CURL *c_handle, const char *proxy_address, uint16_t port, uint8_t proxy_type);
+
+/* Callback function for CURL to write received data.
+ *
+ * This function will append data from an http request to the data buffer
+ * until the request is complete or the buffer is full. Buffer will be null terminated.
+ *
+ * Returns size of bytes written to the data buffer.
+ */
+size_t write_lookup_data(void *data, size_t size, size_t nmemb, void *user_pointer);
diff --git a/src/name_lookup.c b/src/name_lookup.c
index 3fc7e36..863e9aa 100644
--- a/src/name_lookup.c
+++ b/src/name_lookup.c
@@ -22,7 +22,6 @@
#include
#include
-#include /* for u_char */
#include
#include "toxic.h"
@@ -31,6 +30,7 @@
#include "global_commands.h"
#include "misc_tools.h"
#include "configdir.h"
+#include "curl_util.h"
extern struct arg_opts arg_opts;
extern struct Winthread Winthread;;
@@ -41,9 +41,6 @@ extern struct Winthread Winthread;;
#define MAX_DOMAIN_SIZE 32
#define MAX_SERVER_LINE MAX_DOMAIN_SIZE + (SERVER_KEY_SIZE * 2) + 3
-/* List based on Mozilla's recommended configurations for modern browsers */
-#define TLS_CIPHER_SUITE_LIST "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK"
-
struct Nameservers {
int lines;
char names[MAX_SERVERS][MAX_DOMAIN_SIZE];
@@ -189,29 +186,6 @@ static bool get_domain_match(char *pubkey, char *out_domain, size_t out_domain_s
return false;
}
-#define MAX_RECV_LOOKUP_DATA_SIZE 1024
-
-/* Holds raw data received from name server */
-struct Recv_Data {
- char data[MAX_RECV_LOOKUP_DATA_SIZE];
- size_t size;
-};
-
-size_t write_lookup_data(void *data, size_t size, size_t nmemb, void *user_pointer)
-{
- struct Recv_Data *recv_data = (struct Recv_Data *) user_pointer;
- size_t real_size = size * nmemb;
-
- if (real_size >= MAX_RECV_LOOKUP_DATA_SIZE)
- return 0;
-
- memcpy(&recv_data->data, data, real_size);
- recv_data->size = real_size;
- recv_data->data[real_size] = '\0';
-
- return real_size;
-}
-
/* Converts Tox ID string contained in recv_data to binary format and puts it in thread's ID buffer.
*
* Returns 0 on success.
@@ -222,7 +196,7 @@ static int process_response(struct Recv_Data *recv_data)
{
size_t prefix_size = strlen(ID_PREFIX);
- if (recv_data->size < TOX_ADDRESS_SIZE * 2 + prefix_size)
+ if (recv_data->length < TOX_ADDRESS_SIZE * 2 + prefix_size)
return -1;
const char *IDstart = strstr(recv_data->data, ID_PREFIX);
@@ -243,47 +217,6 @@ static int process_response(struct Recv_Data *recv_data)
return 0;
}
-/* Sets proxy info for given CURL handler.
- *
- * Returns 0 on success or if no proxy is set by the client.
- * Returns -1 on failure.
- */
-static int set_lookup_proxy(ToxWindow *self, CURL *c_handle, const char *proxy_address, uint16_t port, uint8_t proxy_type)
-{
- if (proxy_type == TOX_PROXY_TYPE_NONE)
- return 0;
-
- if (proxy_address == NULL || port == 0) {
- lookup_error(self, "Unknown proxy error");
- return -1;
- }
-
- int ret = curl_easy_setopt(c_handle, CURLOPT_PROXYPORT, (long) port);
-
- if (ret != CURLE_OK) {
- lookup_error(self, "Failed to set proxy port (libcurl error %d)", ret);
- return -1;
- }
-
- long int type = proxy_type == TOX_PROXY_TYPE_SOCKS5 ? CURLPROXY_SOCKS5_HOSTNAME : CURLPROXY_HTTP;
-
- ret = curl_easy_setopt(c_handle, CURLOPT_PROXYTYPE, type);
-
- if (ret != CURLE_OK) {
- lookup_error(self, "Failed to set proxy type (libcurl error %d)", ret);
- return -1;
- }
-
- ret = curl_easy_setopt(c_handle, CURLOPT_PROXY, proxy_address);
-
- if (ret != CURLE_OK) {
- lookup_error(self, "Failed to set proxy (libcurl error %d)", ret);
- return -1;
- }
-
- return 0;
-}
-
void *lookup_thread_func(void *data)
{
ToxWindow *self = t_data.self;
@@ -333,8 +266,12 @@ void *lookup_thread_func(void *data)
curl_easy_setopt(c_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
curl_easy_setopt(c_handle, CURLOPT_POSTFIELDS, post_data);
- if (set_lookup_proxy(self, c_handle, arg_opts.proxy_address, arg_opts.proxy_port, arg_opts.proxy_type) == -1)
+ int proxy_ret = set_curl_proxy(c_handle, arg_opts.proxy_address, arg_opts.proxy_port, arg_opts.proxy_type);
+
+ if (proxy_ret != 0) {
+ lookup_error(self, "Failed to set proxy (error %d)\n");
goto on_exit;
+ }
int ret = curl_easy_setopt(c_handle, CURLOPT_USE_SSL, CURLUSESSL_ALL);
@@ -437,9 +374,9 @@ void name_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr,
* Returns -2 if the nameserver list cannot be found.
* Returns -3 if the nameserver list does not contain any valid entries.
*/
-int name_lookup_init(void)
+int name_lookup_init(int curl_init_status)
{
- if (curl_global_init(CURL_GLOBAL_ALL) != 0) {
+ if (curl_init_status != 0) {
t_data.disabled = true;
return -1;
}
@@ -454,8 +391,3 @@ int name_lookup_init(void)
return 0;
}
-
-void name_lookup_cleanup(void)
-{
- curl_global_cleanup();
-}
diff --git a/src/name_lookup.h b/src/name_lookup.h
index c1419d8..e9b8ed4 100644
--- a/src/name_lookup.h
+++ b/src/name_lookup.h
@@ -29,8 +29,7 @@
* Returns 0 on success.
* Returns -1 on failure.
*/
-int name_lookup_init(void);
-void name_lookup_cleanup(void);
+int name_lookup_init(int curl_init_status);
int name_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr, const char *message);
diff --git a/src/toxic.c b/src/toxic.c
index ab56f5c..2691656 100644
--- a/src/toxic.c
+++ b/src/toxic.c
@@ -41,6 +41,7 @@
#include
#include
+#include
#include
#include
@@ -164,7 +165,7 @@ void exit_toxic_success(Tox *m)
free_global_data();
tox_kill(m);
endwin();
- name_lookup_cleanup();
+ curl_global_cleanup();
#ifdef X11
/* We have to terminate xtra last coz reasons
@@ -455,6 +456,7 @@ int store_data(Tox *m, const char *path)
char *data = malloc(data_len * sizeof(char));
if (data == NULL) {
+ fclose(fp);
return -1;
}
@@ -465,6 +467,7 @@ int store_data(Tox *m, const char *path)
char *enc_data = malloc(enc_len * sizeof(char));
if (enc_data == NULL) {
+ fclose(fp);
free(data);
return -1;
}
@@ -580,14 +583,14 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, TOX_ERR_NEW
if (len == 0) {
fclose(fp);
- exit_toxic_err("failed in load_toxic", FATALERR_FILEOP);
+ exit_toxic_err("failed in load_tox", FATALERR_FILEOP);
}
char data[len];
if (fread(data, sizeof(data), 1, fp) != 1) {
fclose(fp);
- exit_toxic_err("failed in load_toxic", FATALERR_FILEOP);
+ exit_toxic_err("failed in load_tox", FATALERR_FILEOP);
}
bool is_encrypted = tox_is_data_encrypted((uint8_t *) data);
@@ -595,7 +598,7 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, TOX_ERR_NEW
/* attempt to encrypt an already encrypted data file */
if (arg_opts.encrypt_data && is_encrypted) {
fclose(fp);
- exit_toxic_err("failed in load_toxic", FATALERR_ENCRYPT);
+ exit_toxic_err("failed in load_tox", FATALERR_ENCRYPT);
}
if (arg_opts.unencrypt_data && is_encrypted)
@@ -681,7 +684,7 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, TOX_ERR_NEW
fclose(fp);
} else { /* Data file does not/should not exist */
if (file_exists(data_path))
- exit_toxic_err("failed in load_toxic", FATALERR_FILEOP);
+ exit_toxic_err("failed in load_tox", FATALERR_FILEOP);
tox_opts->savedata_type = TOX_SAVEDATA_TYPE_NONE;
@@ -691,7 +694,7 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, TOX_ERR_NEW
return NULL;
if (store_data(m, data_path) == -1)
- exit_toxic_err("failed in load_toxic", FATALERR_FILEOP);
+ exit_toxic_err("failed in load_tox", FATALERR_FILEOP);
}
return m;
@@ -920,10 +923,6 @@ static void parse_args(int argc, char *argv[])
case 'n':
snprintf(arg_opts.nodes_path, sizeof(arg_opts.nodes_path), "%s", optarg);
-
- if (!file_exists(arg_opts.nodes_path))
- queue_init_message("DHTnodes file not found");
-
break;
case 'o':
@@ -1092,6 +1091,7 @@ void DnD_callback(const char* asdv, DropType dt)
int main(int argc, char **argv)
{
+ update_unix_time();
parse_args(argc, argv);
/* Use the -b flag to enable stderr */
@@ -1125,16 +1125,12 @@ int main(int argc, char **argv)
const char *p = arg_opts.config_path[0] ? arg_opts.config_path : NULL;
- if (settings_load(user_settings, p) == -1)
+ if (settings_load(user_settings, p) == -1) {
queue_init_message("Failed to load user settings");
-
- int nodelist_ret = load_DHT_nodelist();
-
- if (nodelist_ret != 0) {
- queue_init_message("DHT nodelist failed to load (error %d). You can still connect manually with the /connect command.", nodelist_ret);
}
- int nameserver_ret = name_lookup_init();
+ int curl_init = curl_global_init(CURL_GLOBAL_ALL);
+ int nameserver_ret = name_lookup_init(curl_init);
if (nameserver_ret == -1) {
queue_init_message("curl failed to initialize; name lookup service is disabled.");
@@ -1144,6 +1140,12 @@ int main(int argc, char **argv)
queue_init_message("Name lookup server list does not contain any valid entries.");
}
+ int nodeslist_ret = load_DHT_nodeslist();
+
+ if (nodeslist_ret != 0) {
+ queue_init_message("DHT nodeslist failed to load (error %d)\n", nodeslist_ret);
+ }
+
#ifdef X11
if (init_xtra(DnD_callback) == -1)
queue_init_message("X failed to initialize");
diff --git a/src/windows.h b/src/windows.h
index c2a0760..21f1386 100644
--- a/src/windows.h
+++ b/src/windows.h
@@ -153,7 +153,7 @@ struct ToxWindow {
#ifdef VIDEO
int video_device_selection[2]; /* -1 if not set, if set uses these selections instead of primary video device */
-
+
#endif /* VIDEO */
#endif /* AUDIO */