summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriphydf <iphydf@users.noreply.github.com>2020-03-06 12:10:47 +0000
committeriphydf <iphydf@users.noreply.github.com>2020-03-11 15:21:43 +0000
commit64bf3695d99688ad0967bdba2207c46845a3e8c2 (patch)
tree11ad17034eeef07285eb3a2cbc7e2137136783a4
parentfd5511ad37b0a845645d944bf64e94abc3dc53a3 (diff)
Add a mutex lock/unlock inside every public API function.
-rw-r--r--.cirrus.yml2
-rw-r--r--.travis.yml1
-rwxr-xr-x.travis/bazel-linux6
-rw-r--r--toxcore/tox.api.h15
-rw-r--r--toxcore/tox.c536
-rw-r--r--toxcore/tox.h18
-rw-r--r--toxcore/tox_api.c2
7 files changed, 384 insertions, 196 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 54fedfb1..4ff2851a 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -1,7 +1,7 @@
1--- 1---
2cirrus-ci_task: 2cirrus-ci_task:
3 container: 3 container:
4 image: l.gcr.io/google/bazel:2.1.0 4 image: l.gcr.io/google/bazel:2.2.0
5 cpu: 8 5 cpu: 8
6 memory: 12G 6 memory: 12G
7 configure_script: 7 configure_script:
diff --git a/.travis.yml b/.travis.yml
index a0968fff..224f4dcc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,6 +6,7 @@
6# achieved using the "if: type IN (push, api, cron)" fields in the jobs list. 6# achieved using the "if: type IN (push, api, cron)" fields in the jobs list.
7 7
8language: c 8language: c
9dist: xenial
9os: linux 10os: linux
10 11
11jobs: 12jobs:
diff --git a/.travis/bazel-linux b/.travis/bazel-linux
index e009bfb9..eb496ed4 100755
--- a/.travis/bazel-linux
+++ b/.travis/bazel-linux
@@ -6,9 +6,9 @@ set -eu
6 6
7travis_install() { 7travis_install() {
8 # Get bazel. 8 # Get bazel.
9 wget https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh 9 wget https://github.com/bazelbuild/bazel/releases/download/2.2.0/bazel-2.2.0-installer-linux-x86_64.sh
10 chmod +x bazel-2.1.1-installer-linux-x86_64.sh 10 chmod +x bazel-2.2.0-installer-linux-x86_64.sh
11 ./bazel-2.1.1-installer-linux-x86_64.sh --user 11 ./bazel-2.2.0-installer-linux-x86_64.sh --user
12 echo 'build --jobs=4 --curses=no --verbose_failures' >> $HOME/.bazelrc 12 echo 'build --jobs=4 --curses=no --verbose_failures' >> $HOME/.bazelrc
13 echo 'build --config=linux' >> $HOME/.bazelrc 13 echo 'build --config=linux' >> $HOME/.bazelrc
14 echo "build --config=$CC" >> $HOME/.bazelrc 14 echo "build --config=$CC" >> $HOME/.bazelrc
diff --git a/toxcore/tox.api.h b/toxcore/tox.api.h
index e73402de..f9712b7e 100644
--- a/toxcore/tox.api.h
+++ b/toxcore/tox.api.h
@@ -623,6 +623,21 @@ static class options {
623 */ 623 */
624 any user_data; 624 any user_data;
625 } 625 }
626
627 /**
628 * These options are experimental, so avoid writing code that depends on
629 * them. Options marked "experimental" may change their behaviour or go away
630 * entirely in the future, or may be renamed to something non-experimental
631 * if they become part of the supported API.
632 */
633 namespace experimental {
634 /**
635 * Make public API functions thread-safe using a per-instance lock.
636 *
637 * Default: false.
638 */
639 bool thread_safety;
640 }
626 } 641 }
627 642
628 643
diff --git a/toxcore/tox.c b/toxcore/tox.c
index 530035f7..ebf3ab68 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -25,9 +25,11 @@
25#include "config.h" 25#include "config.h"
26#endif 26#endif
27 27
28#ifndef __cplusplus
28#ifndef _XOPEN_SOURCE 29#ifndef _XOPEN_SOURCE
29#define _XOPEN_SOURCE 600 30#define _XOPEN_SOURCE 600
30#endif 31#endif
32#endif
31 33
32#include "tox.h" 34#include "tox.h"
33 35
@@ -77,8 +79,11 @@
77#endif 79#endif
78 80
79struct Tox { 81struct Tox {
82 // XXX: Messenger *must* be the first member, because toxav casts its
83 // `Tox *` to `Messenger **`.
80 Messenger *m; 84 Messenger *m;
81 Mono_Time *mono_time; 85 Mono_Time *mono_time;
86 pthread_mutex_t *mutex;
82 87
83 tox_self_connection_status_cb *self_connection_status_callback; 88 tox_self_connection_status_cb *self_connection_status_callback;
84 tox_friend_name_cb *friend_name_callback; 89 tox_friend_name_cb *friend_name_callback;
@@ -103,6 +108,20 @@ struct Tox {
103 tox_friend_lossless_packet_cb *friend_lossless_packet_callback; 108 tox_friend_lossless_packet_cb *friend_lossless_packet_callback;
104}; 109};
105 110
111static void lock(const Tox *tox)
112{
113 if (tox->mutex != nullptr) {
114 pthread_mutex_lock(tox->mutex);
115 }
116}
117
118static void unlock(const Tox *tox)
119{
120 if (tox->mutex != nullptr) {
121 pthread_mutex_unlock(tox->mutex);
122 }
123}
124
106struct Tox_Userdata { 125struct Tox_Userdata {
107 Tox *tox; 126 Tox *tox;
108 void *user_data; 127 void *user_data;
@@ -509,14 +528,35 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
509 return nullptr; 528 return nullptr;
510 } 529 }
511 530
531 if (tox_options_get_experimental_thread_safety(opts)) {
532 tox->mutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
533
534 if (tox->mutex == nullptr) {
535 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
536 tox_options_free(default_options);
537 free(tox);
538 return nullptr;
539 }
540
541
542 pthread_mutexattr_t attr;
543
544 pthread_mutexattr_init(&attr);
545 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
546 pthread_mutex_init(tox->mutex, &attr);
547 } else {
548 tox->mutex = nullptr;
549 }
550
551 lock(tox);
552
512 unsigned int m_error; 553 unsigned int m_error;
513 Messenger *const m = new_messenger(tox->mono_time, &m_options, &m_error); 554 tox->m = new_messenger(tox->mono_time, &m_options, &m_error);
514 tox->m = m;
515 555
516 // TODO(iphydf): Clarify this code, check for NULL before new_groupchats, so 556 // TODO(iphydf): Clarify this code, check for NULL before new_groupchats, so
517 // new_groupchats can assume m is non-NULL. 557 // new_groupchats can assume m is non-NULL.
518 if (!new_groupchats(tox->mono_time, m)) { 558 if (!new_groupchats(tox->mono_time, tox->m)) {
519 kill_messenger(m); 559 kill_messenger(tox->m);
520 560
521 if (m_error == MESSENGER_ERROR_PORT) { 561 if (m_error == MESSENGER_ERROR_PORT) {
522 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PORT_ALLOC); 562 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PORT_ALLOC);
@@ -528,6 +568,13 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
528 568
529 mono_time_free(tox->mono_time); 569 mono_time_free(tox->mono_time);
530 tox_options_free(default_options); 570 tox_options_free(default_options);
571 unlock(tox);
572
573 if (tox->mutex != nullptr) {
574 pthread_mutex_destroy(tox->mutex);
575 }
576
577 free(tox->mutex);
531 free(tox); 578 free(tox);
532 return nullptr; 579 return nullptr;
533 } 580 }
@@ -536,35 +583,37 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
536 && tox_load(tox, tox_options_get_savedata_data(opts), tox_options_get_savedata_length(opts)) == -1) { 583 && tox_load(tox, tox_options_get_savedata_data(opts), tox_options_get_savedata_length(opts)) == -1) {
537 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT); 584 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
538 } else if (load_savedata_sk) { 585 } else if (load_savedata_sk) {
539 load_secret_key(m->net_crypto, tox_options_get_savedata_data(opts)); 586 load_secret_key(tox->m->net_crypto, tox_options_get_savedata_data(opts));
540 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK); 587 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK);
541 } else { 588 } else {
542 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK); 589 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK);
543 } 590 }
544 591
545 m_callback_namechange(m, tox_friend_name_handler); 592 m_callback_namechange(tox->m, tox_friend_name_handler);
546 m_callback_core_connection(m, tox_self_connection_status_handler); 593 m_callback_core_connection(tox->m, tox_self_connection_status_handler);
547 m_callback_statusmessage(m, tox_friend_status_message_handler); 594 m_callback_statusmessage(tox->m, tox_friend_status_message_handler);
548 m_callback_userstatus(m, tox_friend_status_handler); 595 m_callback_userstatus(tox->m, tox_friend_status_handler);
549 m_callback_connectionstatus(m, tox_friend_connection_status_handler); 596 m_callback_connectionstatus(tox->m, tox_friend_connection_status_handler);
550 m_callback_typingchange(m, tox_friend_typing_handler); 597 m_callback_typingchange(tox->m, tox_friend_typing_handler);
551 m_callback_read_receipt(m, tox_friend_read_receipt_handler); 598 m_callback_read_receipt(tox->m, tox_friend_read_receipt_handler);
552 m_callback_friendrequest(m, tox_friend_request_handler); 599 m_callback_friendrequest(tox->m, tox_friend_request_handler);
553 m_callback_friendmessage(m, tox_friend_message_handler); 600 m_callback_friendmessage(tox->m, tox_friend_message_handler);
554 callback_file_control(m, tox_file_recv_control_handler); 601 callback_file_control(tox->m, tox_file_recv_control_handler);
555 callback_file_reqchunk(m, tox_file_chunk_request_handler); 602 callback_file_reqchunk(tox->m, tox_file_chunk_request_handler);
556 callback_file_sendrequest(m, tox_file_recv_handler); 603 callback_file_sendrequest(tox->m, tox_file_recv_handler);
557 callback_file_data(m, tox_file_recv_chunk_handler); 604 callback_file_data(tox->m, tox_file_recv_chunk_handler);
558 g_callback_group_invite(m->conferences_object, tox_conference_invite_handler); 605 g_callback_group_invite(tox->m->conferences_object, tox_conference_invite_handler);
559 g_callback_group_connected(m->conferences_object, tox_conference_connected_handler); 606 g_callback_group_connected(tox->m->conferences_object, tox_conference_connected_handler);
560 g_callback_group_message(m->conferences_object, tox_conference_message_handler); 607 g_callback_group_message(tox->m->conferences_object, tox_conference_message_handler);
561 g_callback_group_title(m->conferences_object, tox_conference_title_handler); 608 g_callback_group_title(tox->m->conferences_object, tox_conference_title_handler);
562 g_callback_peer_name(m->conferences_object, tox_conference_peer_name_handler); 609 g_callback_peer_name(tox->m->conferences_object, tox_conference_peer_name_handler);
563 g_callback_peer_list_changed(m->conferences_object, tox_conference_peer_list_changed_handler); 610 g_callback_peer_list_changed(tox->m->conferences_object, tox_conference_peer_list_changed_handler);
564 custom_lossy_packet_registerhandler(m, tox_friend_lossy_packet_handler); 611 custom_lossy_packet_registerhandler(tox->m, tox_friend_lossy_packet_handler);
565 custom_lossless_packet_registerhandler(m, tox_friend_lossless_packet_handler); 612 custom_lossless_packet_registerhandler(tox->m, tox_friend_lossless_packet_handler);
566 613
567 tox_options_free(default_options); 614 tox_options_free(default_options);
615
616 unlock(tox);
568 return tox; 617 return tox;
569} 618}
570 619
@@ -574,11 +623,18 @@ void tox_kill(Tox *tox)
574 return; 623 return;
575 } 624 }
576 625
577 Messenger *m = tox->m; 626 lock(tox);
578 LOGGER_ASSERT(m->log, m->msi_packet == nullptr, "Attempted to kill tox while toxav is still alive"); 627 LOGGER_ASSERT(tox->m->log, tox->m->msi_packet == nullptr, "Attempted to kill tox while toxav is still alive");
579 kill_groupchats(m->conferences_object); 628 kill_groupchats(tox->m->conferences_object);
580 kill_messenger(m); 629 kill_messenger(tox->m);
581 mono_time_free(tox->mono_time); 630 mono_time_free(tox->mono_time);
631 unlock(tox);
632
633 if (tox->mutex != nullptr) {
634 pthread_mutex_destroy(tox->mutex);
635 free(tox->mutex);
636 }
637
582 free(tox); 638 free(tox);
583} 639}
584 640
@@ -594,11 +650,13 @@ static void end_save(uint8_t *data)
594 650
595size_t tox_get_savedata_size(const Tox *tox) 651size_t tox_get_savedata_size(const Tox *tox)
596{ 652{
597 const Messenger *m = tox->m; 653 lock(tox);
598 return 2 * sizeof(uint32_t) 654 size_t ret = 2 * sizeof(uint32_t)
599 + messenger_size(m) 655 + messenger_size(tox->m)
600 + conferences_size(m->conferences_object) 656 + conferences_size(tox->m->conferences_object)
601 + end_size(); 657 + end_size();
658 unlock(tox);
659 return ret;
602} 660}
603 661
604void tox_get_savedata(const Tox *tox, uint8_t *savedata) 662void tox_get_savedata(const Tox *tox, uint8_t *savedata)
@@ -609,6 +667,8 @@ void tox_get_savedata(const Tox *tox, uint8_t *savedata)
609 667
610 memset(savedata, 0, tox_get_savedata_size(tox)); 668 memset(savedata, 0, tox_get_savedata_size(tox));
611 669
670 lock(tox);
671
612 const uint32_t size32 = sizeof(uint32_t); 672 const uint32_t size32 = sizeof(uint32_t);
613 673
614 // write cookie 674 // write cookie
@@ -617,10 +677,11 @@ void tox_get_savedata(const Tox *tox, uint8_t *savedata)
617 host_to_lendian_bytes32(savedata, STATE_COOKIE_GLOBAL); 677 host_to_lendian_bytes32(savedata, STATE_COOKIE_GLOBAL);
618 savedata += size32; 678 savedata += size32;
619 679
620 const Messenger *m = tox->m; 680 savedata = messenger_save(tox->m, savedata);
621 savedata = messenger_save(m, savedata); 681 savedata = conferences_save(tox->m->conferences_object, savedata);
622 savedata = conferences_save(m->conferences_object, savedata);
623 end_save(savedata); 682 end_save(savedata);
683
684 unlock(tox);
624} 685}
625 686
626bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key, Tox_Err_Bootstrap *error) 687bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key, Tox_Err_Bootstrap *error)
@@ -647,14 +708,17 @@ bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *pub
647 708
648 unsigned int i; 709 unsigned int i;
649 710
711 lock(tox);
712
650 for (i = 0; i < count; ++i) { 713 for (i = 0; i < count; ++i) {
651 root[i].port = net_htons(port); 714 root[i].port = net_htons(port);
652 715
653 Messenger *m = tox->m; 716 onion_add_bs_path_node(tox->m->onion_c, root[i], public_key);
654 onion_add_bs_path_node(m->onion_c, root[i], public_key); 717 dht_bootstrap(tox->m->dht, root[i], public_key);
655 dht_bootstrap(m->dht, root[i], public_key);
656 } 718 }
657 719
720 unlock(tox);
721
658 net_freeipport(root); 722 net_freeipport(root);
659 723
660 if (count) { 724 if (count) {
@@ -691,13 +755,16 @@ bool tox_add_tcp_relay(Tox *tox, const char *host, uint16_t port, const uint8_t
691 755
692 unsigned int i; 756 unsigned int i;
693 757
758 lock(tox);
759
694 for (i = 0; i < count; ++i) { 760 for (i = 0; i < count; ++i) {
695 root[i].port = net_htons(port); 761 root[i].port = net_htons(port);
696 762
697 Messenger *m = tox->m; 763 add_tcp_relay(tox->m->net_crypto, root[i], public_key);
698 add_tcp_relay(m->net_crypto, root[i], public_key);
699 } 764 }
700 765
766 unlock(tox);
767
701 net_freeipport(root); 768 net_freeipport(root);
702 769
703 if (count) { 770 if (count) {
@@ -711,9 +778,9 @@ bool tox_add_tcp_relay(Tox *tox, const char *host, uint16_t port, const uint8_t
711 778
712Tox_Connection tox_self_get_connection_status(const Tox *tox) 779Tox_Connection tox_self_get_connection_status(const Tox *tox)
713{ 780{
714 const Messenger *m = tox->m; 781 lock(tox);
715 782 const unsigned int ret = onion_connection_status(tox->m->onion_c);
716 const unsigned int ret = onion_connection_status(m->onion_c); 783 unlock(tox);
717 784
718 if (ret == 2) { 785 if (ret == 2) {
719 return TOX_CONNECTION_UDP; 786 return TOX_CONNECTION_UDP;
@@ -734,55 +801,64 @@ void tox_callback_self_connection_status(Tox *tox, tox_self_connection_status_cb
734 801
735uint32_t tox_iteration_interval(const Tox *tox) 802uint32_t tox_iteration_interval(const Tox *tox)
736{ 803{
737 const Messenger *m = tox->m; 804 lock(tox);
738 return messenger_run_interval(m); 805 uint32_t ret = messenger_run_interval(tox->m);
806 unlock(tox);
807 return ret;
739} 808}
740 809
741void tox_iterate(Tox *tox, void *user_data) 810void tox_iterate(Tox *tox, void *user_data)
742{ 811{
812 lock(tox);
813
743 mono_time_update(tox->mono_time); 814 mono_time_update(tox->mono_time);
744 815
745 Messenger *m = tox->m;
746 struct Tox_Userdata tox_data = { tox, user_data }; 816 struct Tox_Userdata tox_data = { tox, user_data };
747 do_messenger(m, &tox_data); 817 do_messenger(tox->m, &tox_data);
748 do_groupchats(m->conferences_object, &tox_data); 818 do_groupchats(tox->m->conferences_object, &tox_data);
819
820 unlock(tox);
749} 821}
750 822
751void tox_self_get_address(const Tox *tox, uint8_t *address) 823void tox_self_get_address(const Tox *tox, uint8_t *address)
752{ 824{
753 if (address) { 825 if (address) {
754 const Messenger *m = tox->m; 826 lock(tox);
755 getaddress(m, address); 827 getaddress(tox->m, address);
828 unlock(tox);
756 } 829 }
757} 830}
758 831
759void tox_self_set_nospam(Tox *tox, uint32_t nospam) 832void tox_self_set_nospam(Tox *tox, uint32_t nospam)
760{ 833{
761 Messenger *m = tox->m; 834 lock(tox);
762 set_nospam(m->fr, net_htonl(nospam)); 835 set_nospam(tox->m->fr, net_htonl(nospam));
836 unlock(tox);
763} 837}
764 838
765uint32_t tox_self_get_nospam(const Tox *tox) 839uint32_t tox_self_get_nospam(const Tox *tox)
766{ 840{
767 const Messenger *m = tox->m; 841 lock(tox);
768 return net_ntohl(get_nospam(m->fr)); 842 uint32_t ret = net_ntohl(get_nospam(tox->m->fr));
843 unlock(tox);
844 return ret;
769} 845}
770 846
771void tox_self_get_public_key(const Tox *tox, uint8_t *public_key) 847void tox_self_get_public_key(const Tox *tox, uint8_t *public_key)
772{ 848{
773 const Messenger *m = tox->m;
774
775 if (public_key) { 849 if (public_key) {
776 memcpy(public_key, nc_get_self_public_key(m->net_crypto), CRYPTO_PUBLIC_KEY_SIZE); 850 lock(tox);
851 memcpy(public_key, nc_get_self_public_key(tox->m->net_crypto), CRYPTO_PUBLIC_KEY_SIZE);
852 unlock(tox);
777 } 853 }
778} 854}
779 855
780void tox_self_get_secret_key(const Tox *tox, uint8_t *secret_key) 856void tox_self_get_secret_key(const Tox *tox, uint8_t *secret_key)
781{ 857{
782 const Messenger *m = tox->m;
783
784 if (secret_key) { 858 if (secret_key) {
785 memcpy(secret_key, nc_get_self_secret_key(m->net_crypto), CRYPTO_SECRET_KEY_SIZE); 859 lock(tox);
860 memcpy(secret_key, nc_get_self_secret_key(tox->m->net_crypto), CRYPTO_SECRET_KEY_SIZE);
861 unlock(tox);
786 } 862 }
787} 863}
788 864
@@ -793,30 +869,35 @@ bool tox_self_set_name(Tox *tox, const uint8_t *name, size_t length, Tox_Err_Set
793 return 0; 869 return 0;
794 } 870 }
795 871
796 Messenger *m = tox->m; 872 lock(tox);
797 873
798 if (setname(m, name, length) == 0) { 874 if (setname(tox->m, name, length) == 0) {
799 // TODO(irungentoo): function to set different per group names? 875 // TODO(irungentoo): function to set different per group names?
800 send_name_all_groups(m->conferences_object); 876 send_name_all_groups(tox->m->conferences_object);
801 SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_OK); 877 SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_OK);
878 unlock(tox);
802 return 1; 879 return 1;
803 } 880 }
804 881
805 SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_TOO_LONG); 882 SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_TOO_LONG);
883 unlock(tox);
806 return 0; 884 return 0;
807} 885}
808 886
809size_t tox_self_get_name_size(const Tox *tox) 887size_t tox_self_get_name_size(const Tox *tox)
810{ 888{
811 const Messenger *m = tox->m; 889 lock(tox);
812 return m_get_self_name_size(m); 890 size_t ret = m_get_self_name_size(tox->m);
891 unlock(tox);
892 return ret;
813} 893}
814 894
815void tox_self_get_name(const Tox *tox, uint8_t *name) 895void tox_self_get_name(const Tox *tox, uint8_t *name)
816{ 896{
817 if (name) { 897 if (name) {
818 const Messenger *m = tox->m; 898 lock(tox);
819 getself_name(m, name); 899 getself_name(tox->m, name);
900 unlock(tox);
820 } 901 }
821} 902}
822 903
@@ -827,41 +908,48 @@ bool tox_self_set_status_message(Tox *tox, const uint8_t *status_message, size_t
827 return 0; 908 return 0;
828 } 909 }
829 910
830 Messenger *m = tox->m; 911 lock(tox);
831 912
832 if (m_set_statusmessage(m, status_message, length) == 0) { 913 if (m_set_statusmessage(tox->m, status_message, length) == 0) {
833 SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_OK); 914 SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_OK);
915 unlock(tox);
834 return 1; 916 return 1;
835 } 917 }
836 918
837 SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_TOO_LONG); 919 SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_TOO_LONG);
920 unlock(tox);
838 return 0; 921 return 0;
839} 922}
840 923
841size_t tox_self_get_status_message_size(const Tox *tox) 924size_t tox_self_get_status_message_size(const Tox *tox)
842{ 925{
843 const Messenger *m = tox->m; 926 lock(tox);
844 return m_get_self_statusmessage_size(m); 927 size_t ret = m_get_self_statusmessage_size(tox->m);
928 unlock(tox);
929 return ret;
845} 930}
846 931
847void tox_self_get_status_message(const Tox *tox, uint8_t *status_message) 932void tox_self_get_status_message(const Tox *tox, uint8_t *status_message)
848{ 933{
849 if (status_message) { 934 if (status_message) {
850 const Messenger *m = tox->m; 935 lock(tox);
851 m_copy_self_statusmessage(m, status_message); 936 m_copy_self_statusmessage(tox->m, status_message);
937 unlock(tox);
852 } 938 }
853} 939}
854 940
855void tox_self_set_status(Tox *tox, Tox_User_Status status) 941void tox_self_set_status(Tox *tox, Tox_User_Status status)
856{ 942{
857 Messenger *m = tox->m; 943 lock(tox);
858 m_set_userstatus(m, status); 944 m_set_userstatus(tox->m, status);
945 unlock(tox);
859} 946}
860 947
861Tox_User_Status tox_self_get_status(const Tox *tox) 948Tox_User_Status tox_self_get_status(const Tox *tox)
862{ 949{
863 const Messenger *m = tox->m; 950 lock(tox);
864 const uint8_t status = m_get_self_userstatus(m); 951 const uint8_t status = m_get_self_userstatus(tox->m);
952 unlock(tox);
865 return (Tox_User_Status)status; 953 return (Tox_User_Status)status;
866} 954}
867 955
@@ -911,15 +999,17 @@ uint32_t tox_friend_add(Tox *tox, const uint8_t *address, const uint8_t *message
911 return UINT32_MAX; 999 return UINT32_MAX;
912 } 1000 }
913 1001
914 Messenger *m = tox->m; 1002 lock(tox);
915 const int32_t ret = m_addfriend(m, address, message, length); 1003 const int32_t ret = m_addfriend(tox->m, address, message, length);
916 1004
917 if (ret >= 0) { 1005 if (ret >= 0) {
918 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_OK); 1006 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_OK);
1007 unlock(tox);
919 return ret; 1008 return ret;
920 } 1009 }
921 1010
922 set_friend_error(m->log, ret, error); 1011 set_friend_error(tox->m->log, ret, error);
1012 unlock(tox);
923 return UINT32_MAX; 1013 return UINT32_MAX;
924} 1014}
925 1015
@@ -930,22 +1020,25 @@ uint32_t tox_friend_add_norequest(Tox *tox, const uint8_t *public_key, Tox_Err_F
930 return UINT32_MAX; 1020 return UINT32_MAX;
931 } 1021 }
932 1022
933 Messenger *m = tox->m; 1023 lock(tox);
934 const int32_t ret = m_addfriend_norequest(m, public_key); 1024 const int32_t ret = m_addfriend_norequest(tox->m, public_key);
935 1025
936 if (ret >= 0) { 1026 if (ret >= 0) {
937 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_OK); 1027 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_OK);
1028 unlock(tox);
938 return ret; 1029 return ret;
939 } 1030 }
940 1031
941 set_friend_error(m->log, ret, error); 1032 set_friend_error(tox->m->log, ret, error);
1033 unlock(tox);
942 return UINT32_MAX; 1034 return UINT32_MAX;
943} 1035}
944 1036
945bool tox_friend_delete(Tox *tox, uint32_t friend_number, Tox_Err_Friend_Delete *error) 1037bool tox_friend_delete(Tox *tox, uint32_t friend_number, Tox_Err_Friend_Delete *error)
946{ 1038{
947 Messenger *m = tox->m; 1039 lock(tox);
948 const int ret = m_delfriend(m, friend_number); 1040 const int ret = m_delfriend(tox->m, friend_number);
1041 unlock(tox);
949 1042
950 // TODO(irungentoo): handle if realloc fails? 1043 // TODO(irungentoo): handle if realloc fails?
951 if (ret == -1) { 1044 if (ret == -1) {
@@ -964,8 +1057,9 @@ uint32_t tox_friend_by_public_key(const Tox *tox, const uint8_t *public_key, Tox
964 return UINT32_MAX; 1057 return UINT32_MAX;
965 } 1058 }
966 1059
967 const Messenger *m = tox->m; 1060 lock(tox);
968 const int32_t ret = getfriend_id(m, public_key); 1061 const int32_t ret = getfriend_id(tox->m, public_key);
1062 unlock(tox);
969 1063
970 if (ret == -1) { 1064 if (ret == -1) {
971 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND); 1065 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND);
@@ -983,27 +1077,32 @@ bool tox_friend_get_public_key(const Tox *tox, uint32_t friend_number, uint8_t *
983 return 0; 1077 return 0;
984 } 1078 }
985 1079
986 const Messenger *m = tox->m; 1080 lock(tox);
987 1081
988 if (get_real_pk(m, friend_number, public_key) == -1) { 1082 if (get_real_pk(tox->m, friend_number, public_key) == -1) {
989 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND); 1083 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND);
1084 unlock(tox);
990 return 0; 1085 return 0;
991 } 1086 }
992 1087
993 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK); 1088 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK);
1089 unlock(tox);
994 return 1; 1090 return 1;
995} 1091}
996 1092
997bool tox_friend_exists(const Tox *tox, uint32_t friend_number) 1093bool tox_friend_exists(const Tox *tox, uint32_t friend_number)
998{ 1094{
999 const Messenger *m = tox->m; 1095 lock(tox);
1000 return m_friend_exists(m, friend_number); 1096 bool ret = m_friend_exists(tox->m, friend_number);
1097 unlock(tox);
1098 return ret;
1001} 1099}
1002 1100
1003uint64_t tox_friend_get_last_online(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Get_Last_Online *error) 1101uint64_t tox_friend_get_last_online(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Get_Last_Online *error)
1004{ 1102{
1005 const Messenger *m = tox->m; 1103 lock(tox);
1006 const uint64_t timestamp = m_get_last_online(m, friend_number); 1104 const uint64_t timestamp = m_get_last_online(tox->m, friend_number);
1105 unlock(tox);
1007 1106
1008 if (timestamp == UINT64_MAX) { 1107 if (timestamp == UINT64_MAX) {
1009 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_LAST_ONLINE_FRIEND_NOT_FOUND); 1108 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_LAST_ONLINE_FRIEND_NOT_FOUND);
@@ -1016,23 +1115,27 @@ uint64_t tox_friend_get_last_online(const Tox *tox, uint32_t friend_number, Tox_
1016 1115
1017size_t tox_self_get_friend_list_size(const Tox *tox) 1116size_t tox_self_get_friend_list_size(const Tox *tox)
1018{ 1117{
1019 const Messenger *m = tox->m; 1118 lock(tox);
1020 return count_friendlist(m); 1119 size_t ret = count_friendlist(tox->m);
1120 unlock(tox);
1121 return ret;
1021} 1122}
1022 1123
1023void tox_self_get_friend_list(const Tox *tox, uint32_t *friend_list) 1124void tox_self_get_friend_list(const Tox *tox, uint32_t *friend_list)
1024{ 1125{
1025 if (friend_list) { 1126 if (friend_list) {
1026 const Messenger *m = tox->m; 1127 lock(tox);
1027 // TODO(irungentoo): size parameter? 1128 // TODO(irungentoo): size parameter?
1028 copy_friendlist(m, friend_list, tox_self_get_friend_list_size(tox)); 1129 copy_friendlist(tox->m, friend_list, count_friendlist(tox->m));
1130 unlock(tox);
1029 } 1131 }
1030} 1132}
1031 1133
1032size_t tox_friend_get_name_size(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error) 1134size_t tox_friend_get_name_size(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error)
1033{ 1135{
1034 const Messenger *m = tox->m; 1136 lock(tox);
1035 const int ret = m_get_name_size(m, friend_number); 1137 const int ret = m_get_name_size(tox->m, friend_number);
1138 unlock(tox);
1036 1139
1037 if (ret == -1) { 1140 if (ret == -1) {
1038 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); 1141 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
@@ -1050,8 +1153,9 @@ bool tox_friend_get_name(const Tox *tox, uint32_t friend_number, uint8_t *name,
1050 return 0; 1153 return 0;
1051 } 1154 }
1052 1155
1053 const Messenger *m = tox->m; 1156 lock(tox);
1054 const int ret = getname(m, friend_number, name); 1157 const int ret = getname(tox->m, friend_number, name);
1158 unlock(tox);
1055 1159
1056 if (ret == -1) { 1160 if (ret == -1) {
1057 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); 1161 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
@@ -1069,8 +1173,9 @@ void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *callback)
1069 1173
1070size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error) 1174size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error)
1071{ 1175{
1072 const Messenger *m = tox->m; 1176 lock(tox);
1073 const int ret = m_get_statusmessage_size(m, friend_number); 1177 const int ret = m_get_statusmessage_size(tox->m, friend_number);
1178 unlock(tox);
1074 1179
1075 if (ret == -1) { 1180 if (ret == -1) {
1076 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); 1181 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
@@ -1089,18 +1194,20 @@ bool tox_friend_get_status_message(const Tox *tox, uint32_t friend_number, uint8
1089 return false; 1194 return false;
1090 } 1195 }
1091 1196
1092 const Messenger *const m = tox->m; 1197 lock(tox);
1093 const int size = m_get_statusmessage_size(m, friend_number); 1198 const int size = m_get_statusmessage_size(tox->m, friend_number);
1094 1199
1095 if (size == -1) { 1200 if (size == -1) {
1096 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); 1201 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
1202 unlock(tox);
1097 return false; 1203 return false;
1098 } 1204 }
1099 1205
1100 const int ret = m_copy_statusmessage(m, friend_number, status_message, size); 1206 const int ret = m_copy_statusmessage(tox->m, friend_number, status_message, size);
1101 LOGGER_ASSERT(m->log, ret == size, "concurrency problem: friend status message changed"); 1207 LOGGER_ASSERT(tox->m->log, ret == size, "concurrency problem: friend status message changed");
1102 1208
1103 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK); 1209 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
1210 unlock(tox);
1104 return ret == size; 1211 return ret == size;
1105} 1212}
1106 1213
@@ -1111,9 +1218,9 @@ void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *
1111 1218
1112Tox_User_Status tox_friend_get_status(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error) 1219Tox_User_Status tox_friend_get_status(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error)
1113{ 1220{
1114 const Messenger *m = tox->m; 1221 lock(tox);
1115 1222 const int ret = m_get_userstatus(tox->m, friend_number);
1116 const int ret = m_get_userstatus(m, friend_number); 1223 unlock(tox);
1117 1224
1118 if (ret == USERSTATUS_INVALID) { 1225 if (ret == USERSTATUS_INVALID) {
1119 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); 1226 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
@@ -1131,9 +1238,9 @@ void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *callback)
1131 1238
1132Tox_Connection tox_friend_get_connection_status(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error) 1239Tox_Connection tox_friend_get_connection_status(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error)
1133{ 1240{
1134 const Messenger *m = tox->m; 1241 lock(tox);
1135 1242 const int ret = m_get_friend_connectionstatus(tox->m, friend_number);
1136 const int ret = m_get_friend_connectionstatus(m, friend_number); 1243 unlock(tox);
1137 1244
1138 if (ret == -1) { 1245 if (ret == -1) {
1139 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); 1246 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
@@ -1151,8 +1258,9 @@ void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_statu
1151 1258
1152bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error) 1259bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, Tox_Err_Friend_Query *error)
1153{ 1260{
1154 const Messenger *m = tox->m; 1261 lock(tox);
1155 const int ret = m_get_istyping(m, friend_number); 1262 const int ret = m_get_istyping(tox->m, friend_number);
1263 unlock(tox);
1156 1264
1157 if (ret == -1) { 1265 if (ret == -1) {
1158 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND); 1266 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
@@ -1170,14 +1278,16 @@ void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *callback)
1170 1278
1171bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool typing, Tox_Err_Set_Typing *error) 1279bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool typing, Tox_Err_Set_Typing *error)
1172{ 1280{
1173 Messenger *m = tox->m; 1281 lock(tox);
1174 1282
1175 if (m_set_usertyping(m, friend_number, typing) == -1) { 1283 if (m_set_usertyping(tox->m, friend_number, typing) == -1) {
1176 SET_ERROR_PARAMETER(error, TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND); 1284 SET_ERROR_PARAMETER(error, TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND);
1285 unlock(tox);
1177 return 0; 1286 return 0;
1178 } 1287 }
1179 1288
1180 SET_ERROR_PARAMETER(error, TOX_ERR_SET_TYPING_OK); 1289 SET_ERROR_PARAMETER(error, TOX_ERR_SET_TYPING_OK);
1290 unlock(tox);
1181 return 1; 1291 return 1;
1182} 1292}
1183 1293
@@ -1228,9 +1338,11 @@ uint32_t tox_friend_send_message(Tox *tox, uint32_t friend_number, Tox_Message_T
1228 return 0; 1338 return 0;
1229 } 1339 }
1230 1340
1231 Messenger *m = tox->m;
1232 uint32_t message_id = 0; 1341 uint32_t message_id = 0;
1233 set_message_error(m->log, m_send_message_generic(m, friend_number, type, message, length, &message_id), error); 1342 lock(tox);
1343 set_message_error(tox->m->log, m_send_message_generic(tox->m, friend_number, type, message, length, &message_id),
1344 error);
1345 unlock(tox);
1234 return message_id; 1346 return message_id;
1235} 1347}
1236 1348
@@ -1262,8 +1374,9 @@ bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length)
1262bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, Tox_File_Control control, 1374bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, Tox_File_Control control,
1263 Tox_Err_File_Control *error) 1375 Tox_Err_File_Control *error)
1264{ 1376{
1265 Messenger *m = tox->m; 1377 lock(tox);
1266 const int ret = file_control(m, friend_number, file_number, control); 1378 const int ret = file_control(tox->m, friend_number, file_number, control);
1379 unlock(tox);
1267 1380
1268 if (ret == 0) { 1381 if (ret == 0) {
1269 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_OK); 1382 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_OK);
@@ -1311,8 +1424,9 @@ bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, To
1311bool tox_file_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, 1424bool tox_file_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position,
1312 Tox_Err_File_Seek *error) 1425 Tox_Err_File_Seek *error)
1313{ 1426{
1314 Messenger *m = tox->m; 1427 lock(tox);
1315 const int ret = file_seek(m, friend_number, file_number, position); 1428 const int ret = file_seek(tox->m, friend_number, file_number, position);
1429 unlock(tox);
1316 1430
1317 if (ret == 0) { 1431 if (ret == 0) {
1318 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_OK); 1432 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_OK);
@@ -1363,8 +1477,9 @@ bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_
1363 return 0; 1477 return 0;
1364 } 1478 }
1365 1479
1366 const Messenger *m = tox->m; 1480 lock(tox);
1367 const int ret = file_get_id(m, friend_number, file_number, file_id); 1481 const int ret = file_get_id(tox->m, friend_number, file_number, file_id);
1482 unlock(tox);
1368 1483
1369 if (ret == 0) { 1484 if (ret == 0) {
1370 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_OK); 1485 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_OK);
@@ -1396,8 +1511,9 @@ uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t
1396 file_id = f_id; 1511 file_id = f_id;
1397 } 1512 }
1398 1513
1399 Messenger *m = tox->m; 1514 lock(tox);
1400 const long int file_num = new_filesender(m, friend_number, kind, file_size, file_id, filename, filename_length); 1515 const long int file_num = new_filesender(tox->m, friend_number, kind, file_size, file_id, filename, filename_length);
1516 unlock(tox);
1401 1517
1402 if (file_num >= 0) { 1518 if (file_num >= 0) {
1403 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_OK); 1519 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_OK);
@@ -1429,8 +1545,9 @@ uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t
1429bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, const uint8_t *data, 1545bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, const uint8_t *data,
1430 size_t length, Tox_Err_File_Send_Chunk *error) 1546 size_t length, Tox_Err_File_Send_Chunk *error)
1431{ 1547{
1432 Messenger *m = tox->m; 1548 lock(tox);
1433 const int ret = file_data(m, friend_number, file_number, position, data, length); 1549 const int ret = file_data(tox->m, friend_number, file_number, position, data, length);
1550 unlock(tox);
1434 1551
1435 if (ret == 0) { 1552 if (ret == 0) {
1436 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_OK); 1553 SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_OK);
@@ -1518,8 +1635,9 @@ void tox_callback_conference_peer_list_changed(Tox *tox, tox_conference_peer_lis
1518 1635
1519uint32_t tox_conference_new(Tox *tox, Tox_Err_Conference_New *error) 1636uint32_t tox_conference_new(Tox *tox, Tox_Err_Conference_New *error)
1520{ 1637{
1521 Messenger *m = tox->m; 1638 lock(tox);
1522 const int ret = add_groupchat(m->conferences_object, GROUPCHAT_TYPE_TEXT); 1639 const int ret = add_groupchat(tox->m->conferences_object, GROUPCHAT_TYPE_TEXT);
1640 unlock(tox);
1523 1641
1524 if (ret == -1) { 1642 if (ret == -1) {
1525 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_NEW_INIT); 1643 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_NEW_INIT);
@@ -1532,8 +1650,9 @@ uint32_t tox_conference_new(Tox *tox, Tox_Err_Conference_New *error)
1532 1650
1533bool tox_conference_delete(Tox *tox, uint32_t conference_number, Tox_Err_Conference_Delete *error) 1651bool tox_conference_delete(Tox *tox, uint32_t conference_number, Tox_Err_Conference_Delete *error)
1534{ 1652{
1535 Messenger *m = tox->m; 1653 lock(tox);
1536 const int ret = del_groupchat(m->conferences_object, conference_number, true); 1654 const int ret = del_groupchat(tox->m->conferences_object, conference_number, true);
1655 unlock(tox);
1537 1656
1538 if (ret == -1) { 1657 if (ret == -1) {
1539 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_DELETE_CONFERENCE_NOT_FOUND); 1658 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_DELETE_CONFERENCE_NOT_FOUND);
@@ -1546,8 +1665,9 @@ bool tox_conference_delete(Tox *tox, uint32_t conference_number, Tox_Err_Confere
1546 1665
1547uint32_t tox_conference_peer_count(const Tox *tox, uint32_t conference_number, Tox_Err_Conference_Peer_Query *error) 1666uint32_t tox_conference_peer_count(const Tox *tox, uint32_t conference_number, Tox_Err_Conference_Peer_Query *error)
1548{ 1667{
1549 const Messenger *m = tox->m; 1668 lock(tox);
1550 const int ret = group_number_peers(m->conferences_object, conference_number, false); 1669 const int ret = group_number_peers(tox->m->conferences_object, conference_number, false);
1670 unlock(tox);
1551 1671
1552 if (ret == -1) { 1672 if (ret == -1) {
1553 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND); 1673 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
@@ -1561,8 +1681,9 @@ uint32_t tox_conference_peer_count(const Tox *tox, uint32_t conference_number, T
1561size_t tox_conference_peer_get_name_size(const Tox *tox, uint32_t conference_number, uint32_t peer_number, 1681size_t tox_conference_peer_get_name_size(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
1562 Tox_Err_Conference_Peer_Query *error) 1682 Tox_Err_Conference_Peer_Query *error)
1563{ 1683{
1564 const Messenger *m = tox->m; 1684 lock(tox);
1565 const int ret = group_peername_size(m->conferences_object, conference_number, peer_number, false); 1685 const int ret = group_peername_size(tox->m->conferences_object, conference_number, peer_number, false);
1686 unlock(tox);
1566 1687
1567 switch (ret) { 1688 switch (ret) {
1568 case -1: 1689 case -1:
@@ -1581,8 +1702,9 @@ size_t tox_conference_peer_get_name_size(const Tox *tox, uint32_t conference_num
1581bool tox_conference_peer_get_name(const Tox *tox, uint32_t conference_number, uint32_t peer_number, uint8_t *name, 1702bool tox_conference_peer_get_name(const Tox *tox, uint32_t conference_number, uint32_t peer_number, uint8_t *name,
1582 Tox_Err_Conference_Peer_Query *error) 1703 Tox_Err_Conference_Peer_Query *error)
1583{ 1704{
1584 const Messenger *m = tox->m; 1705 lock(tox);
1585 const int ret = group_peername(m->conferences_object, conference_number, peer_number, name, false); 1706 const int ret = group_peername(tox->m->conferences_object, conference_number, peer_number, name, false);
1707 unlock(tox);
1586 1708
1587 switch (ret) { 1709 switch (ret) {
1588 case -1: 1710 case -1:
@@ -1601,8 +1723,9 @@ bool tox_conference_peer_get_name(const Tox *tox, uint32_t conference_number, ui
1601bool tox_conference_peer_get_public_key(const Tox *tox, uint32_t conference_number, uint32_t peer_number, 1723bool tox_conference_peer_get_public_key(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
1602 uint8_t *public_key, Tox_Err_Conference_Peer_Query *error) 1724 uint8_t *public_key, Tox_Err_Conference_Peer_Query *error)
1603{ 1725{
1604 const Messenger *m = tox->m; 1726 lock(tox);
1605 const int ret = group_peer_pubkey(m->conferences_object, conference_number, peer_number, public_key, false); 1727 const int ret = group_peer_pubkey(tox->m->conferences_object, conference_number, peer_number, public_key, false);
1728 unlock(tox);
1606 1729
1607 switch (ret) { 1730 switch (ret) {
1608 case -1: 1731 case -1:
@@ -1621,8 +1744,9 @@ bool tox_conference_peer_get_public_key(const Tox *tox, uint32_t conference_numb
1621bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t conference_number, uint32_t peer_number, 1744bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
1622 Tox_Err_Conference_Peer_Query *error) 1745 Tox_Err_Conference_Peer_Query *error)
1623{ 1746{
1624 const Messenger *m = tox->m; 1747 lock(tox);
1625 const int ret = group_peernumber_is_ours(m->conferences_object, conference_number, peer_number); 1748 const int ret = group_peernumber_is_ours(tox->m->conferences_object, conference_number, peer_number);
1749 unlock(tox);
1626 1750
1627 switch (ret) { 1751 switch (ret) {
1628 case -1: 1752 case -1:
@@ -1645,8 +1769,9 @@ bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t conference_numb
1645uint32_t tox_conference_offline_peer_count(const Tox *tox, uint32_t conference_number, 1769uint32_t tox_conference_offline_peer_count(const Tox *tox, uint32_t conference_number,
1646 Tox_Err_Conference_Peer_Query *error) 1770 Tox_Err_Conference_Peer_Query *error)
1647{ 1771{
1648 const Messenger *m = tox->m; 1772 lock(tox);
1649 const int ret = group_number_peers(m->conferences_object, conference_number, true); 1773 const int ret = group_number_peers(tox->m->conferences_object, conference_number, true);
1774 unlock(tox);
1650 1775
1651 if (ret == -1) { 1776 if (ret == -1) {
1652 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND); 1777 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
@@ -1661,8 +1786,9 @@ size_t tox_conference_offline_peer_get_name_size(const Tox *tox, uint32_t confer
1661 uint32_t offline_peer_number, 1786 uint32_t offline_peer_number,
1662 Tox_Err_Conference_Peer_Query *error) 1787 Tox_Err_Conference_Peer_Query *error)
1663{ 1788{
1664 const Messenger *m = tox->m; 1789 lock(tox);
1665 const int ret = group_peername_size(m->conferences_object, conference_number, offline_peer_number, true); 1790 const int ret = group_peername_size(tox->m->conferences_object, conference_number, offline_peer_number, true);
1791 unlock(tox);
1666 1792
1667 switch (ret) { 1793 switch (ret) {
1668 case -1: 1794 case -1:
@@ -1682,8 +1808,9 @@ bool tox_conference_offline_peer_get_name(const Tox *tox, uint32_t conference_nu
1682 uint8_t *name, 1808 uint8_t *name,
1683 Tox_Err_Conference_Peer_Query *error) 1809 Tox_Err_Conference_Peer_Query *error)
1684{ 1810{
1685 const Messenger *m = tox->m; 1811 lock(tox);
1686 const int ret = group_peername(m->conferences_object, conference_number, offline_peer_number, name, true); 1812 const int ret = group_peername(tox->m->conferences_object, conference_number, offline_peer_number, name, true);
1813 unlock(tox);
1687 1814
1688 switch (ret) { 1815 switch (ret) {
1689 case -1: 1816 case -1:
@@ -1703,8 +1830,9 @@ bool tox_conference_offline_peer_get_public_key(const Tox *tox, uint32_t confere
1703 uint32_t offline_peer_number, 1830 uint32_t offline_peer_number,
1704 uint8_t *public_key, Tox_Err_Conference_Peer_Query *error) 1831 uint8_t *public_key, Tox_Err_Conference_Peer_Query *error)
1705{ 1832{
1706 const Messenger *m = tox->m; 1833 lock(tox);
1707 const int ret = group_peer_pubkey(m->conferences_object, conference_number, offline_peer_number, public_key, true); 1834 const int ret = group_peer_pubkey(tox->m->conferences_object, conference_number, offline_peer_number, public_key, true);
1835 unlock(tox);
1708 1836
1709 switch (ret) { 1837 switch (ret) {
1710 case -1: 1838 case -1:
@@ -1724,9 +1852,11 @@ uint64_t tox_conference_offline_peer_get_last_active(const Tox *tox, uint32_t co
1724 uint32_t offline_peer_number, 1852 uint32_t offline_peer_number,
1725 Tox_Err_Conference_Peer_Query *error) 1853 Tox_Err_Conference_Peer_Query *error)
1726{ 1854{
1727 const Messenger *m = tox->m;
1728 uint64_t last_active = UINT64_MAX; 1855 uint64_t last_active = UINT64_MAX;
1729 const int ret = group_frozen_last_active(m->conferences_object, conference_number, offline_peer_number, &last_active); 1856 lock(tox);
1857 const int ret = group_frozen_last_active(tox->m->conferences_object, conference_number, offline_peer_number,
1858 &last_active);
1859 unlock(tox);
1730 1860
1731 switch (ret) { 1861 switch (ret) {
1732 case -1: 1862 case -1:
@@ -1746,8 +1876,9 @@ bool tox_conference_set_max_offline(Tox *tox, uint32_t conference_number,
1746 uint32_t max_offline_peers, 1876 uint32_t max_offline_peers,
1747 Tox_Err_Conference_Set_Max_Offline *error) 1877 Tox_Err_Conference_Set_Max_Offline *error)
1748{ 1878{
1749 const Messenger *m = tox->m; 1879 lock(tox);
1750 const int ret = group_set_max_frozen(m->conferences_object, conference_number, max_offline_peers); 1880 const int ret = group_set_max_frozen(tox->m->conferences_object, conference_number, max_offline_peers);
1881 unlock(tox);
1751 1882
1752 if (ret == -1) { 1883 if (ret == -1) {
1753 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_CONFERENCE_NOT_FOUND); 1884 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_CONFERENCE_NOT_FOUND);
@@ -1761,8 +1892,9 @@ bool tox_conference_set_max_offline(Tox *tox, uint32_t conference_number,
1761bool tox_conference_invite(Tox *tox, uint32_t friend_number, uint32_t conference_number, 1892bool tox_conference_invite(Tox *tox, uint32_t friend_number, uint32_t conference_number,
1762 Tox_Err_Conference_Invite *error) 1893 Tox_Err_Conference_Invite *error)
1763{ 1894{
1764 Messenger *m = tox->m; 1895 lock(tox);
1765 const int ret = invite_friend(m->conferences_object, friend_number, conference_number); 1896 const int ret = invite_friend(tox->m->conferences_object, friend_number, conference_number);
1897 unlock(tox);
1766 1898
1767 switch (ret) { 1899 switch (ret) {
1768 case -1: 1900 case -1:
@@ -1785,8 +1917,9 @@ bool tox_conference_invite(Tox *tox, uint32_t friend_number, uint32_t conference
1785uint32_t tox_conference_join(Tox *tox, uint32_t friend_number, const uint8_t *cookie, size_t length, 1917uint32_t tox_conference_join(Tox *tox, uint32_t friend_number, const uint8_t *cookie, size_t length,
1786 Tox_Err_Conference_Join *error) 1918 Tox_Err_Conference_Join *error)
1787{ 1919{
1788 Messenger *m = tox->m; 1920 lock(tox);
1789 const int ret = join_groupchat(m->conferences_object, friend_number, GROUPCHAT_TYPE_TEXT, cookie, length); 1921 const int ret = join_groupchat(tox->m->conferences_object, friend_number, GROUPCHAT_TYPE_TEXT, cookie, length);
1922 unlock(tox);
1790 1923
1791 switch (ret) { 1924 switch (ret) {
1792 case -1: 1925 case -1:
@@ -1821,15 +1954,17 @@ uint32_t tox_conference_join(Tox *tox, uint32_t friend_number, const uint8_t *co
1821bool tox_conference_send_message(Tox *tox, uint32_t conference_number, Tox_Message_Type type, const uint8_t *message, 1954bool tox_conference_send_message(Tox *tox, uint32_t conference_number, Tox_Message_Type type, const uint8_t *message,
1822 size_t length, Tox_Err_Conference_Send_Message *error) 1955 size_t length, Tox_Err_Conference_Send_Message *error)
1823{ 1956{
1824 Messenger *m = tox->m; 1957 lock(tox);
1825 int ret = 0; 1958 int ret = 0;
1826 1959
1827 if (type == TOX_MESSAGE_TYPE_NORMAL) { 1960 if (type == TOX_MESSAGE_TYPE_NORMAL) {
1828 ret = group_message_send(m->conferences_object, conference_number, message, length); 1961 ret = group_message_send(tox->m->conferences_object, conference_number, message, length);
1829 } else { 1962 } else {
1830 ret = group_action_send(m->conferences_object, conference_number, message, length); 1963 ret = group_action_send(tox->m->conferences_object, conference_number, message, length);
1831 } 1964 }
1832 1965
1966 unlock(tox);
1967
1833 switch (ret) { 1968 switch (ret) {
1834 case -1: 1969 case -1:
1835 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_CONFERENCE_NOT_FOUND); 1970 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_CONFERENCE_NOT_FOUND);
@@ -1854,8 +1989,9 @@ bool tox_conference_send_message(Tox *tox, uint32_t conference_number, Tox_Messa
1854 1989
1855size_t tox_conference_get_title_size(const Tox *tox, uint32_t conference_number, Tox_Err_Conference_Title *error) 1990size_t tox_conference_get_title_size(const Tox *tox, uint32_t conference_number, Tox_Err_Conference_Title *error)
1856{ 1991{
1857 const Messenger *m = tox->m; 1992 lock(tox);
1858 const int ret = group_title_get_size(m->conferences_object, conference_number); 1993 const int ret = group_title_get_size(tox->m->conferences_object, conference_number);
1994 unlock(tox);
1859 1995
1860 switch (ret) { 1996 switch (ret) {
1861 case -1: 1997 case -1:
@@ -1874,8 +2010,9 @@ size_t tox_conference_get_title_size(const Tox *tox, uint32_t conference_number,
1874bool tox_conference_get_title(const Tox *tox, uint32_t conference_number, uint8_t *title, 2010bool tox_conference_get_title(const Tox *tox, uint32_t conference_number, uint8_t *title,
1875 Tox_Err_Conference_Title *error) 2011 Tox_Err_Conference_Title *error)
1876{ 2012{
1877 const Messenger *m = tox->m; 2013 lock(tox);
1878 const int ret = group_title_get(m->conferences_object, conference_number, title); 2014 const int ret = group_title_get(tox->m->conferences_object, conference_number, title);
2015 unlock(tox);
1879 2016
1880 switch (ret) { 2017 switch (ret) {
1881 case -1: 2018 case -1:
@@ -1894,8 +2031,9 @@ bool tox_conference_get_title(const Tox *tox, uint32_t conference_number, uint8_
1894bool tox_conference_set_title(Tox *tox, uint32_t conference_number, const uint8_t *title, size_t length, 2031bool tox_conference_set_title(Tox *tox, uint32_t conference_number, const uint8_t *title, size_t length,
1895 Tox_Err_Conference_Title *error) 2032 Tox_Err_Conference_Title *error)
1896{ 2033{
1897 Messenger *m = tox->m; 2034 lock(tox);
1898 const int ret = group_title_send(m->conferences_object, conference_number, title, length); 2035 const int ret = group_title_send(tox->m->conferences_object, conference_number, title, length);
2036 unlock(tox);
1899 2037
1900 switch (ret) { 2038 switch (ret) {
1901 case -1: 2039 case -1:
@@ -1917,22 +2055,26 @@ bool tox_conference_set_title(Tox *tox, uint32_t conference_number, const uint8_
1917 2055
1918size_t tox_conference_get_chatlist_size(const Tox *tox) 2056size_t tox_conference_get_chatlist_size(const Tox *tox)
1919{ 2057{
1920 const Messenger *m = tox->m; 2058 lock(tox);
1921 return count_chatlist(m->conferences_object); 2059 size_t ret = count_chatlist(tox->m->conferences_object);
2060 unlock(tox);
2061 return ret;
1922} 2062}
1923 2063
1924void tox_conference_get_chatlist(const Tox *tox, uint32_t *chatlist) 2064void tox_conference_get_chatlist(const Tox *tox, uint32_t *chatlist)
1925{ 2065{
1926 const Messenger *m = tox->m; 2066 lock(tox);
1927 const size_t list_size = tox_conference_get_chatlist_size(tox); 2067 const size_t list_size = count_chatlist(tox->m->conferences_object);
1928 copy_chatlist(m->conferences_object, chatlist, list_size); 2068 copy_chatlist(tox->m->conferences_object, chatlist, list_size);
2069 unlock(tox);
1929} 2070}
1930 2071
1931Tox_Conference_Type tox_conference_get_type(const Tox *tox, uint32_t conference_number, 2072Tox_Conference_Type tox_conference_get_type(const Tox *tox, uint32_t conference_number,
1932 Tox_Err_Conference_Get_Type *error) 2073 Tox_Err_Conference_Get_Type *error)
1933{ 2074{
1934 const Messenger *m = tox->m; 2075 lock(tox);
1935 const int ret = group_get_type(m->conferences_object, conference_number); 2076 const int ret = group_get_type(tox->m->conferences_object, conference_number);
2077 unlock(tox);
1936 2078
1937 if (ret == -1) { 2079 if (ret == -1) {
1938 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_GET_TYPE_CONFERENCE_NOT_FOUND); 2080 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_GET_TYPE_CONFERENCE_NOT_FOUND);
@@ -1945,7 +2087,10 @@ Tox_Conference_Type tox_conference_get_type(const Tox *tox, uint32_t conference_
1945 2087
1946bool tox_conference_get_id(const Tox *tox, uint32_t conference_number, uint8_t *id /* TOX_CONFERENCE_ID_SIZE bytes */) 2088bool tox_conference_get_id(const Tox *tox, uint32_t conference_number, uint8_t *id /* TOX_CONFERENCE_ID_SIZE bytes */)
1947{ 2089{
1948 return conference_get_id(tox->m->conferences_object, conference_number, id); 2090 lock(tox);
2091 bool ret = conference_get_id(tox->m->conferences_object, conference_number, id);
2092 unlock(tox);
2093 return ret;
1949} 2094}
1950 2095
1951// TODO(iphydf): Delete in 0.3.0. 2096// TODO(iphydf): Delete in 0.3.0.
@@ -1961,7 +2106,9 @@ uint32_t tox_conference_by_id(const Tox *tox, const uint8_t *id, Tox_Err_Confere
1961 return UINT32_MAX; 2106 return UINT32_MAX;
1962 } 2107 }
1963 2108
2109 lock(tox);
1964 const int32_t ret = conference_by_id(tox->m->conferences_object, id); 2110 const int32_t ret = conference_by_id(tox->m->conferences_object, id);
2111 unlock(tox);
1965 2112
1966 if (ret == -1) { 2113 if (ret == -1) {
1967 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_BY_ID_NOT_FOUND); 2114 SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_BY_ID_NOT_FOUND);
@@ -2032,8 +2179,6 @@ bool tox_friend_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_
2032 return 0; 2179 return 0;
2033 } 2180 }
2034 2181
2035 Messenger *m = tox->m;
2036
2037 if (length == 0) { 2182 if (length == 0) {
2038 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY); 2183 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY);
2039 return 0; 2184 return 0;
@@ -2046,7 +2191,9 @@ bool tox_friend_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_
2046 return 0; 2191 return 0;
2047 } 2192 }
2048 2193
2049 const int ret = m_send_custom_lossy_packet(m, friend_number, data, length); 2194 lock(tox);
2195 const int ret = m_send_custom_lossy_packet(tox->m, friend_number, data, length);
2196 unlock(tox);
2050 2197
2051 set_custom_packet_error(ret, error); 2198 set_custom_packet_error(ret, error);
2052 2199
@@ -2070,14 +2217,14 @@ bool tox_friend_send_lossless_packet(Tox *tox, uint32_t friend_number, const uin
2070 return 0; 2217 return 0;
2071 } 2218 }
2072 2219
2073 Messenger *m = tox->m;
2074
2075 if (length == 0) { 2220 if (length == 0) {
2076 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY); 2221 SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY);
2077 return 0; 2222 return 0;
2078 } 2223 }
2079 2224
2080 const int ret = send_custom_lossless_packet(m, friend_number, data, length); 2225 lock(tox);
2226 const int ret = send_custom_lossless_packet(tox->m, friend_number, data, length);
2227 unlock(tox);
2081 2228
2082 set_custom_packet_error(ret, error); 2229 set_custom_packet_error(ret, error);
2083 2230
@@ -2096,15 +2243,17 @@ void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb
2096void tox_self_get_dht_id(const Tox *tox, uint8_t *dht_id) 2243void tox_self_get_dht_id(const Tox *tox, uint8_t *dht_id)
2097{ 2244{
2098 if (dht_id) { 2245 if (dht_id) {
2099 const Messenger *m = tox->m; 2246 lock(tox);
2100 memcpy(dht_id, dht_get_self_public_key(m->dht), CRYPTO_PUBLIC_KEY_SIZE); 2247 memcpy(dht_id, dht_get_self_public_key(tox->m->dht), CRYPTO_PUBLIC_KEY_SIZE);
2248 unlock(tox);
2101 } 2249 }
2102} 2250}
2103 2251
2104uint16_t tox_self_get_udp_port(const Tox *tox, Tox_Err_Get_Port *error) 2252uint16_t tox_self_get_udp_port(const Tox *tox, Tox_Err_Get_Port *error)
2105{ 2253{
2106 const Messenger *m = tox->m; 2254 lock(tox);
2107 const uint16_t port = net_htons(net_port(m->net)); 2255 const uint16_t port = net_htons(net_port(tox->m->net));
2256 unlock(tox);
2108 2257
2109 if (port) { 2258 if (port) {
2110 SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK); 2259 SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK);
@@ -2117,13 +2266,16 @@ uint16_t tox_self_get_udp_port(const Tox *tox, Tox_Err_Get_Port *error)
2117 2266
2118uint16_t tox_self_get_tcp_port(const Tox *tox, Tox_Err_Get_Port *error) 2267uint16_t tox_self_get_tcp_port(const Tox *tox, Tox_Err_Get_Port *error)
2119{ 2268{
2120 const Messenger *m = tox->m; 2269 lock(tox);
2121 2270
2122 if (m->tcp_server) { 2271 if (tox->m->tcp_server) {
2123 SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK); 2272 SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK);
2124 return m->options.tcp_server_port; 2273 uint16_t ret = tox->m->options.tcp_server_port;
2274 unlock(tox);
2275 return ret;
2125 } 2276 }
2126 2277
2127 SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND); 2278 SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND);
2279 unlock(tox);
2128 return 0; 2280 return 0;
2129} 2281}
diff --git a/toxcore/tox.h b/toxcore/tox.h
index af6f3360..50e838f3 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -690,6 +690,20 @@ struct Tox_Options {
690 */ 690 */
691 void *log_user_data; 691 void *log_user_data;
692 692
693
694 /**
695 * These options are experimental, so avoid writing code that depends on
696 * them. Options marked "experimental" may change their behaviour or go away
697 * entirely in the future, or may be renamed to something non-experimental
698 * if they become part of the supported API.
699 */
700 /**
701 * Make public API functions thread-safe using a per-instance lock.
702 *
703 * Default: false.
704 */
705 bool experimental_thread_safety;
706
693}; 707};
694 708
695 709
@@ -753,6 +767,10 @@ void *tox_options_get_log_user_data(const struct Tox_Options *options);
753 767
754void tox_options_set_log_user_data(struct Tox_Options *options, void *user_data); 768void tox_options_set_log_user_data(struct Tox_Options *options, void *user_data);
755 769
770bool tox_options_get_experimental_thread_safety(const struct Tox_Options *options);
771
772void tox_options_set_experimental_thread_safety(struct Tox_Options *options, bool thread_safety);
773
756/** 774/**
757 * Initialises a Tox_Options object with the default options. 775 * Initialises a Tox_Options object with the default options.
758 * 776 *
diff --git a/toxcore/tox_api.c b/toxcore/tox_api.c
index 025c7456..8503f237 100644
--- a/toxcore/tox_api.c
+++ b/toxcore/tox_api.c
@@ -58,6 +58,7 @@ ACCESSORS(size_t, savedata_, length)
58ACCESSORS(tox_log_cb *, log_, callback) 58ACCESSORS(tox_log_cb *, log_, callback)
59ACCESSORS(void *, log_, user_data) 59ACCESSORS(void *, log_, user_data)
60ACCESSORS(bool,, local_discovery_enabled) 60ACCESSORS(bool,, local_discovery_enabled)
61ACCESSORS(bool,, experimental_thread_safety)
61 62
62const uint8_t *tox_options_get_savedata_data(const struct Tox_Options *options) 63const uint8_t *tox_options_get_savedata_data(const struct Tox_Options *options)
63{ 64{
@@ -80,6 +81,7 @@ void tox_options_default(struct Tox_Options *options)
80 tox_options_set_proxy_type(options, TOX_PROXY_TYPE_NONE); 81 tox_options_set_proxy_type(options, TOX_PROXY_TYPE_NONE);
81 tox_options_set_hole_punching_enabled(options, true); 82 tox_options_set_hole_punching_enabled(options, true);
82 tox_options_set_local_discovery_enabled(options, true); 83 tox_options_set_local_discovery_enabled(options, true);
84 tox_options_set_experimental_thread_safety(options, false);
83 } 85 }
84} 86}
85 87