Пример #1
0
/*
 * Checks the file request response.
 */
BOOL PeerFileAccept (Connection *peer, UWORD ackstatus, UDWORD port)
{
    Connection *flist, *fpeer;
    
    flist = PeerFileCreate (peer->serv);
    fpeer = ServerFindChild (flist->serv, peer->cont, TYPE_FILEDIRECT);
    
    if (!flist || !fpeer || !port || (ackstatus == TCP_ACK_REFUSE))
    {
        if (fpeer)
            TCPClose (fpeer);

        return 0;
    }

    ASSERT_MSGDIRECT(peer);
    ASSERT_FILELISTEN(flist);
    ASSERT_FILEDIRECT(fpeer);
    
    fpeer->connect  = 0;
    fpeer->oscar_dc_seq  = 0;
    fpeer->port     = port;
    fpeer->ip       = peer->ip;
    s_repl (&fpeer->server, s_ip (fpeer->ip));
    
    if (prG->verbose)
        rl_printf (i18n (2520, "Opening file transfer connection to %s:%s%ld%s... \n"),
                  s_wordquote (fpeer->server), COLQUOTE, UD2UL (fpeer->port), COLNONE);

    TCPDispatchConn (fpeer);
    
    return 1;
}
Пример #2
0
/*
 * "Logs in" TCP connection by opening listening socket.
 */
Event *RemoteOpen (Connection *remo)
{
    s_repl (&remo->server, s_realpath (remo->pref_server));

    rl_printf (i18n (2223, "Opening scripting FIFO at %s... "), s_wordquote (remo->server));

    remo->connect     = 0;
    remo->our_seq     = 0;
    remo->open        = &RemoteOpen;
    remo->dispatch    = &RemoteDispatch;
    remo->reconnect   = NULL;
    remo->close       = &RemoteClose;
    remo->our_session = 0;
    remo->ip          = 0;
    remo->port        = 0;

    UtilIOConnectF (remo);
    
    if (remo->connect)
        remo->connect = CONNECT_OK | CONNECT_SELECT_R;
    return NULL;
}
Пример #3
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);
}
Пример #4
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);
    }
}
Пример #5
0
io_err_t UtilIOShowError (Connection *conn, io_err_t rc)
{
    int e = errno;
    const char *t = NULL;

    switch (rc) {
    
        case IO_CONNECTED: 
            rl_print ("");
            if (prG->verbose || (conn->serv && conn == conn->serv->conn))
                if (rl_pos () > 0)
                     rl_print (i18n (1634, "ok.\n"));
            return IO_CONNECTED;

        case IO_OK:
            return IO_OK;

        case IO_NO_MEM:
        case IO_NO_PARAM:
            assert (0);

        case IO_NO_SOCKET:
            if (1) t = i18n (1638, "Couldn't create socket"); else
        case IO_NO_NONBLOCK:
            if (1) t = i18n (1950, "Couldn't set socket nonblocking"); else
        case IO_NO_HOSTNAME:
            if (1) t = i18n (2743, "Can't find hostname"); else
        case IO_CONN_TO:
            if (1) t = i18n (2744, "Connection timed out"); else
        case IO_NO_CONN:
                   t = i18n (1952, "Couldn't open connection");
            if (prG->verbose || (conn->serv && conn == conn->serv->conn))
            {
                Contact *cont = conn->cont;
                char *semi = strchr (conn->server, ';');
                if (semi)
                    *semi = 0;
                rl_log_for (cont->nick, COLCONTACT);
                rl_printf (i18n (2745, "Opening connection to %s:%s%ld%s "),
                          s_wordquote (conn->server), COLQUOTE, UD2UL (conn->port), COLNONE);
                if (semi)
                    *semi = ';';
                rl_print (i18n (1949, "failed:\n"));
                rl_printf ("%s [%d]\n",
                    s_sprintf  ("%s: %s (%d).", t, conn->dispatcher->funcs->f_err (conn, conn->dispatcher), e),
                    __LINE__);
            }
            UtilIOClose (conn);
            return IO_RW;
        case IO_CLOSED:
#ifdef ECONNRESET
            if (!errno)
                errno = ECONNRESET;
#endif
        case IO_RW:
            if (prG->verbose || (conn->serv && conn == conn->serv->conn))
            {
                Contact *cont;
                if ((cont = conn->cont))
                {
                    rl_log_for (cont->nick, COLCONTACT);
                    rl_printf (i18n (1878, "Error while reading from socket: %s (%d, %d)\n"), conn->dispatcher->funcs->f_err (conn, conn->dispatcher), rc, errno);
                }
            }
            UtilIOClose (conn);
            return IO_RW;
        default:
            assert (0);
    }
}