/*
 * Open preference file.
 */
static FILE *PrefOpenRC (Preferences *pref)
{
    if (!pref->rcfile)
        pref->rcfile = strdup (s_sprintf ("%smicqrc", PrefUserDir (pref)));
    
    return fopen (pref->rcfile, "r");
}
/*
 * Open status file.
 */
static FILE *PrefOpenStat (Preferences *pref)
{
    if (!pref->statfile)
        pref->statfile = strdup (s_sprintf ("%sstatus", PrefUserDir (pref)));

    return fopen (pref->statfile, "r");
}
示例#3
0
/*
 * Dispatches incoming packets on the file transfer connection.
 */
void PeerFileDispatch (Connection *fpeer)
{
    Contact *cont;
    Packet *pak;
    int err = 0;
    
    ASSERT_FILEDIRECT (fpeer);
    assert (fpeer->cont);

    cont = fpeer->cont;

    if (fpeer->connect & CONNECT_SELECT_W && UtilIOSelectIs (fpeer->sok, WRITEFDS))
    {
        fpeer->connect &= ~CONNECT_SELECT_W;
        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>")));
        UtilIOSendTCP2 (fpeer, NULL);
        QueueRetry (fpeer, QUEUE_PEER_FILE, fpeer->cont);
        if (!UtilIOSelectIs (fpeer->sok, READFDS))
            return;
    }
    if (!(pak = UtilIOReceiveTCP2 (fpeer)))
        return;

    if (prG->verbose & DEB_PACKTCP)
        TCPPrint (pak, fpeer, FALSE);

    switch (PacketRead1 (pak))
    {
        strc_t name, text;
        UDWORD len, off, nr, speed;

        case 0:
                   PacketRead4 (pak); /* EMPTY */
            nr   = PacketRead4 (pak); /* COUNT */
            len  = PacketRead4 (pak); /* BYTES */
            speed= PacketRead4 (pak); /* SPEED */
            name = PacketReadL2Str (pak, NULL); /* NICK  */
            PacketD (pak);
            
            rl_log_for (cont->nick, COLCONTACT);
            rl_printf (i18n (2161, "Receiving %ld files with total size %ld bytes at speed %lx from %s.\n"),
                     UD2UL (nr), UD2UL (len), UD2UL (speed), ConvFromCont (name, cont));
            
            if (len != fpeer->oscar_file_len)
            {
                rl_printf ("FIXME: byte len different than in file request: requested %ld, sending %ld.\n",
                           UD2UL (fpeer->oscar_file_len), UD2UL (len));
                fpeer->oscar_file_len = len;
            }
            
            pak = PeerPacketC (fpeer, 1);
            PacketWrite4 (pak, 64);
            PacketWriteLNTS (pak, cont->nick);
            PeerPacketSend (fpeer, pak);
            PacketD (pak);
            return;
        
        case 1:
            speed = PacketRead4 (pak); /* SPEED */
            name  = PacketReadL2Str (pak, NULL); /* NICK  */
            PacketD (pak);
            
            rl_log_for (cont->nick, COLCONTACT);
            rl_printf (i18n (2170, "Sending file at speed %lx to %s.\n"), UD2UL (speed), s_wordquote (ConvFromCont (name, cont)));
            
            fpeer->oscar_dc_seq = 1;
            QueueRetry (fpeer, QUEUE_PEER_FILE, cont);
            return;
            
        case 2:
                   PacketRead1 (pak); /* EMPTY */
            name = PacketReadL2Str (pak, NULL);
            text = PacketReadL2Str (pak, NULL);
            len  = PacketRead4 (pak);
                   PacketRead4 (pak); /* EMPTY */
                   PacketRead4 (pak); /* SPEED */
            off  = 0;
            PacketD (pak);
            
            {
                Connection *ffile = ServerChild (fpeer->serv, fpeer->cont, TYPE_FILE);
                char buf[200], *p;
                int pos = 0;
                struct stat finfo;

                assert (ffile);
                pos = snprintf (buf, sizeof (buf), "%sfiles" _OS_PATHSEPSTR "%s" _OS_PATHSEPSTR,
                                PrefUserDir (prG), cont->screen);
                snprintf (buf + pos, sizeof (buf) - pos, "%s", ConvFromCont (name, cont));
                for (p = buf + pos; *p; p++)
                    if (*p == '/')
                        *p = '_';
                finfo.st_size = 0;
                if (!stat (buf, &finfo))
                    if ((UDWORD)finfo.st_size < len)
                        off = finfo.st_size;
                fpeer->oscar_file = ffile;
                ffile->sok = open (buf, O_CREAT | O_WRONLY | (off ? O_APPEND : O_TRUNC), 0660);
                if (ffile->sok == -1)
                {
                    int rc = errno;
                    if (rc == ENOENT)
                    {
                        mkdir (s_sprintf ("%sfiles", PrefUserDir (prG)), 0700);
                        mkdir (s_sprintf ("%sfiles" _OS_PATHSEPSTR "%s", PrefUserDir (prG), cont->screen), 0700);
                        ffile->sok = open (buf, O_CREAT | O_WRONLY | (off ? O_APPEND : O_TRUNC), 0660);
                    }
                    if (ffile->sok == -1)
                    {
                        rl_log_for (cont->nick, COLCONTACT);
                        rl_printf (i18n (2083, "Cannot open file %s: %s (%d).\n"),
                                 buf, strerror (rc), rc);
                        ConnectionD (fpeer);
                        return;
                    }
                }
                ffile->connect = CONNECT_OK;
                ffile->oscar_file_len = len;
                ffile->oscar_file_done = off;

                rl_log_for (cont->nick, COLCONTACT);
                rl_printf (i18n (2162, "Receiving file %s (%s) with %ld bytes as %s.\n"),
                         name->txt, text->txt, UD2UL (len), buf);
            }
            pak = PeerPacketC (fpeer, 3);
            PacketWrite4 (pak, off);
            PacketWrite4 (pak, 0);
            PacketWrite4 (pak, 64);
            PacketWrite4 (pak, 1);
            PeerPacketSend (fpeer, pak);
            PacketD (pak);
            return;

        case 3:
            off = PacketRead4 (pak);
                  PacketRead4 (pak); /* EMPTY */
                  PacketRead4 (pak); /* SPEED */
            nr  = PacketRead4 (pak); /* NR */
            PacketD (pak);
            
            rl_log_for (cont->nick, COLCONTACT);
            rl_printf (i18n (2163, "Sending file %ld at offset %ld.\n"),
                       UD2UL (nr), UD2UL (off));
            
            err = lseek (fpeer->oscar_file->sok, off, SEEK_SET);
            if (err == -1)
            {
                err = errno;
                rl_log_for (cont->nick, COLCONTACT);
                rl_printf (i18n (2084, "Error while seeking to offset %ld: %s (%d).\n"),
                           UD2UL (off), strerror (err), err);
                TCPClose (fpeer);
                return;
            }
            fpeer->oscar_file->oscar_file_done = off;
            fpeer->oscar_file->connect = CONNECT_OK;
            
            QueueRetry (fpeer, QUEUE_PEER_FILE, cont);
            return;
            
        case 4:
            rl_log_for (cont->nick, COLCONTACT);
            rl_printf (i18n (2169, "File transfer aborted by peer (%d).\n"),
                     PacketRead1 (pak));
            PacketD (pak);
            PeerFileClose (fpeer);
            return;

        case 5:
            rl_printf ("FIXME: Ignoring speed change to %d.\n",
                     PacketRead1 (pak));
            PacketD (pak);
            return;

        case 6:
            if (fpeer->oscar_file->oscar_file_done + pak->len - 1 > fpeer->oscar_file->oscar_file_len)
            {
                rl_log_for (cont->nick, COLCONTACT);
                rl_printf (i18n (2165, "The peer sent more bytes (%ld) than the file length (%ld).\n"),
                           UD2UL (fpeer->oscar_file->oscar_file_done + pak->len - 1), UD2UL (fpeer->oscar_file->oscar_file_len));
                PacketD (pak);
                TCPClose (fpeer);
                return;
            }
            if (pak->len <= 1)
            {
                PacketD (pak);
                return;
            }
            len = write (fpeer->oscar_file->sok, pak->data + 1, pak->len - 1);
            if (len + 1 != pak->len)
            {
                rl_log_for (cont->nick, COLCONTACT);
                rl_printf (i18n (2575, "Error writing to file (%lu bytes written out of %u).\n"), UD2UL (len), pak->len - 1);
                PacketD (pak);
                TCPClose (fpeer);
                return;
            }
            fpeer->oscar_file->oscar_file_done += len;
            if (fpeer->oscar_file->oscar_file_len == fpeer->oscar_file->oscar_file_done)
            {
                ReadLinePromptReset ();
                rl_log_for (cont->nick, COLCONTACT);
                rl_print  (i18n (2166, "Finished receiving file.\n"));
#if HAVE_FSYNC
                fsync (fpeer->oscar_file->sok);
#endif
                close (fpeer->oscar_file->sok);
                fpeer->oscar_file->sok = -1;
                fpeer->oscar_file->connect = CONNECT_OK;
            }
            else if (fpeer->oscar_file->oscar_file_len)
            {
                ReadLinePromptUpdate (s_sprintf ("[%s%ld %02d%%%s] %s%s",
                              COLINCOMING, 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>")));
            }
            PacketD (pak);
            return;
        default:
            rl_log_for (cont->nick, COLCONTACT);
            rl_print  (i18n (2167, "Error - unknown packet.\n"));
            rl_print  (s_dump (pak->data, pak->len));
            PacketD (pak);
            PeerFileClose (fpeer);
    }
    if ((prG->verbose & DEB_TCP) && err)
    {
        rl_printf ("%s %s: %d\n", s_now, i18n (2029, "Protocol error on peer-to-peer connection"), err);
        PeerFileClose (fpeer);
    }
}