summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2013-10-01 16:48:32 -0400
committerirungentoo <irungentoo@gmail.com>2013-10-01 16:48:32 -0400
commit6dbc8a54969421c5baeb0ec7bb50779c62ae2e44 (patch)
tree86c0b3981f8bbb6642fd203a32d12aab13e286c5
parent766cff692f9dc93ef284a214ad4bc6389d6afa76 (diff)
Core now takes better care of file transfers.
-rw-r--r--toxcore/Messenger.c129
-rw-r--r--toxcore/Messenger.h18
2 files changed, 142 insertions, 5 deletions
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index b21da28b..39bcd704 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -606,7 +606,7 @@ void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, in
606 m->friend_connectionstatuschange = function; 606 m->friend_connectionstatuschange = function;
607 m->friend_connectionstatuschange_userdata = userdata; 607 m->friend_connectionstatuschange_userdata = userdata;
608} 608}
609 609static void break_files(Messenger *m, int friendnumber);
610static void check_friend_connectionstatus(Messenger *m, int friendnumber, uint8_t status) 610static void check_friend_connectionstatus(Messenger *m, int friendnumber, uint8_t status)
611{ 611{
612 if (!m->friend_connectionstatuschange) 612 if (!m->friend_connectionstatuschange)
@@ -618,8 +618,12 @@ static void check_friend_connectionstatus(Messenger *m, int friendnumber, uint8_
618 const uint8_t was_online = m->friendlist[friendnumber].status == FRIEND_ONLINE; 618 const uint8_t was_online = m->friendlist[friendnumber].status == FRIEND_ONLINE;
619 const uint8_t is_online = status == FRIEND_ONLINE; 619 const uint8_t is_online = status == FRIEND_ONLINE;
620 620
621 if (is_online != was_online) 621 if (is_online != was_online) {
622 if (was_online)
623 break_files(m, friendnumber);
624
622 m->friend_connectionstatuschange(m, friendnumber, is_online, m->friend_connectionstatuschange_userdata); 625 m->friend_connectionstatuschange(m, friendnumber, is_online, m->friend_connectionstatuschange_userdata);
626 }
623} 627}
624 628
625void set_friend_status(Messenger *m, int friendnumber, uint8_t status) 629void set_friend_status(Messenger *m, int friendnumber, uint8_t status)
@@ -938,7 +942,6 @@ static void do_allgroupchats(Messenger *m)
938void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, int, uint8_t, uint64_t, uint8_t *, uint16_t, 942void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, int, uint8_t, uint64_t, uint8_t *, uint16_t,
939 void *), void *userdata) 943 void *), void *userdata)
940{ 944{
941
942 m->file_sendrequest = function; 945 m->file_sendrequest = function;
943 m->file_sendrequest_userdata = userdata; 946 m->file_sendrequest_userdata = userdata;
944} 947}
@@ -977,6 +980,9 @@ void callback_file_data(Messenger *m, void (*function)(Messenger *m, int, uint8_
977int file_sendrequest(Messenger *m, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename, 980int file_sendrequest(Messenger *m, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename,
978 uint16_t filename_length) 981 uint16_t filename_length)
979{ 982{
983 if (friend_not_valid(m, friendnumber))
984 return 0;
985
980 if (filename_length > MAX_FILENAME_LENGTH) 986 if (filename_length > MAX_FILENAME_LENGTH)
981 return 0; 987 return 0;
982 988
@@ -990,6 +996,35 @@ int file_sendrequest(Messenger *m, int friendnumber, uint8_t filenumber, uint64_
990 1 + sizeof(filesize) + filename_length); 996 1 + sizeof(filesize) + filename_length);
991} 997}
992 998
999/* Send a file send request.
1000 * Maximum filename length is 256 bytes.
1001 * return file number on success
1002 * return -1 on failure
1003 */
1004int new_filesender(Messenger *m, int friendnumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length)
1005{
1006 if (friend_not_valid(m, friendnumber))
1007 return 0;
1008
1009 uint32_t i;
1010
1011 for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) {
1012 if (m->friendlist[friendnumber].file_sending[i].status == 0)
1013 break;
1014 }
1015
1016 if (i == MAX_CONCURRENT_FILE_PIPES)
1017 return -1;
1018
1019 if (file_sendrequest(m, friendnumber, i, filesize, filename, filename_length) == 0)
1020 return -1;
1021
1022 m->friendlist[friendnumber].file_sending[i].status = 1;
1023 m->friendlist[friendnumber].file_sending[i].size = filesize;
1024 m->friendlist[friendnumber].file_sending[i].transferred = 0;
1025 return i;
1026}
1027
993/* Send a file control request. 1028/* Send a file control request.
994 * 1029 *
995 * return 1 on success 1030 * return 1 on success
@@ -1000,11 +1035,37 @@ int file_control(Messenger *m, int friendnumber, uint8_t filenumber, uint8_t mes
1000 if (length > MAX_DATA_SIZE - 2) 1035 if (length > MAX_DATA_SIZE - 2)
1001 return 0; 1036 return 0;
1002 1037
1038 if (friend_not_valid(m, friendnumber))
1039 return 0;
1040
1041 if (m->friendlist[friendnumber].file_sending[filenumber].status == 0)
1042 return 0;
1043
1003 uint8_t packet[MAX_DATA_SIZE]; 1044 uint8_t packet[MAX_DATA_SIZE];
1004 packet[0] = filenumber; 1045 packet[0] = filenumber;
1005 packet[1] = message_id; 1046 packet[1] = message_id;
1006 memcpy(packet + 2, data, length); 1047 memcpy(packet + 2, data, length);
1007 return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_CONTROL, packet, length + 2); 1048
1049 if (write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_CONTROL, packet, length + 2)) {
1050 switch (message_id) {
1051 case FILECONTROL_ACCEPT:
1052 m->friendlist[friendnumber].file_receiving[filenumber].status = 3;
1053 break;
1054
1055 case FILECONTROL_PAUSE:
1056 m->friendlist[friendnumber].file_receiving[filenumber].status = 2;
1057 break;
1058
1059 case FILECONTROL_KILL:
1060 case FILECONTROL_FINISHED:
1061 m->friendlist[friendnumber].file_receiving[filenumber].status = 0;
1062 break;
1063 }
1064
1065 return 1;
1066 } else {
1067 return 0;
1068 }
1008} 1069}
1009 1070
1010 1071
@@ -1018,10 +1079,62 @@ int file_data(Messenger *m, int friendnumber, uint8_t filenumber, uint8_t *data,
1018 if (length > MAX_DATA_SIZE - 1) 1079 if (length > MAX_DATA_SIZE - 1)
1019 return 0; 1080 return 0;
1020 1081
1082 if (friend_not_valid(m, friendnumber))
1083 return 0;
1084
1085 if (m->friendlist[friendnumber].file_sending[filenumber].status != 3)
1086 return 0;
1087
1021 uint8_t packet[MAX_DATA_SIZE]; 1088 uint8_t packet[MAX_DATA_SIZE];
1022 packet[0] = filenumber; 1089 packet[0] = filenumber;
1023 memcpy(packet + 1, data, length); 1090 memcpy(packet + 1, data, length);
1024 return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_DATA, packet, length + 1); 1091
1092 if (write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_DATA, packet, length + 1)) {
1093 m->friendlist[friendnumber].file_sending[filenumber].transferred += length;
1094 return 1;
1095 }
1096
1097 return 0;
1098
1099}
1100/* Run this when the friend disconnects.
1101 * Sets all current file transfers to broken.
1102 */
1103static void break_files(Messenger *m, int friendnumber)
1104{
1105 uint32_t i;
1106
1107 for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) {
1108 if (m->friendlist[friendnumber].file_sending[i].status != 0)
1109 m->friendlist[friendnumber].file_sending[i].status = 4;
1110
1111 if (m->friendlist[friendnumber].file_receiving[i].status != 0)
1112 m->friendlist[friendnumber].file_receiving[i].status = 4;
1113 }
1114}
1115
1116static int handle_filecontrol(Messenger *m, int friendnumber, uint8_t filenumber, uint8_t message_id, uint8_t *data,
1117 uint16_t length)
1118{
1119 if (m->friendlist[friendnumber].file_sending[filenumber].status == 0)
1120 return -1;
1121
1122 switch (message_id) {
1123 case FILECONTROL_ACCEPT:
1124 m->friendlist[friendnumber].file_sending[filenumber].status = 3;
1125 return 0;
1126
1127 case FILECONTROL_PAUSE:
1128 m->friendlist[friendnumber].file_sending[filenumber].status = 2;
1129 return 0;
1130
1131 case FILECONTROL_KILL:
1132 case FILECONTROL_FINISHED:
1133 m->friendlist[friendnumber].file_sending[filenumber].status = 0;
1134 return 0;
1135 }
1136
1137 return -1;
1025} 1138}
1026 1139
1027/**************************************/ 1140/**************************************/
@@ -1331,6 +1444,9 @@ void doFriends(Messenger *m)
1331 uint8_t filenumber = data[0]; 1444 uint8_t filenumber = data[0];
1332 uint8_t control_type = data[1]; 1445 uint8_t control_type = data[1];
1333 1446
1447 if (handle_filecontrol(m, i, filenumber, control_type, data + 2, data_length - 2) == -1)
1448 break;
1449
1334 if (m->file_filecontrol) 1450 if (m->file_filecontrol)
1335 (*m->file_filecontrol)(m, i, filenumber, control_type, data + 2, data_length - 2, m->file_filecontrol_userdata); 1451 (*m->file_filecontrol)(m, i, filenumber, control_type, data + 2, data_length - 2, m->file_filecontrol_userdata);
1336 1452
@@ -1343,6 +1459,9 @@ void doFriends(Messenger *m)
1343 1459
1344 uint8_t filenumber = data[0]; 1460 uint8_t filenumber = data[0];
1345 1461
1462 if (m->friendlist[i].file_receiving[filenumber].status == 0)
1463 break;
1464
1346 if (m->file_filedata) 1465 if (m->file_filedata)
1347 (*m->file_filedata)(m, i, filenumber, data + 1, data_length - 1, m->file_filedata_userdata); 1466 (*m->file_filedata)(m, i, filenumber, data + 1, data_length - 1, m->file_filedata_userdata);
1348 1467
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index 05a5af27..fbf4d767 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -99,6 +99,22 @@ typedef enum {
99} 99}
100USERSTATUS; 100USERSTATUS;
101 101
102struct File_Transfers {
103 uint64_t size;
104 uint64_t transferred;
105 uint8_t status; /* 0 == no transfer, 1 = not accepted, 2 = paused, 3 = transferring, 4 = broken*/
106};
107
108/* This cannot be bigger than 256 */
109#define MAX_CONCURRENT_FILE_PIPES 256
110
111enum {
112 FILECONTROL_ACCEPT,
113 FILECONTROL_PAUSE,
114 FILECONTROL_KILL,
115 FILECONTROL_FINISHED
116};
117
102typedef struct { 118typedef struct {
103 uint8_t client_id[CLIENT_ID_SIZE]; 119 uint8_t client_id[CLIENT_ID_SIZE];
104 int crypt_connection_id; 120 int crypt_connection_id;
@@ -120,6 +136,8 @@ typedef struct {
120 uint32_t friendrequest_nospam; // The nospam number used in the friend request. 136 uint32_t friendrequest_nospam; // The nospam number used in the friend request.
121 uint64_t ping_lastrecv; 137 uint64_t ping_lastrecv;
122 uint64_t ping_lastsent; 138 uint64_t ping_lastsent;
139 struct File_Transfers file_sending[MAX_CONCURRENT_FILE_PIPES];
140 struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES];
123} Friend; 141} Friend;
124 142
125typedef struct Messenger { 143typedef struct Messenger {