Here is a module I found once. I presume that I compiled it according
to the given instructions.

/*
 dcc-send-limiter.c : Limit the transmit speed of DCC sends

 For irssi 0.8+

 compile:
   export IRSSI=~/cvs/irssi
   gcc dcc-send-limiter.c -o ~/.irssi/modules/libdcc_send_limiter.so -g -shared 
-I$IRSSI -I$IRSSI/src -I$IRSSI/src/core -I$IRSSI/src/irc/core 
-I$IRSSI/src/irc/dcc `glib-config --cflags` -O2 -fPIC

 usage:
   /LOAD dcc_send_limiter

    Copyright (C) 2001 Timo Sirainen

    Modified 2001/07/04 by Martin Persson
        * updated to only keep track of the last 30 sec

    Modified 2001/07/01 by Martin Persson
        * added speed send checks
        * fixed crash when destroying dcc sends 
          that didn't contain any module data
        * fixed crash when initiating dcc send


    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#define MODULE_NAME "irc/dcc/limiter"
#define HAVE_CONFIG_H

#include "common.h"
#include "signals.h"
#include "network.h"
#include "settings.h"

#include "irc.h"
#include "dcc-send.h"

typedef struct {
        int timeout_tag;

        unsigned long skip_bytes;
        unsigned long starttime;
        unsigned long max_speed;
} MODULE_SEND_DCC_REC;

static void dcc_send_data(SEND_DCC_REC *dcc);

static void reset_dcc_send(SEND_DCC_REC *dcc)
{
        MODULE_SEND_DCC_REC *mdcc;

        if (g_slist_find(dcc_conns, dcc) == NULL) {
                /* the DCC was closed during the wait */
                return;
        }

        mdcc = MODULE_DATA(dcc);
        g_source_remove(mdcc->timeout_tag);
        mdcc->timeout_tag = -1;

        dcc->tagwrite = g_input_add(dcc->handle, G_INPUT_WRITE,
                                    (GInputFunction) dcc_send_data, dcc);
}

static int sent_too_much(SEND_DCC_REC *dcc, MODULE_SEND_DCC_REC *mdcc)
{
        GTimeVal gtv;
        unsigned long timediff, curtime;
        unsigned long transfd, speed;

        /* 0 == unlimited speed */
        if (mdcc->max_speed == 0) return 0;

        /* get time difference in milliseconds */
        g_get_current_time(&gtv);
        curtime = (gtv.tv_sec * 1000) + (gtv.tv_usec / 1000);

        transfd = (dcc->transfd - mdcc->skip_bytes);
        timediff = curtime - mdcc->starttime + 1;
        speed = ((transfd * 1000) / timediff);

        /* reset speed counter every 30 seconds */
        if (timediff >= 30000) {
                mdcc->starttime = curtime;
                mdcc->skip_bytes = dcc->transfd;
        }

        return (speed > (mdcc->max_speed * 1024));
}

/* input function: DCC SEND - we're ready to send more data */
static void dcc_send_data(SEND_DCC_REC *dcc)
{
        MODULE_SEND_DCC_REC *mdcc;
        char buffer[512];
        int ret, max_speed;
        GTimeVal gtv;

        mdcc = MODULE_DATA(dcc);

        max_speed = settings_get_int("dcc_send_top_speed");
        if (max_speed != mdcc->max_speed) {
                /* speed setting has changed, calculate speed from current 
position 
                   instead of from the start to eliminate speed 
boosts/slowdowns */

                mdcc->max_speed = max_speed;
                mdcc->skip_bytes = dcc->transfd;

                g_get_current_time(&gtv);
                mdcc->starttime = (gtv.tv_sec * 1000) + (gtv.tv_usec / 1000);
        }

        if (sent_too_much(dcc, mdcc)) {
                /* disable calling this function for 1/10th of a second. */
                g_source_remove(dcc->tagwrite);
                dcc->tagwrite = -1;
                mdcc->timeout_tag =
                        g_timeout_add(100, (GSourceFunc) reset_dcc_send, dcc);
                return;
        }

        ret = read(dcc->fhandle, buffer, sizeof(buffer));
        if (ret <= 0) {
                /* no need to call this function anymore..
                   in fact it just eats all the cpu.. */
                dcc->waitforend = TRUE;
                g_source_remove(dcc->tagwrite);
                dcc->tagwrite = -1;
                return;
        }

        ret = net_transmit(dcc->handle, buffer, ret);
        if (ret > 0) dcc->transfd += ret;
        dcc->gotalldata = FALSE;

        lseek(dcc->fhandle, dcc->transfd, SEEK_SET);

        signal_emit("dcc transfer update", 1, dcc);
}

static void sig_dcc_connected(SEND_DCC_REC *dcc)
{
        MODULE_SEND_DCC_REC *mdcc;
        GTimeVal gtv;

        if (!IS_DCC_SEND(dcc))
                return;

        mdcc = g_new0(MODULE_SEND_DCC_REC, 1);
        MODULE_DATA_SET(dcc, mdcc);
        mdcc->timeout_tag = -1;
        mdcc->skip_bytes = 0;
        mdcc->max_speed = settings_get_int("dcc_send_top_speed");

        /* get starttime in milliseconds */
        g_get_current_time(&gtv);
        mdcc->starttime = (gtv.tv_sec * 1000) + (gtv.tv_usec / 1000);

        g_source_remove(dcc->tagwrite);
        dcc->tagwrite = g_input_add(dcc->handle, G_INPUT_WRITE,
                                        (GInputFunction) dcc_send_data, dcc);
}

static void sig_dcc_destroyed(SEND_DCC_REC *dcc)
{
        MODULE_SEND_DCC_REC *mdcc;

        if (!IS_DCC_SEND(dcc))
                return;

        mdcc = MODULE_DATA(dcc);
        if (mdcc != NULL) {
                if (mdcc->timeout_tag != -1)
                        g_source_remove(mdcc->timeout_tag);

                g_free(mdcc);
        }
}

void dcc_send_limiter_init(void)
{
        settings_add_int("dcc", "dcc_send_top_speed", 30);

        signal_add_last("dcc connected", (SIGNAL_FUNC) sig_dcc_connected);
        signal_add_first("dcc destroyed", (SIGNAL_FUNC) sig_dcc_destroyed);

        module_register("dcc_send_limiter", "core");
}

void dcc_send_limiter_deinit(void)
{
        signal_remove("dcc connected", (SIGNAL_FUNC) sig_dcc_connected);
        signal_remove("dcc destroyed", (SIGNAL_FUNC) sig_dcc_destroyed);
}

-Olaf.
-- 
___ Olaf 'Rhialto' Seibert  -- There's no point being grown-up if you 
\X/ rhialto/at/xs4all.nl    -- can't be childish sometimes. -The 4th Doctor

Reply via email to