/*
 * Interprets the given SNAC.
 */
void SnacCallback (Event *event)
{
    Packet  *pak  = event->pak;
    SNAC *s;
    UWORD family;
    
    ASSERT_SERVER(event->conn);
    
    family     = PacketReadB2 (pak);
    pak->cmd   = PacketReadB2 (pak);
    pak->flags = PacketReadB2 (pak);
    pak->ref   = PacketReadB4 (pak);
    
    if (pak->flags & 0x8000)
        PacketReadData (pak, NULL, PacketReadB2 (pak));
    
    for (s = SNACS; s->fam; s++)
        if (s->fam == family && s->cmd == pak->cmd)
            break;
    
    if (s->f)
        s->f (event);
    else
        SnacSrvUnknown (event);

    EventD (event);
}
Beispiel #2
0
void PeerFileResend (Event *event)
{
    Contact *cont;
    Connection *fpeer = event->conn;
    Packet *pak;
    Event *event2;
    int rc;
    const char *opt_text;
    
    if (!fpeer)
    {
        EventD (event);
        return;
    }
    
    ASSERT_FILEDIRECT (fpeer);

    cont = event->cont;
    assert (cont);
    
    if (!OptGetStr (event->opt, CO_FILENAME, &opt_text))
        opt_text = "";

    if (event->attempts >= MAX_RETRY_P2PFILE_ATTEMPTS || (!event->pak && !event->seq))
    {
        rl_log_for (cont->nick, COLCONTACT);
        rl_printf (i18n (2168, "File transfer #%ld (%s) dropped after %ld attempts because of timeout.\n"),
                   UD2UL (event->seq), opt_text, UD2UL (event->attempts));
        TCPClose (fpeer);
    }
    else if (!(fpeer->connect & CONNECT_MASK))
    {
        rl_log_for (cont->nick, COLCONTACT);
        rl_printf (i18n (2072, "File transfer #%ld (%s) canceled because of closed connection.\n"),
                   UD2UL (event->seq), opt_text);
    }
    else if (~fpeer->connect & CONNECT_OK)
    {
        if (!event->seq)
            event->attempts++;
        event->due = time (NULL) + 20;
        QueueEnqueue (event);
        return;
    }
    else if (!event->seq)
    {
        fpeer->oscar_dc_seq = 0;
        PeerPacketSend (fpeer, event->pak);
        PacketD (event->pak);
        event->pak = NULL;
    }
    else if (event->seq != fpeer->oscar_dc_seq)
    {
        event->due = time (NULL) + 10;
        QueueEnqueue (event);
        return;
    }
    else if (event->pak)
    {
        Connection *ffile;
        struct stat finfo;
        
        PeerPacketSend (fpeer, event->pak);
        PacketD (event->pak);
        event->pak = NULL;
        QueueEnqueue (event);
        
        ffile = ServerChild (fpeer->serv, fpeer->cont, TYPE_FILE);
        fpeer->oscar_file = ffile;

        if (stat (opt_text, &finfo))
        {
            rc = errno;
            rl_printf (i18n (2071, "Couldn't stat file %s: %s (%d)\n"),
                      s_wordquote (opt_text), strerror (rc), rc);
        }
        ffile->oscar_file_len = finfo.st_size;

        ffile->sok = open (opt_text, O_RDONLY);
        if (ffile->sok == -1)
        {
            int rc = errno;
            rl_log_for (cont->nick, COLCONTACT);
            rl_printf (i18n (2083, "Cannot open file %s: %s (%d).\n"),
                      opt_text, strerror (rc), rc);
            TCPClose (fpeer);
            ConnectionD (ffile);
            ConnectionD (fpeer);
            return;
        }
        return;
    }
    else if (!fpeer->oscar_file || fpeer->connect & CONNECT_SELECT_W)
    {
        event->attempts++;
        event->due = time (NULL) + 3;
        QueueEnqueue (event);
        return;
    }
    else
    {
        int len = 0;

        pak = PeerPacketC (fpeer, 6);
        len = read (fpeer->oscar_file->sok, pak->data + 1, 2048);
        if (len == -1)
        {
            len = errno;
            rl_log_for (cont->nick, COLCONTACT);
            rl_printf (i18n (2086, "Error while reading file %s: %s (%d).\n"),
                      opt_text, strerror (len), len);
            TCPClose (fpeer);
        }
        else
        {
            pak->len += len;
            fpeer->oscar_file->oscar_file_done += len;
            PeerPacketSend (fpeer, pak);
            PacketD (pak);

            if (len > 0)
            {
                if (fpeer->oscar_file->oscar_file_len)
                    ReadLinePromptUpdate (s_sprintf ("[%s%ld %02d%%%s] %s%s",
                                  COLCONTACT, UD2UL (fpeer->oscar_file->oscar_file_done), (int)((100.0 * fpeer->oscar_file->oscar_file_done) / fpeer->oscar_file->oscar_file_len),
                                  COLNONE, COLSERVER, i18n (2467, "climm>")));
                else
                    ReadLinePromptUpdate (s_sprintf ("[%s%ld%s] %s%s",
                                  COLCONTACT, UD2UL (fpeer->oscar_file->oscar_file_done),
                                  COLNONE, COLSERVER, i18n (2467, "climm>")));
                event->attempts = 0;
                QueueEnqueue (event);
                return;
            }

            ReadLinePromptReset ();
            rl_log_for (cont->nick, COLCONTACT);
            rl_printf (i18n (2087, "Finished sending file %s.\n"), opt_text);
            ConnectionD (fpeer->oscar_file);
            fpeer->oscar_dc_seq++;
            event2 = QueueDequeue (fpeer, QUEUE_PEER_FILE, fpeer->oscar_dc_seq);
            if (event2)
            {
                QueueEnqueue (event2);
                QueueRetry (fpeer, QUEUE_PEER_FILE, fpeer->cont);
                return;
            }
            else
            {
                rl_log_for (cont->nick, COLCONTACT);
                rl_printf (i18n (2088, "Finished sending all %d files.\n"), fpeer->oscar_dc_seq - 1);
                ConnectionD (fpeer);
            }
        }
    }
    EventD (event);
}