summaryrefslogtreecommitdiff
path: root/toxcore
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore')
-rw-r--r--toxcore/Messenger.c82
-rw-r--r--toxcore/Messenger.h14
-rw-r--r--toxcore/tox.c33
-rw-r--r--toxcore/tox.h52
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 */
1032int 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 */
1031static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint32_t file_type, 1076static 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 */
1059long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_type, uint64_t filesize, 1109long 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}
126USERSTATUS; 126USERSTATUS;
127 127
128#define FILE_ID_LENGTH 32
129
128struct File_Transfers { 130struct 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};
137enum { 140enum {
138 FILESTATUS_NONE, 141 FILESTATUS_NONE,
@@ -610,6 +613,15 @@ void callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, u
610void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *), 613void 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 */
623int 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 */
622long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_type, uint64_t filesize, 634long 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
892uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *filename, 892bool 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
910uint32_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
1534void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *function, void *user_data); 1539void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *function, void *user_data);
1535 1540
1536 1541
1542typedef 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 */
1565bool 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 */
1627uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *filename, 1655uint32_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
1631typedef enum TOX_ERR_FILE_SEND_CHUNK { 1659typedef enum TOX_ERR_FILE_SEND_CHUNK {