diff options
Diffstat (limited to 'toxcore')
-rw-r--r-- | toxcore/Messenger.c | 82 | ||||
-rw-r--r-- | toxcore/Messenger.h | 14 | ||||
-rw-r--r-- | toxcore/tox.c | 33 | ||||
-rw-r--r-- | toxcore/tox.h | 52 |
4 files changed, 146 insertions, 35 deletions
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 911c92da..39572dd0 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c | |||
@@ -1023,13 +1023,58 @@ void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_ | |||
1023 | 1023 | ||
1024 | #define MAX_FILENAME_LENGTH 255 | 1024 | #define MAX_FILENAME_LENGTH 255 |
1025 | 1025 | ||
1026 | /* Copy the file transfer file id to file_id | ||
1027 | * | ||
1028 | * return 0 on success. | ||
1029 | * return -1 if friend not valid. | ||
1030 | * return -2 if filenumber not valid | ||
1031 | */ | ||
1032 | int file_get_id(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint8_t *file_id) | ||
1033 | { | ||
1034 | if (friend_not_valid(m, friendnumber)) | ||
1035 | return -1; | ||
1036 | |||
1037 | if (m->friendlist[friendnumber].status != FRIEND_ONLINE) | ||
1038 | return -2; | ||
1039 | |||
1040 | uint32_t temp_filenum; | ||
1041 | uint8_t send_receive, file_number; | ||
1042 | |||
1043 | if (filenumber >= (1 << 16)) { | ||
1044 | send_receive = 1; | ||
1045 | temp_filenum = (filenumber >> 16) - 1; | ||
1046 | } else { | ||
1047 | send_receive = 0; | ||
1048 | temp_filenum = filenumber; | ||
1049 | } | ||
1050 | |||
1051 | if (temp_filenum >= MAX_CONCURRENT_FILE_PIPES) | ||
1052 | return -2; | ||
1053 | |||
1054 | file_number = temp_filenum; | ||
1055 | |||
1056 | struct File_Transfers *ft; | ||
1057 | |||
1058 | if (send_receive) { | ||
1059 | ft = &m->friendlist[friendnumber].file_receiving[file_number]; | ||
1060 | } else { | ||
1061 | ft = &m->friendlist[friendnumber].file_sending[file_number]; | ||
1062 | } | ||
1063 | |||
1064 | if (ft->status == FILESTATUS_NONE) | ||
1065 | return -2; | ||
1066 | |||
1067 | memcpy(file_id, ft->id, FILE_ID_LENGTH); | ||
1068 | return 0; | ||
1069 | } | ||
1070 | |||
1026 | /* Send a file send request. | 1071 | /* Send a file send request. |
1027 | * Maximum filename length is 255 bytes. | 1072 | * Maximum filename length is 255 bytes. |
1028 | * return 1 on success | 1073 | * return 1 on success |
1029 | * return 0 on failure | 1074 | * return 0 on failure |
1030 | */ | 1075 | */ |
1031 | static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint32_t file_type, | 1076 | static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint32_t file_type, |
1032 | uint64_t filesize, const uint8_t *filename, uint16_t filename_length) | 1077 | uint64_t filesize, const uint8_t *file_id, const uint8_t *filename, uint16_t filename_length) |
1033 | { | 1078 | { |
1034 | if (friend_not_valid(m, friendnumber)) | 1079 | if (friend_not_valid(m, friendnumber)) |
1035 | return 0; | 1080 | return 0; |
@@ -1037,13 +1082,18 @@ static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t fi | |||
1037 | if (filename_length > MAX_FILENAME_LENGTH) | 1082 | if (filename_length > MAX_FILENAME_LENGTH) |
1038 | return 0; | 1083 | return 0; |
1039 | 1084 | ||
1040 | uint8_t packet[1 + sizeof(file_type) + sizeof(filesize) + filename_length]; | 1085 | uint8_t packet[1 + sizeof(file_type) + sizeof(filesize) + FILE_ID_LENGTH + filename_length]; |
1041 | packet[0] = filenumber; | 1086 | packet[0] = filenumber; |
1042 | file_type = htonl(file_type); | 1087 | file_type = htonl(file_type); |
1043 | memcpy(packet + 1, &file_type, sizeof(file_type)); | 1088 | memcpy(packet + 1, &file_type, sizeof(file_type)); |
1044 | host_to_net((uint8_t *)&filesize, sizeof(filesize)); | 1089 | host_to_net((uint8_t *)&filesize, sizeof(filesize)); |
1045 | memcpy(packet + 1 + sizeof(file_type), &filesize, sizeof(filesize)); | 1090 | memcpy(packet + 1 + sizeof(file_type), &filesize, sizeof(filesize)); |
1046 | memcpy(packet + 1 + sizeof(file_type) + sizeof(filesize), filename, filename_length); | 1091 | memcpy(packet + 1 + sizeof(file_type) + sizeof(filesize), file_id, FILE_ID_LENGTH); |
1092 | |||
1093 | if (filename_length) { | ||
1094 | memcpy(packet + 1 + sizeof(file_type) + sizeof(filesize) + FILE_ID_LENGTH, filename, filename_length); | ||
1095 | } | ||
1096 | |||
1047 | return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_SENDREQUEST, packet, sizeof(packet), 0); | 1097 | return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_SENDREQUEST, packet, sizeof(packet), 0); |
1048 | } | 1098 | } |
1049 | 1099 | ||
@@ -1057,7 +1107,7 @@ static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t fi | |||
1057 | * | 1107 | * |
1058 | */ | 1108 | */ |
1059 | long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_type, uint64_t filesize, | 1109 | long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_type, uint64_t filesize, |
1060 | const uint8_t *filename, uint16_t filename_length) | 1110 | const uint8_t *file_id, const uint8_t *filename, uint16_t filename_length) |
1061 | { | 1111 | { |
1062 | if (friend_not_valid(m, friendnumber)) | 1112 | if (friend_not_valid(m, friendnumber)) |
1063 | return -1; | 1113 | return -1; |
@@ -1078,7 +1128,7 @@ long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_ | |||
1078 | if (i == MAX_CONCURRENT_FILE_PIPES) | 1128 | if (i == MAX_CONCURRENT_FILE_PIPES) |
1079 | return -3; | 1129 | return -3; |
1080 | 1130 | ||
1081 | if (file_sendrequest(m, friendnumber, i, file_type, filesize, filename, filename_length) == 0) | 1131 | if (file_sendrequest(m, friendnumber, i, file_type, filesize, file_id, filename, filename_length) == 0) |
1082 | return -4; | 1132 | return -4; |
1083 | 1133 | ||
1084 | struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[i]; | 1134 | struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[i]; |
@@ -1088,6 +1138,7 @@ long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_ | |||
1088 | ft->requested = 0; | 1138 | ft->requested = 0; |
1089 | ft->slots_allocated = 0; | 1139 | ft->slots_allocated = 0; |
1090 | ft->paused = FILE_PAUSE_NOT; | 1140 | ft->paused = FILE_PAUSE_NOT; |
1141 | memcpy(ft->id, file_id, FILE_ID_LENGTH); | ||
1091 | 1142 | ||
1092 | ++m->friendlist[friendnumber].num_sending_files; | 1143 | ++m->friendlist[friendnumber].num_sending_files; |
1093 | 1144 | ||
@@ -1932,9 +1983,9 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) | |||
1932 | } | 1983 | } |
1933 | 1984 | ||
1934 | case PACKET_ID_FILE_SENDREQUEST: { | 1985 | case PACKET_ID_FILE_SENDREQUEST: { |
1935 | const unsigned int head_length = 1 + sizeof(uint32_t) + sizeof(uint64_t); | 1986 | const unsigned int head_length = 1 + sizeof(uint32_t) + sizeof(uint64_t) + FILE_ID_LENGTH; |
1936 | 1987 | ||
1937 | if (data_length < head_length + 1) | 1988 | if (data_length < head_length) |
1938 | break; | 1989 | break; |
1939 | 1990 | ||
1940 | uint8_t filenumber = data[0]; | 1991 | uint8_t filenumber = data[0]; |
@@ -1944,16 +1995,15 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) | |||
1944 | memcpy(&file_type, data + 1, sizeof(file_type)); | 1995 | memcpy(&file_type, data + 1, sizeof(file_type)); |
1945 | file_type = ntohl(file_type); | 1996 | file_type = ntohl(file_type); |
1946 | 1997 | ||
1947 | /* Check if the name is the right size if file is avatar. */ | ||
1948 | if (file_type == FILEKIND_AVATAR && filename_length != crypto_hash_sha256_BYTES) | ||
1949 | break; | ||
1950 | |||
1951 | memcpy(&filesize, data + 1 + sizeof(uint32_t), sizeof(filesize)); | 1998 | memcpy(&filesize, data + 1 + sizeof(uint32_t), sizeof(filesize)); |
1952 | net_to_host((uint8_t *) &filesize, sizeof(filesize)); | 1999 | net_to_host((uint8_t *) &filesize, sizeof(filesize)); |
1953 | m->friendlist[i].file_receiving[filenumber].status = FILESTATUS_NOT_ACCEPTED; | 2000 | struct File_Transfers *ft = &m->friendlist[i].file_receiving[filenumber]; |
1954 | m->friendlist[i].file_receiving[filenumber].size = filesize; | 2001 | |
1955 | m->friendlist[i].file_receiving[filenumber].transferred = 0; | 2002 | ft->status = FILESTATUS_NOT_ACCEPTED; |
1956 | m->friendlist[i].file_receiving[filenumber].paused = FILE_PAUSE_NOT; | 2003 | ft->size = filesize; |
2004 | ft->transferred = 0; | ||
2005 | ft->paused = FILE_PAUSE_NOT; | ||
2006 | memcpy(ft->id, data + 1 + sizeof(uint32_t) + sizeof(uint64_t), FILE_ID_LENGTH); | ||
1957 | 2007 | ||
1958 | /* Force NULL terminate file name. */ | 2008 | /* Force NULL terminate file name. */ |
1959 | uint8_t filename_terminated[filename_length + 1]; | 2009 | uint8_t filename_terminated[filename_length + 1]; |
@@ -1965,7 +2015,7 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) | |||
1965 | real_filenumber <<= 16; | 2015 | real_filenumber <<= 16; |
1966 | 2016 | ||
1967 | if (m->file_sendrequest) | 2017 | if (m->file_sendrequest) |
1968 | (*m->file_sendrequest)(m, i, real_filenumber, file_type, filesize, filename_terminated, filename_length, | 2018 | (*m->file_sendrequest)(m, i, real_filenumber, file_type, filesize, filename, filename_length, |
1969 | m->file_sendrequest_userdata); | 2019 | m->file_sendrequest_userdata); |
1970 | 2020 | ||
1971 | break; | 2021 | break; |
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 716ac851..94cff062 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h | |||
@@ -125,6 +125,8 @@ typedef enum { | |||
125 | } | 125 | } |
126 | USERSTATUS; | 126 | USERSTATUS; |
127 | 127 | ||
128 | #define FILE_ID_LENGTH 32 | ||
129 | |||
128 | struct File_Transfers { | 130 | struct File_Transfers { |
129 | uint64_t size; | 131 | uint64_t size; |
130 | uint64_t transferred; | 132 | uint64_t transferred; |
@@ -133,6 +135,7 @@ struct File_Transfers { | |||
133 | uint32_t last_packet_number; /* number of the last packet sent. */ | 135 | uint32_t last_packet_number; /* number of the last packet sent. */ |
134 | uint64_t requested; /* total data requested by the request chunk callback */ | 136 | uint64_t requested; /* total data requested by the request chunk callback */ |
135 | unsigned int slots_allocated; /* number of slots allocated to this transfer. */ | 137 | unsigned int slots_allocated; /* number of slots allocated to this transfer. */ |
138 | uint8_t id[FILE_ID_LENGTH]; | ||
136 | }; | 139 | }; |
137 | enum { | 140 | enum { |
138 | FILESTATUS_NONE, | 141 | FILESTATUS_NONE, |
@@ -610,6 +613,15 @@ void callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, u | |||
610 | void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *), | 613 | void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *), |
611 | void *userdata); | 614 | void *userdata); |
612 | 615 | ||
616 | |||
617 | /* Copy the file transfer file id to file_id | ||
618 | * | ||
619 | * return 0 on success. | ||
620 | * return -1 if friend not valid. | ||
621 | * return -2 if filenumber not valid | ||
622 | */ | ||
623 | int file_get_id(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint8_t *file_id); | ||
624 | |||
613 | /* Send a file send request. | 625 | /* Send a file send request. |
614 | * Maximum filename length is 255 bytes. | 626 | * Maximum filename length is 255 bytes. |
615 | * return file number on success | 627 | * return file number on success |
@@ -620,7 +632,7 @@ void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_ | |||
620 | * | 632 | * |
621 | */ | 633 | */ |
622 | long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_type, uint64_t filesize, | 634 | long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_type, uint64_t filesize, |
623 | const uint8_t *filename, uint16_t filename_length); | 635 | const uint8_t *file_id, const uint8_t *filename, uint16_t filename_length); |
624 | 636 | ||
625 | /* Send a file control request. | 637 | /* Send a file control request. |
626 | * | 638 | * |
diff --git a/toxcore/tox.c b/toxcore/tox.c index da109502..b793bd8c 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c | |||
@@ -889,21 +889,42 @@ void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *function | |||
889 | callback_file_control(m, function, user_data); | 889 | callback_file_control(m, function, user_data); |
890 | } | 890 | } |
891 | 891 | ||
892 | uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *filename, | 892 | bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t *file_id, |
893 | size_t filename_length, TOX_ERR_FILE_SEND *error) | 893 | TOX_ERR_FILE_GET *error) |
894 | { | ||
895 | const Messenger *m = tox; | ||
896 | int ret = file_get_id(m, friend_number, file_number, file_id); | ||
897 | |||
898 | if (ret == 0) { | ||
899 | SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_OK); | ||
900 | return 1; | ||
901 | } else if (ret == -1) { | ||
902 | SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_FRIEND_NOT_FOUND); | ||
903 | } else { | ||
904 | SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_NOT_FOUND); | ||
905 | } | ||
906 | |||
907 | return 0; | ||
908 | } | ||
909 | |||
910 | uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *file_id, | ||
911 | const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error) | ||
894 | { | 912 | { |
895 | if (!filename) { | 913 | if (!filename) { |
896 | SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NULL); | 914 | SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NULL); |
897 | return UINT32_MAX; | 915 | return UINT32_MAX; |
898 | } | 916 | } |
899 | 917 | ||
900 | if (!filename_length) { | 918 | uint8_t f_id[FILE_ID_LENGTH]; |
901 | SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NAME_EMPTY); | 919 | |
902 | return UINT32_MAX; | 920 | if (!file_id) { |
921 | /* Tox keys are 32 bytes like FILE_ID_LENGTH. */ | ||
922 | new_symmetric_key(f_id); | ||
923 | file_id = f_id; | ||
903 | } | 924 | } |
904 | 925 | ||
905 | Messenger *m = tox; | 926 | Messenger *m = tox; |
906 | long int file_num = new_filesender(m, friend_number, kind, file_size, filename, filename_length); | 927 | long int file_num = new_filesender(m, friend_number, kind, file_size, file_id, filename, filename_length); |
907 | 928 | ||
908 | if (file_num >= 0) { | 929 | if (file_num >= 0) { |
909 | SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_OK); | 930 | SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_OK); |
diff --git a/toxcore/tox.h b/toxcore/tox.h index f1b8b893..b255de5e 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h | |||
@@ -255,6 +255,11 @@ bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch); | |||
255 | */ | 255 | */ |
256 | #define TOX_HASH_LENGTH /*crypto_hash_sha256_BYTES*/ 32 | 256 | #define TOX_HASH_LENGTH /*crypto_hash_sha256_BYTES*/ 32 |
257 | 257 | ||
258 | /** | ||
259 | * The number of bytes in a file id. | ||
260 | */ | ||
261 | #define TOX_FILE_ID_LENGTH 32 | ||
262 | |||
258 | /******************************************************************************* | 263 | /******************************************************************************* |
259 | * | 264 | * |
260 | * :: Global enumerations | 265 | * :: Global enumerations |
@@ -1412,9 +1417,9 @@ enum TOX_FILE_KIND { | |||
1412 | * | 1417 | * |
1413 | * Clients who receive avatar send requests can reject it (by sending | 1418 | * Clients who receive avatar send requests can reject it (by sending |
1414 | * TOX_FILE_CONTROL_CANCEL before any other controls), or accept it (by | 1419 | * TOX_FILE_CONTROL_CANCEL before any other controls), or accept it (by |
1415 | * sending TOX_FILE_CONTROL_RESUME). The filename of length TOX_HASH_LENGTH bytes | 1420 | * sending TOX_FILE_CONTROL_RESUME). The file_id of length TOX_HASH_LENGTH bytes |
1416 | * will contain the hash. A client can compare this hash with a | 1421 | * (same length as TOX_FILE_ID_LENGTH) will contain the hash. A client can compare |
1417 | * saved hash and send TOX_FILE_CONTROL_CANCEL to terminate the avatar | 1422 | * this hash with a saved hash and send TOX_FILE_CONTROL_CANCEL to terminate the avatar |
1418 | * transfer if it matches. | 1423 | * transfer if it matches. |
1419 | */ | 1424 | */ |
1420 | TOX_FILE_KIND_AVATAR | 1425 | TOX_FILE_KIND_AVATAR |
@@ -1534,6 +1539,32 @@ typedef void tox_file_recv_control_cb(Tox *tox, uint32_t friend_number, uint32_t | |||
1534 | void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *function, void *user_data); | 1539 | void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *function, void *user_data); |
1535 | 1540 | ||
1536 | 1541 | ||
1542 | typedef enum TOX_ERR_FILE_GET { | ||
1543 | TOX_ERR_FILE_GET_OK, | ||
1544 | /** | ||
1545 | * The friend_number passed did not designate a valid friend. | ||
1546 | */ | ||
1547 | TOX_ERR_FILE_GET_FRIEND_NOT_FOUND, | ||
1548 | /** | ||
1549 | * No file transfer with the given file number was found for the given friend. | ||
1550 | */ | ||
1551 | TOX_ERR_FILE_GET_NOT_FOUND | ||
1552 | } TOX_ERR_FILE_GET; | ||
1553 | |||
1554 | /** | ||
1555 | * Copy the file id associated to the file transfer to a byte array. | ||
1556 | * | ||
1557 | * @param friend_number The friend number of the friend the file is being | ||
1558 | * transferred to. | ||
1559 | * @param file_number The friend-specific identifier for the file transfer. | ||
1560 | * @param file_id A memory region of at least TOX_FILE_ID_LENGTH bytes. If | ||
1561 | * this parameter is NULL, this function has no effect. | ||
1562 | * | ||
1563 | * @return true on success. | ||
1564 | */ | ||
1565 | bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t *file_id, | ||
1566 | TOX_ERR_FILE_GET *error); | ||
1567 | |||
1537 | /******************************************************************************* | 1568 | /******************************************************************************* |
1538 | * | 1569 | * |
1539 | * :: File transmission: sending | 1570 | * :: File transmission: sending |
@@ -1557,8 +1588,7 @@ typedef enum TOX_ERR_FILE_SEND { | |||
1557 | */ | 1588 | */ |
1558 | TOX_ERR_FILE_SEND_NAME_EMPTY, | 1589 | TOX_ERR_FILE_SEND_NAME_EMPTY, |
1559 | /** | 1590 | /** |
1560 | * Filename length exceeded 255 bytes or if kind was equal to TOX_FILE_KIND_AVATAR | 1591 | * Filename length exceeded 255 bytes. |
1561 | * the length was not TOX_HASH_LENGTH. | ||
1562 | */ | 1592 | */ |
1563 | TOX_ERR_FILE_SEND_NAME_INVALID_LENGTH, | 1593 | TOX_ERR_FILE_SEND_NAME_INVALID_LENGTH, |
1564 | /** | 1594 | /** |
@@ -1581,11 +1611,6 @@ typedef enum TOX_ERR_FILE_SEND { | |||
1581 | * File transmission occurs in chunks, which are requested through the | 1611 | * File transmission occurs in chunks, which are requested through the |
1582 | * `file_request_chunk` event. | 1612 | * `file_request_chunk` event. |
1583 | * | 1613 | * |
1584 | * File numbers are stable across tox_save/tox_load cycles, so that file | ||
1585 | * transfers can be resumed when a client restarts. The client needs to | ||
1586 | * associate (friend Public Key, file number) with the local path of the file and | ||
1587 | * persist this information to support resuming of transfers across restarts. | ||
1588 | * | ||
1589 | * If the file contents change during a transfer, the behaviour is unspecified | 1614 | * If the file contents change during a transfer, the behaviour is unspecified |
1590 | * in general. What will actually happen depends on the mode in which the file | 1615 | * in general. What will actually happen depends on the mode in which the file |
1591 | * was modified and how the client determines the file size. | 1616 | * was modified and how the client determines the file size. |
@@ -1616,6 +1641,9 @@ typedef enum TOX_ERR_FILE_SEND { | |||
1616 | * @param kind The meaning of the file to be sent. | 1641 | * @param kind The meaning of the file to be sent. |
1617 | * @param file_size Size in bytes of the file the client wants to send, 0 if | 1642 | * @param file_size Size in bytes of the file the client wants to send, 0 if |
1618 | * unknown or streaming. | 1643 | * unknown or streaming. |
1644 | * @param file_id A file identifier of length TOX_FILE_ID_LENGTH that can be used to | ||
1645 | * uniquely identify file transfers across core restarts. If NULL, a random one will | ||
1646 | * be generated by core. It can then be obtained by using tox_file_get_file_id(). | ||
1619 | * @param filename Name of the file. Does not need to be the actual name. This | 1647 | * @param filename Name of the file. Does not need to be the actual name. This |
1620 | * name will be sent along with the file send request. | 1648 | * name will be sent along with the file send request. |
1621 | * @param filename_length Size in bytes of the filename. | 1649 | * @param filename_length Size in bytes of the filename. |
@@ -1624,8 +1652,8 @@ typedef enum TOX_ERR_FILE_SEND { | |||
1624 | * number is per friend. File numbers are reused after a transfer terminates. | 1652 | * number is per friend. File numbers are reused after a transfer terminates. |
1625 | * on failure, this function returns UINT32_MAX. | 1653 | * on failure, this function returns UINT32_MAX. |
1626 | */ | 1654 | */ |
1627 | uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *filename, | 1655 | uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *file_id, |
1628 | size_t filename_length, TOX_ERR_FILE_SEND *error); | 1656 | const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error); |
1629 | 1657 | ||
1630 | 1658 | ||
1631 | typedef enum TOX_ERR_FILE_SEND_CHUNK { | 1659 | typedef enum TOX_ERR_FILE_SEND_CHUNK { |