示例#1
0
//TODO: make this function not suck.
static void doFriends(void)
{
    /* TODO: add incoming connections and some other stuff. */
    uint32_t i;
    int len;
    uint8_t temp[MAX_DATA_SIZE];
    for (i = 0; i < numfriends; ++i) {
        if (friendlist[i].status == FRIEND_ADDED) {
            int fr = send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size);
            if (fr == 0) /* TODO: This needs to be fixed so that it sends the friend requests a couple of times in case of packet loss */
                set_friend_status(i, FRIEND_REQUESTED);
            else if (fr > 0)
                set_friend_status(i, FRIEND_REQUESTED);
        }
        if (friendlist[i].status == FRIEND_REQUESTED || friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online */
            if (friendlist[i].status == FRIEND_REQUESTED) {
                if (friendlist[i].friend_request_id + 10 < unix_time()) { /*I know this is hackish but it should work.*/
                    send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size);
                    friendlist[i].friend_request_id = unix_time();
                }
            }
            IP_Port friendip = DHT_getfriendip(friendlist[i].client_id);
            switch (is_cryptoconnected(friendlist[i].crypt_connection_id)) {
            case 0:
                if (friendip.ip.i > 1)
                    friendlist[i].crypt_connection_id = crypto_connect(friendlist[i].client_id, friendip);
                break;
            case 3: /*  Connection is established */
                set_friend_status(i, FRIEND_ONLINE);
                friendlist[i].name_sent = 0;
                friendlist[i].userstatus_sent = 0;
                friendlist[i].statusmessage_sent = 0;
                break;
            case 4:
                crypto_kill(friendlist[i].crypt_connection_id);
                friendlist[i].crypt_connection_id = -1;
                break;
            default:
                break;
            }
        }
        while (friendlist[i].status == FRIEND_ONLINE) { /* friend is online */
            if (friendlist[i].name_sent == 0) {
                if (m_sendname(i, self_name, self_name_length))
                    friendlist[i].name_sent = 1;
            }
            if (friendlist[i].statusmessage_sent == 0) {
                if (send_statusmessage(i, self_statusmessage, self_statusmessage_length))
                    friendlist[i].statusmessage_sent = 1;
            }
            if (friendlist[i].userstatus_sent == 0) {
                if (send_userstatus(i, self_userstatus))
                    friendlist[i].userstatus_sent = 1;
            }
            len = read_cryptpacket(friendlist[i].crypt_connection_id, temp);
            uint8_t packet_id = temp[0];
            uint8_t* data = temp + 1;
            int data_length = len - 1;
            if (len > 0) {
                switch (packet_id) {
                case PACKET_ID_NICKNAME: {
                    if (data_length >= MAX_NAME_LENGTH || data_length == 0)
                        break;
                    if(friend_namechange_isset)
                        friend_namechange(i, data, data_length);
                    memcpy(friendlist[i].name, data, data_length);
                    friendlist[i].name[data_length - 1] = 0; /* make sure the NULL terminator is present. */
                    break;
                }
                case PACKET_ID_STATUSMESSAGE: {
                    if (data_length == 0)
                        break;
                    uint8_t *status = calloc(MIN(data_length, MAX_STATUSMESSAGE_LENGTH), 1);
                    memcpy(status, data, MIN(data_length, MAX_STATUSMESSAGE_LENGTH));
                    if (friend_statusmessagechange_isset)
                        friend_statusmessagechange(i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH));
                    set_friend_statusmessage(i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH));
                    free(status);
                    break;
                }
                case PACKET_ID_USERSTATUS: {
                    if (data_length != 1)
                        break;
                    USERSTATUS status = data[0];
                    if (friend_userstatuschange_isset)
                        friend_userstatuschange(i, status);
                    set_friend_userstatus(i, status);
                    break;
                }
                case PACKET_ID_MESSAGE: {
                    uint8_t *message_id = data;
                    uint8_t message_id_length = 4;
                    uint8_t *message = data + message_id_length;
                    uint16_t message_length = data_length - message_id_length;
                    if (friendlist[i].receives_read_receipts) {
                        write_cryptpacket_id(i, PACKET_ID_RECEIPT, message_id, message_id_length);
                    }
                    if (friend_message_isset)
                        (*friend_message)(i, message, message_length);
                    break;
                }
                case PACKET_ID_ACTION: {
                    if (friend_action_isset)
                        (*friend_action)(i, data, data_length);
                    break;
                }
                case PACKET_ID_RECEIPT: {
                    uint32_t msgid;
                    if (data_length < sizeof(msgid))
                        break;
                    memcpy(&msgid, data, sizeof(msgid));
                    msgid = ntohl(msgid);
                    if (read_receipt_isset)
                        (*read_receipt)(i, msgid);
                    break;
                }
                }
            } else {
                if (is_cryptoconnected(friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */
                    crypto_kill(friendlist[i].crypt_connection_id);
                    friendlist[i].crypt_connection_id = -1;
                    set_friend_status(i, FRIEND_CONFIRMED);
                }
                break;
            }
        }
    }
}
示例#2
0
//TODO: make this function not suck.
void doFriends(Messenger *m)
{
    /* TODO: add incoming connections and some other stuff. */
    uint32_t i;
    int len;
    uint8_t temp[MAX_DATA_SIZE];
    uint64_t temp_time = unix_time();

    for (i = 0; i < m->numfriends; ++i) {
        if (m->friendlist[i].status == FRIEND_ADDED) {
            int fr = send_friendrequest(m->friendlist[i].client_id, m->friendlist[i].friendrequest_nospam, m->friendlist[i].info,
                                        m->friendlist[i].info_size);

            if (fr >= 0) {
                set_friend_status(m, i, FRIEND_REQUESTED);
                m->friendlist[i].friendrequest_lastsent = temp_time;
            }
        }

        if (m->friendlist[i].status == FRIEND_REQUESTED
                || m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online */
            if (m->friendlist[i].status == FRIEND_REQUESTED) {
                /* If we didn't connect to friend after successfully sending him a friend request the request is deemed
                   unsuccessful so we set the status back to FRIEND_ADDED and try again.*/
                if (m->friendlist[i].friendrequest_lastsent + m->friendlist[i].friendrequest_timeout < temp_time) {
                    set_friend_status(m, i, FRIEND_ADDED);
                    /* Double the default timeout everytime if friendrequest is assumed to have been
                       sent unsuccessfully. */
                    m->friendlist[i].friendrequest_timeout *= 2;
                }
            }

            IP_Port friendip = DHT_getfriendip(m->friendlist[i].client_id);

            switch (is_cryptoconnected(m->friendlist[i].crypt_connection_id)) {
                case 0:
                    if (friendip.ip.i > 1)
                        m->friendlist[i].crypt_connection_id = crypto_connect(m->friendlist[i].client_id, friendip);

                    break;

                case 3: /*  Connection is established */
                    set_friend_status(m, i, FRIEND_ONLINE);
                    m->friendlist[i].name_sent = 0;
                    m->friendlist[i].userstatus_sent = 0;
                    m->friendlist[i].statusmessage_sent = 0;
                    m->friendlist[i].ping_lastrecv = temp_time;
                    break;

                case 4:
                    crypto_kill(m->friendlist[i].crypt_connection_id);
                    m->friendlist[i].crypt_connection_id = -1;
                    break;

                default:
                    break;
            }
        }

        while (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online */
            if (m->friendlist[i].name_sent == 0) {
                if (m_sendname(m, i, m->name, m->name_length))
                    m->friendlist[i].name_sent = 1;
            }

            if (m->friendlist[i].statusmessage_sent == 0) {
                if (send_statusmessage(m, i, m->statusmessage, m->statusmessage_length))
                    m->friendlist[i].statusmessage_sent = 1;
            }

            if (m->friendlist[i].userstatus_sent == 0) {
                if (send_userstatus(m, i, m->userstatus))
                    m->friendlist[i].userstatus_sent = 1;
            }

            if (m->friendlist[i].ping_lastsent + FRIEND_PING_INTERVAL < temp_time) {
                send_ping(m, i);
            }

            len = read_cryptpacket(m->friendlist[i].crypt_connection_id, temp);
            uint8_t packet_id = temp[0];
            uint8_t *data = temp + 1;
            int data_length = len - 1;

            if (len > 0) {
                switch (packet_id) {
                    case PACKET_ID_PING: {
                        m->friendlist[i].ping_lastrecv = temp_time;
                        break;
                    }

                    case PACKET_ID_NICKNAME: {
                        if (data_length >= MAX_NAME_LENGTH || data_length == 0)
                            break;

                        if (m->friend_namechange)
                            m->friend_namechange(m, i, data, data_length, m->friend_namechange_userdata);

                        memcpy(m->friendlist[i].name, data, data_length);
                        m->friendlist[i].name[data_length - 1] = 0; /* make sure the NULL terminator is present. */
                        break;
                    }

                    case PACKET_ID_STATUSMESSAGE: {
                        if (data_length == 0)
                            break;

                        uint8_t *status = calloc(MIN(data_length, MAX_STATUSMESSAGE_LENGTH), 1);
                        memcpy(status, data, MIN(data_length, MAX_STATUSMESSAGE_LENGTH));

                        if (m->friend_statusmessagechange)
                            m->friend_statusmessagechange(m, i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH),
                                                          m->friend_statuschange_userdata);

                        set_friend_statusmessage(m, i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH));
                        free(status);
                        break;
                    }

                    case PACKET_ID_USERSTATUS: {
                        if (data_length != 1)
                            break;

                        USERSTATUS status = data[0];

                        if (m->friend_userstatuschange)
                            m->friend_userstatuschange(m, i, status, m->friend_userstatuschange_userdata);

                        set_friend_userstatus(m, i, status);
                        break;
                    }

                    case PACKET_ID_MESSAGE: {
                        uint8_t *message_id = data;
                        uint8_t message_id_length = 4;
                        uint8_t *message = data + message_id_length;
                        uint16_t message_length = data_length - message_id_length;

                        if (m->friendlist[i].receives_read_receipts) {
                            write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length);
                        }

                        if (m->friend_message)
                            (*m->friend_message)(m, i, message, message_length, m->friend_message_userdata);

                        break;
                    }

                    case PACKET_ID_ACTION: {
                        if (m->friend_action)
                            (*m->friend_action)(m, i, data, data_length, m->friend_action_userdata);

                        break;
                    }

                    case PACKET_ID_RECEIPT: {
                        uint32_t msgid;

                        if (data_length < sizeof(msgid))
                            break;

                        memcpy(&msgid, data, sizeof(msgid));
                        msgid = ntohl(msgid);

                        if (m->read_receipt)
                            (*m->read_receipt)(m, i, msgid, m->read_receipt_userdata);

                        break;
                    }
                }
            } else {
                if (is_cryptoconnected(m->friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */
                    crypto_kill(m->friendlist[i].crypt_connection_id);
                    m->friendlist[i].crypt_connection_id = -1;
                    set_friend_status(m, i, FRIEND_CONFIRMED);
                }

                break;
            }

            if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) {
                /* if we stopped recieving ping packets kill it */
                crypto_kill(m->friendlist[i].crypt_connection_id);
                m->friendlist[i].crypt_connection_id = -1;
                set_friend_status(m, i, FRIEND_CONFIRMED);
            }
        }
    }
}