diff options
Diffstat (limited to 'toxcore')
-rw-r--r-- | toxcore/Messenger.c | 129 | ||||
-rw-r--r-- | toxcore/Messenger.h | 18 |
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 | 609 | static void break_files(Messenger *m, int friendnumber); | |
610 | static void check_friend_connectionstatus(Messenger *m, int friendnumber, uint8_t status) | 610 | static 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 | ||
625 | void set_friend_status(Messenger *m, int friendnumber, uint8_t status) | 629 | void set_friend_status(Messenger *m, int friendnumber, uint8_t status) |
@@ -938,7 +942,6 @@ static void do_allgroupchats(Messenger *m) | |||
938 | void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, int, uint8_t, uint64_t, uint8_t *, uint16_t, | 942 | void 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_ | |||
977 | int file_sendrequest(Messenger *m, int friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *filename, | 980 | int 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 | */ | ||
1004 | int 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 | */ | ||
1103 | static 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 | |||
1116 | static 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 | } |
100 | USERSTATUS; | 100 | USERSTATUS; |
101 | 101 | ||
102 | struct 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 | |||
111 | enum { | ||
112 | FILECONTROL_ACCEPT, | ||
113 | FILECONTROL_PAUSE, | ||
114 | FILECONTROL_KILL, | ||
115 | FILECONTROL_FINISHED | ||
116 | }; | ||
117 | |||
102 | typedef struct { | 118 | typedef 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 | ||
125 | typedef struct Messenger { | 143 | typedef struct Messenger { |