diff options
-rw-r--r-- | toxcore/Messenger.c | 157 |
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 | ||
1611 | static 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 | */ |
1613 | static int handle_filecontrol(Messenger *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, | 1633 | static 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 | ||