summaryrefslogtreecommitdiff
path: root/toxcore
diff options
context:
space:
mode:
authoriphydf <iphydf@users.noreply.github.com>2017-01-05 17:50:32 +0000
committeriphydf <iphydf@users.noreply.github.com>2017-01-10 16:26:44 +0000
commit2ba967d07801b8c8c94851528855cce24860d882 (patch)
tree757494dccddc26d48437747587d5f4e69ba8fbda /toxcore
parent5c248e9d11fb2c3d33f40b5ea992e13e5270e293 (diff)
Always kill invalid file transfers when receiving file controls.
Previously, toxcore would send a kill control to the friend only if the file control was valid. Determining which file transfer is used does not depend on the specific file control. We can always kill it in that case. Also, added some logging for file control logic, since there is no other feedback on error (failure of the file control handler is swallowed).
Diffstat (limited to 'toxcore')
-rw-r--r--toxcore/Messenger.c157
1 files changed, 99 insertions, 58 deletions
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index 48a79aa0..cd4c8380 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -1608,96 +1608,135 @@ static void break_files(const Messenger *m, int32_t friendnumber)
1608 } 1608 }
1609} 1609}
1610 1610
1611static struct File_Transfers *get_file_transfer(uint8_t receive_send, uint8_t filenumber,
1612 uint32_t *real_filenumber, Friend *sender)
1613{
1614 struct File_Transfers *ft;
1615
1616 if (receive_send == 0) {
1617 *real_filenumber = (filenumber + 1) << 16;
1618 ft = &sender->file_receiving[filenumber];
1619 } else {
1620 *real_filenumber = filenumber;
1621 ft = &sender->file_sending[filenumber];
1622 }
1623
1624 if (ft->status == FILESTATUS_NONE) {
1625 return NULL;
1626 }
1627
1628 return ft;
1629}
1630
1611/* return -1 on failure, 0 on success. 1631/* return -1 on failure, 0 on success.
1612 */ 1632 */
1613static int handle_filecontrol(Messenger *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, 1633static int handle_filecontrol(Messenger *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber,
1614 uint8_t control_type, const uint8_t *data, uint16_t length, void *userdata) 1634 uint8_t control_type, const uint8_t *data, uint16_t length, void *userdata)
1615{ 1635{
1616 if (receive_send > 1) { 1636 if (receive_send > 1) {
1637 LOGGER_DEBUG(m->log, "file control (friend %d, file %d): receive_send value is invalid (should be 0 or 1): %d",
1638 friendnumber, filenumber, receive_send);
1617 return -1; 1639 return -1;
1618 } 1640 }
1619 1641
1620 if (control_type > FILECONTROL_SEEK) { 1642 uint32_t real_filenumber;
1621 return -1; 1643 struct File_Transfers *ft = get_file_transfer(receive_send, filenumber, &real_filenumber, &m->friendlist[friendnumber]);
1622 }
1623
1624 uint32_t real_filenumber = filenumber;
1625 struct File_Transfers *ft;
1626
1627 if (receive_send == 0) {
1628 real_filenumber += 1;
1629 real_filenumber <<= 16;
1630 ft = &m->friendlist[friendnumber].file_receiving[filenumber];
1631 } else {
1632 ft = &m->friendlist[friendnumber].file_sending[filenumber];
1633 }
1634 1644
1635 if (ft->status == FILESTATUS_NONE) { 1645 if (ft == NULL) {
1636 /* File transfer doesn't exist, tell the other to kill it. */ 1646 LOGGER_DEBUG(m->log, "file control (friend %d, file %d): file transfer does not exist; telling the other to kill it",
1647 friendnumber, filenumber);
1637 send_file_control_packet(m, friendnumber, !receive_send, filenumber, FILECONTROL_KILL, 0, 0); 1648 send_file_control_packet(m, friendnumber, !receive_send, filenumber, FILECONTROL_KILL, 0, 0);
1638 return -1; 1649 return -1;
1639 } 1650 }
1640 1651
1641 if (control_type == FILECONTROL_ACCEPT) { 1652 switch (control_type) {
1642 if (receive_send && ft->status == FILESTATUS_NOT_ACCEPTED) { 1653 case FILECONTROL_ACCEPT: {
1643 ft->status = FILESTATUS_TRANSFERRING; 1654 if (receive_send && ft->status == FILESTATUS_NOT_ACCEPTED) {
1644 } else { 1655 ft->status = FILESTATUS_TRANSFERRING;
1645 if (ft->paused & FILE_PAUSE_OTHER) {
1646 ft->paused ^= FILE_PAUSE_OTHER;
1647 } else { 1656 } else {
1648 return -1; 1657 if (ft->paused & FILE_PAUSE_OTHER) {
1658 ft->paused ^= FILE_PAUSE_OTHER;
1659 } else {
1660 LOGGER_DEBUG(m->log, "file control (friend %d, file %d): friend told us to resume file transfer that wasn't paused",
1661 friendnumber, filenumber);
1662 return -1;
1663 }
1649 } 1664 }
1650 }
1651 1665
1652 if (m->file_filecontrol) { 1666 if (m->file_filecontrol) {
1653 (*m->file_filecontrol)(m, friendnumber, real_filenumber, control_type, userdata); 1667 m->file_filecontrol(m, friendnumber, real_filenumber, control_type, userdata);
1654 } 1668 }
1655 } else if (control_type == FILECONTROL_PAUSE) { 1669
1656 if ((ft->paused & FILE_PAUSE_OTHER) || ft->status != FILESTATUS_TRANSFERRING) { 1670 return 0;
1657 return -1;
1658 } 1671 }
1659 1672
1660 ft->paused |= FILE_PAUSE_OTHER; 1673 case FILECONTROL_PAUSE: {
1674 if ((ft->paused & FILE_PAUSE_OTHER) || ft->status != FILESTATUS_TRANSFERRING) {
1675 LOGGER_DEBUG(m->log, "file control (friend %d, file %d): friend told us to pause file transfer that is already paused",
1676 friendnumber, filenumber);
1677 return -1;
1678 }
1661 1679
1662 if (m->file_filecontrol) { 1680 ft->paused |= FILE_PAUSE_OTHER;
1663 (*m->file_filecontrol)(m, friendnumber, real_filenumber, control_type, userdata); 1681
1664 } 1682 if (m->file_filecontrol) {
1665 } else if (control_type == FILECONTROL_KILL) { 1683 m->file_filecontrol(m, friendnumber, real_filenumber, control_type, userdata);
1684 }
1666 1685
1667 if (m->file_filecontrol) { 1686 return 0;
1668 (*m->file_filecontrol)(m, friendnumber, real_filenumber, control_type, userdata);
1669 } 1687 }
1670 1688
1671 ft->status = FILESTATUS_NONE; 1689 case FILECONTROL_KILL: {
1690 if (m->file_filecontrol) {
1691 m->file_filecontrol(m, friendnumber, real_filenumber, control_type, userdata);
1692 }
1672 1693
1673 if (receive_send) { 1694 ft->status = FILESTATUS_NONE;
1674 --m->friendlist[friendnumber].num_sending_files;
1675 }
1676 } else if (control_type == FILECONTROL_SEEK) {
1677 uint64_t position;
1678 1695
1679 if (length != sizeof(position)) { 1696 if (receive_send) {
1680 return -1; 1697 --m->friendlist[friendnumber].num_sending_files;
1681 } 1698 }
1682 1699
1683 /* seek can only be sent by the receiver to seek before resuming broken transfers. */ 1700 return 0;
1684 if (ft->status != FILESTATUS_NOT_ACCEPTED || !receive_send) {
1685 return -1;
1686 } 1701 }
1687 1702
1688 memcpy(&position, data, sizeof(position)); 1703 case FILECONTROL_SEEK: {
1689 net_to_host((uint8_t *) &position, sizeof(position)); 1704 uint64_t position;
1690 1705
1691 if (position >= ft->size) { 1706 if (length != sizeof(position)) {
1692 return -1; 1707 LOGGER_DEBUG(m->log, "file control (friend %d, file %d): expected payload of length %d, but got %d",
1708 friendnumber, filenumber, (uint32_t)sizeof(position), length);
1709 return -1;
1710 }
1711
1712 /* seek can only be sent by the receiver to seek before resuming broken transfers. */
1713 if (ft->status != FILESTATUS_NOT_ACCEPTED || !receive_send) {
1714 LOGGER_DEBUG(m->log,
1715 "file control (friend %d, file %d): seek was either sent by a sender or by the receiver after accepting",
1716 friendnumber, filenumber);
1717 return -1;
1718 }
1719
1720 memcpy(&position, data, sizeof(position));
1721 net_to_host((uint8_t *) &position, sizeof(position));
1722
1723 if (position >= ft->size) {
1724 LOGGER_DEBUG(m->log,
1725 "file control (friend %d, file %d): seek position %lld exceeds file size %lld",
1726 friendnumber, filenumber, (unsigned long long)position, (unsigned long long)ft->size);
1727 return -1;
1728 }
1729
1730 ft->transferred = ft->requested = position;
1731 return 0;
1693 } 1732 }
1694 1733
1695 ft->transferred = ft->requested = position; 1734 default: {
1696 } else { 1735 LOGGER_DEBUG(m->log, "file control (friend %d, file %d): invalid file control: %d",
1697 return -1; 1736 friendnumber, filenumber, control_type);
1737 return -1;
1738 }
1698 } 1739 }
1699
1700 return 0;
1701} 1740}
1702 1741
1703/**************************************/ 1742/**************************************/
@@ -2271,6 +2310,8 @@ static int handle_packet(void *object, int i, const uint8_t *temp, uint16_t len,
2271 } 2310 }
2272 2311
2273 if (handle_filecontrol(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3, userdata) == -1) { 2312 if (handle_filecontrol(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3, userdata) == -1) {
2313 // TODO(iphydf): Do something different here? Right now, this
2314 // check is pointless.
2274 break; 2315 break;
2275 } 2316 }
2276 2317