summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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