diff --git a/src/twc-profile.c b/src/twc-profile.c index 86acabe..8071ab6 100644 --- a/src/twc-profile.c +++ b/src/twc-profile.c @@ -60,42 +60,6 @@ twc_profile_expanded_data_path(struct t_twc_profile *profile) return full_path; } -/** - * Try loading a Tox save file for a profile. - * - * Returns 0 on success, -1 on failure. - * - * TODO: support encrypted save files - */ -int -twc_profile_load_data(struct t_twc_profile *profile) -{ - char *full_path = twc_profile_expanded_data_path(profile); - FILE *file = fopen(full_path, "r"); - free(full_path); - - if (file) - { - // get file size - fseek(file, 0, SEEK_END); - size_t size = ftell(file); - rewind(file); - - // allocate a buffer and read file into it - uint8_t *data = malloc(sizeof(*data) * size); - fread(data, sizeof(uint8_t), size, file); - fclose(file); - - // try loading the data - int status = tox_load(profile->tox, data, size); - free(data); - - return status; - } - - return -1; -} - /** * Save a profile's Tox data to disk. * @@ -118,9 +82,9 @@ twc_profile_save_data_file(struct t_twc_profile *profile) free(dir_path); // save Tox data to a buffer - uint32_t size = tox_size(profile->tox); + uint32_t size = tox_get_savedata_size(profile->tox); uint8_t *data = malloc(size); - tox_save(profile->tox, data); + tox_get_savedata(profile->tox, data); // save buffer to a file FILE *file = fopen(full_path, "w"); @@ -191,15 +155,107 @@ twc_profile_new(const char *name) return profile; } +/** + * Load Tox options from WeeChat configuration files into a Tox_Options struct. + */ +void +twc_profile_set_options(struct Tox_Options *options, + struct t_twc_profile *profile) +{ + tox_options_default(options); + + const char *proxy_host = + TWC_PROFILE_OPTION_STRING(profile, TWC_PROFILE_OPTION_PROXY_ADDRESS); + if (proxy_host) + options->proxy_host = proxy_host; + + switch (TWC_PROFILE_OPTION_INTEGER(profile, TWC_PROFILE_OPTION_PROXY_TYPE)) + { + case TWC_PROXY_NONE: + options->proxy_type = TOX_PROXY_TYPE_NONE; + break; + case TWC_PROXY_SOCKS5: + options->proxy_type = TOX_PROXY_TYPE_SOCKS5; + break; + case TWC_PROXY_HTTP: + options->proxy_type = TOX_PROXY_TYPE_HTTP; + break; + } + + options->proxy_port = + TWC_PROFILE_OPTION_INTEGER(profile, TWC_PROFILE_OPTION_PROXY_PORT); + options->udp_enabled = + TWC_PROFILE_OPTION_BOOLEAN(profile, TWC_PROFILE_OPTION_UDP); + options->ipv6_enabled = + TWC_PROFILE_OPTION_BOOLEAN(profile, TWC_PROFILE_OPTION_IPV6); +} + +void +twc_tox_new_print_error(struct t_twc_profile *profile, + struct Tox_Options *options, + TOX_ERR_NEW error) +{ + switch (error) + { + case TOX_ERR_NEW_MALLOC: + weechat_printf(profile->buffer, + "%scould not load Tox (malloc error)", + weechat_prefix("error")); + break; + case TOX_ERR_NEW_PORT_ALLOC: + weechat_printf(profile->buffer, + "%scould not load Tox (failed to allocate a port)", + weechat_prefix("error")); + break; + case TOX_ERR_NEW_PROXY_BAD_TYPE: + weechat_printf(profile->buffer, + "%scould not load Tox (internal error; bad proxy type)", + weechat_prefix("error")); + break; + case TOX_ERR_NEW_PROXY_BAD_HOST: + weechat_printf(profile->buffer, + "%scould not load Tox (invalid proxy host: \"%s\")", + weechat_prefix("error"), options->proxy_host); + break; + case TOX_ERR_NEW_PROXY_BAD_PORT: + weechat_printf(profile->buffer, + "%scould not load Tox (invalid proxy port: \"%d\")", + weechat_prefix("error"), options->proxy_port); + break; + case TOX_ERR_NEW_PROXY_NOT_FOUND: + weechat_printf(profile->buffer, + "%scould not load Tox (proxy host not found: \"%s\")", + weechat_prefix("error"), options->proxy_host); + break; + case TOX_ERR_NEW_LOAD_ENCRYPTED: + weechat_printf(profile->buffer, + "%scould not load Tox (encrypted data files are not yet supported)", + weechat_prefix("error")); + break; + case TOX_ERR_NEW_LOAD_BAD_FORMAT: + weechat_printf(profile->buffer, + "%scould not load Tox (invalid data file, some data " + "may have been loaded; use -force to try using it)", + weechat_prefix("error")); + break; + default: + weechat_printf(profile->buffer, + "%scould not load Tox (unknown error %d)", + weechat_prefix("error"), error); + break; + } + +} + /** * Load a profile's Tox object, creating a new one if it can't be loaded from * disk, and bootstraps the Tox DHT. */ -void +enum t_twc_rc twc_profile_load(struct t_twc_profile *profile) { if (profile->tox) - return; + return TWC_RC_ERROR; if (!(profile->buffer)) { @@ -208,90 +264,73 @@ twc_profile_load(struct t_twc_profile *profile) NULL, NULL, twc_profile_buffer_close_callback, profile); if (!(profile->buffer)) - return; + return TWC_RC_ERROR; } weechat_printf(profile->buffer, - "%s%s: profile %s connecting", - weechat_prefix("network"), weechat_plugin->name, - profile->name); + "%s profile %s connecting", + weechat_prefix("network"), profile->name); // create Tox options object struct Tox_Options options; - tox_options_default(&options); - - char *proxy_type; - switch (TWC_PROFILE_OPTION_INTEGER(profile, TWC_PROFILE_OPTION_PROXY_TYPE)) - { - case TWC_PROXY_NONE: - options.proxy_type = TOX_PROXY_TYPE_NONE; - break; - case TWC_PROXY_SOCKS5: - options.proxy_type = TOX_PROXY_TYPE_SOCKS5; - proxy_type = "SOCKS5"; - break; - case TWC_PROXY_HTTP: - options.proxy_type = TOX_PROXY_TYPE_HTTP; - proxy_type = "HTTP"; - break; - } - - const char *proxy_host = - TWC_PROFILE_OPTION_STRING(profile, TWC_PROFILE_OPTION_PROXY_ADDRESS); - if (proxy_host) - options.proxy_host = proxy_host; - - options.proxy_port = - TWC_PROFILE_OPTION_INTEGER(profile, TWC_PROFILE_OPTION_PROXY_PORT); - options.udp_enabled = - TWC_PROFILE_OPTION_BOOLEAN(profile, TWC_PROFILE_OPTION_UDP); - options.ipv6_enabled = - TWC_PROFILE_OPTION_BOOLEAN(profile, TWC_PROFILE_OPTION_IPV6); + twc_profile_set_options(&options, profile); + // print a proxy message if (options.proxy_type != TOX_PROXY_TYPE_NONE) { - if (!options.proxy_host || !options.proxy_port) - { - weechat_printf(profile->buffer, - "%sproxy is enabled, but proxy information is " - "incomplete; aborting", - weechat_prefix("error")); - return; - } - else - { - weechat_printf(profile->buffer, - "%susing %s proxy %s:%d", - weechat_prefix("network"), - proxy_type, - options.proxy_host, options.proxy_port); - } + weechat_printf(profile->buffer, + "%susing %s proxy %s:%d", + weechat_prefix("network"), + options.proxy_type == TOX_PROXY_TYPE_HTTP ? "HTTP" : + TOX_PROXY_TYPE_SOCKS5 ? "SOCKS5" : + NULL, + options.proxy_host, options.proxy_port); + } + + // try loading data file + char *path = twc_profile_expanded_data_path(profile); + uint8_t *data; + size_t data_size = 0; + enum t_twc_rc data_rc = twc_read_file(path, &data, &data_size); + + if (data_rc == TWC_RC_ERROR_MALLOC) + { + weechat_printf(profile->buffer, + "%scould not load Tox data file, aborting (malloc error)", + weechat_prefix("error")); + return TWC_RC_ERROR_MALLOC; } // create Tox - profile->tox = tox_new(&options); - if (!(profile->tox)) + TOX_ERR_NEW rc; + profile->tox = tox_new(&options, data, data_size, &rc); + if (rc != TOX_ERR_NEW_OK) { - weechat_printf(profile->buffer, - "%scould not create Tox instance", - weechat_prefix("error")); - return; + twc_tox_new_print_error(profile, &options, rc); + return rc == TOX_ERR_NEW_MALLOC ? TWC_RC_ERROR_MALLOC : TWC_RC_ERROR; } - // try loading Tox saved data - // TODO: this can return -1 even if it does not fail - if (twc_profile_load_data(profile) == -1) + if (data_size == 0) { - // we failed to load - set some defaults - char *name; + // no data file loaded, set default name + const char *default_name = "Tox-WeeChat User"; + + const char *name; struct passwd *user_pwd; if ((user_pwd = getpwuid(geteuid()))) name = user_pwd->pw_name; else - name = "Tox-WeeChat User"; + name = default_name; - tox_set_name(profile->tox, - (uint8_t *)name, strlen(name)); + TOX_ERR_SET_INFO rc; + tox_self_set_name(profile->tox, + (uint8_t *)name, strlen(name), + &rc); + + if (rc == TOX_ERR_SET_INFO_TOO_LONG) + tox_self_set_name(profile->tox, + (uint8_t *)default_name, strlen(default_name), + NULL); } // bootstrap DHT @@ -300,16 +339,15 @@ twc_profile_load(struct t_twc_profile *profile) for (int i = 0; i < bootstrap_node_count; ++i) twc_bootstrap_random_node(profile->tox); - // start Tox_do loop + // start tox_iterate loop twc_do_timer_cb(profile, 0); // register Tox callbacks tox_callback_friend_message(profile->tox, twc_friend_message_callback, profile); - tox_callback_friend_action(profile->tox, twc_friend_action_callback, profile); - tox_callback_connection_status(profile->tox, twc_connection_status_callback, profile); - tox_callback_name_change(profile->tox, twc_name_change_callback, profile); - tox_callback_user_status(profile->tox, twc_user_status_callback, profile); - tox_callback_status_message(profile->tox, twc_status_message_callback, profile); + tox_callback_friend_connection_status(profile->tox, twc_connection_status_callback, profile); + tox_callback_friend_name(profile->tox, twc_name_change_callback, profile); + tox_callback_friend_status(profile->tox, twc_user_status_callback, profile); + tox_callback_friend_status_message(profile->tox, twc_status_message_callback, profile); tox_callback_friend_request(profile->tox, twc_friend_request_callback, profile); tox_callback_group_invite(profile->tox, twc_group_invite_callback, profile); tox_callback_group_message(profile->tox, twc_group_message_callback, profile); diff --git a/src/twc-profile.h b/src/twc-profile.h index 026e75b..dbfc5ab 100644 --- a/src/twc-profile.h +++ b/src/twc-profile.h @@ -93,7 +93,7 @@ twc_profile_init(); struct t_twc_profile * twc_profile_new(const char *name); -void +enum t_twc_rc twc_profile_load(struct t_twc_profile *profile); void diff --git a/src/twc-tox-callbacks.c b/src/twc-tox-callbacks.c index 907fdff..f74958f 100644 --- a/src/twc-tox-callbacks.c +++ b/src/twc-tox-callbacks.c @@ -38,24 +38,25 @@ twc_do_timer_cb(void *data, { struct t_twc_profile *profile = data; - tox_do(profile->tox); - struct t_hook *hook = weechat_hook_timer(tox_do_interval(profile->tox), 0, 1, - twc_do_timer_cb, profile); + tox_iterate(profile->tox); + struct t_hook *hook = weechat_hook_timer(tox_iteration_interval(profile->tox), + 0, 1, twc_do_timer_cb, profile); profile->tox_do_timer = hook; // check connection status - int connected = tox_isconnected(profile->tox); - twc_profile_set_online_status(profile, connected); + TOX_CONNECTION connection = tox_self_get_connection_status(profile->tox); + bool is_connected = connection == TOX_CONNECTION_TCP + || connection == TOX_CONNECTION_UDP; + twc_profile_set_online_status(profile, is_connected); return WEECHAT_RC_OK; } void -twc_handle_friend_message(Tox *tox, int32_t friend_number, - const uint8_t *message, uint16_t length, - void *data, - enum TWC_MESSAGE_TYPE message_type) - +twc_friend_message_callback(Tox *tox, uint32_t friend_number, + TOX_MESSAGE_TYPE type, + const uint8_t *message, size_t length, + void *data) { struct t_twc_profile *profile = data; struct t_twc_chat *chat = twc_chat_search_friend(profile, @@ -66,36 +67,15 @@ twc_handle_friend_message(Tox *tox, int32_t friend_number, char *message_nt = twc_null_terminate(message, length); twc_chat_print_message(chat, "", name, - message_nt, message_type); + message_nt, type); free(name); free(message_nt); } void -twc_friend_message_callback(Tox *tox, int32_t friend_number, - const uint8_t *message, uint16_t length, - void *data) -{ - twc_handle_friend_message(tox, friend_number, - message, length, - data, TWC_MESSAGE_TYPE_MESSAGE); -} - -void -twc_friend_action_callback(Tox *tox, int32_t friend_number, - const uint8_t *message, uint16_t length, - void *data) -{ - twc_handle_friend_message(tox, friend_number, - message, length, - data, TWC_MESSAGE_TYPE_ACTION); -} - -void -twc_connection_status_callback(Tox *tox, - int32_t friend_number, uint8_t status, - void *data) +twc_connection_status_callback(Tox *tox, uint32_t friend_number, + TOX_CONNECTION status, void *data) { struct t_twc_profile *profile = data; char *name = twc_get_name_nt(profile->tox, friend_number); @@ -120,8 +100,8 @@ twc_connection_status_callback(Tox *tox, } void -twc_name_change_callback(Tox *tox, int32_t friend_number, - const uint8_t *name, uint16_t length, +twc_name_change_callback(Tox *tox, uint32_t friend_number, + const uint8_t *name, size_t length, void *data) { struct t_twc_profile *profile = data; @@ -155,9 +135,8 @@ twc_name_change_callback(Tox *tox, int32_t friend_number, } void -twc_user_status_callback(Tox *tox, - int32_t friend_number, uint8_t status, - void *data) +twc_user_status_callback(Tox *tox, uint32_t friend_number, + TOX_USER_STATUS status, void *data) { struct t_twc_profile *profile = data; struct t_twc_chat *chat = twc_chat_search_friend(profile, @@ -168,8 +147,8 @@ twc_user_status_callback(Tox *tox, } void -twc_status_message_callback(Tox *tox, int32_t friend_number, - const uint8_t *message, uint16_t length, +twc_status_message_callback(Tox *tox, uint32_t friend_number, + const uint8_t *message, size_t length, void *data) { struct t_twc_profile *profile = data; @@ -182,7 +161,7 @@ twc_status_message_callback(Tox *tox, int32_t friend_number, void twc_friend_request_callback(Tox *tox, const uint8_t *public_key, - const uint8_t *message, uint16_t length, + const uint8_t *message, size_t length, void *data) { struct t_twc_profile *profile = data; diff --git a/src/twc-tox-callbacks.h b/src/twc-tox-callbacks.h index 3e2a3b9..f5e803b 100644 --- a/src/twc-tox-callbacks.h +++ b/src/twc-tox-callbacks.h @@ -27,38 +27,32 @@ twc_do_timer_cb(void *data, int remaining_calls); void -twc_friend_message_callback(Tox *tox, int32_t friend_number, - const uint8_t *message, uint16_t length, +twc_friend_message_callback(Tox *tox, uint32_t friend_number, + TOX_MESSAGE_TYPE type, + const uint8_t *message, size_t length, void *data); void -twc_friend_action_callback(Tox *tox, int32_t friend_number, - const uint8_t *message, uint16_t length, - void *data); +twc_connection_status_callback(Tox *tox, uint32_t friend_number, + TOX_CONNECTION status, void *data); void -twc_connection_status_callback(Tox *tox, - int32_t friend_number, uint8_t status, - void *data); - -void -twc_name_change_callback(Tox *tox, int32_t friend_number, - const uint8_t *name, uint16_t length, +twc_name_change_callback(Tox *tox, uint32_t friend_number, + const uint8_t *name, size_t length, void *data); void -twc_user_status_callback(Tox *tox, - int32_t friend_number, uint8_t status, - void *data); +twc_user_status_callback(Tox *tox, uint32_t friend_number, + TOX_USER_STATUS status, void *data); void -twc_status_message_callback(Tox *tox, int32_t friend_number, - const uint8_t *message, uint16_t length, +twc_status_message_callback(Tox *tox, uint32_t friend_number, + const uint8_t *message, size_t length, void *data); void twc_friend_request_callback(Tox *tox, const uint8_t *public_key, - const uint8_t *message, uint16_t length, + const uint8_t *message, size_t length, void *data); void diff --git a/src/twc-utils.c b/src/twc-utils.c index 2f7d668..0e8cf40 100644 --- a/src/twc-utils.c +++ b/src/twc-utils.c @@ -183,3 +183,36 @@ twc_hash_tox_id(const uint8_t *tox_id) return hash; } +/** + * Read an entire file into memory. + * + * @return TWC_RC_OK on success, TWC_RC_ERROR if file can not be opened, and + * TWC_RC_ERROR_MALLOC if an appropriate buffer can not be allocated. + */ +enum t_twc_rc +twc_read_file(const char *path, uint8_t **data, size_t *size) +{ + FILE *file; + if (file = fopen(path, "r")) + { + // get file size + fseek(file, 0, SEEK_END); + *size = ftell(file); + rewind(file); + + if (data = malloc(sizeof(*data) * *size)) + { + fread(data, sizeof(uint8_t), *size, file); + fclose(file); + return TWC_RC_OK; + } + else + { + fclose(file); + return TWC_RC_ERROR_MALLOC; + } + } + + return TWC_RC_ERROR; +} + diff --git a/src/twc-utils.h b/src/twc-utils.h index 8fae20f..a030576 100644 --- a/src/twc-utils.h +++ b/src/twc-utils.h @@ -54,5 +54,8 @@ twc_uint32_reverse_bytes(uint32_t num); unsigned long long twc_hash_tox_id(const uint8_t *tox_id); +enum t_twc_rc +twc_read_file(const char *path, uint8_t **data, size_t *size); + #endif // TOX_WEECHAT_UTILS_H diff --git a/src/twc.h b/src/twc.h index 7646201..0c5b252 100644 --- a/src/twc.h +++ b/src/twc.h @@ -23,7 +23,8 @@ extern struct t_weechat_plugin *weechat_plugin; /// Return codes used throughout Tox-WeeChat. -enum t_twc_rc { +enum t_twc_rc +{ TWC_RC_OK, /// Generic error return code. TWC_RC_ERROR,