Fix various problems with adding and removing module DCC bindings
Change remove_all_dcc_binds() so that it only removes DCC binds for the module supplied, as it's supposed to. get_dcc_type() should ignore the first entry in dcc_types[] ("<none>") otherwise the client will try to respond to DCC requests with that name. Explicitly track the number of entries in the dcc_types[] array rather than using a NULL terminator. This allows us to change dcc_types[] to use NULL entries to mark unused slots in the array, rather than pointers to entries with a NULL .name element. Together, this means that the dcc_types[] array is only resized when it actually needs to be grown and removal works correctly (without eg. prematurely marking the end of the array). Make add_dcc_bind() fail if the requested DCC type has already been bound by a module (this still allows one module at a time to rebind a built-in DCC type). Previously the behaviour was ill-defined in this case.
This commit is contained in:
parent
5ae42802ec
commit
9e7fc85ae1
|
@ -1,5 +1,10 @@
|
|||
[Changes 1.2.2]
|
||||
|
||||
* Fix various problems with adding and removing module DCC bindings. The
|
||||
same DCC type cannot be bound by more than one module simultaneously. The
|
||||
remove_all_dcc_binds() function now only removes all DCC bindings for the
|
||||
given module. (caf)
|
||||
|
||||
* Fix crash when unloading the arcfour module. (caf)
|
||||
|
||||
* Change add_dcc_bind() to collect all function pointer arguments into a
|
||||
|
|
|
@ -156,7 +156,7 @@ struct dcc_offer {
|
|||
int check_dcc_socket(int);
|
||||
char *get_dcc_info(SocketList *, DCC_int *, int);
|
||||
void init_dcc_table(void);
|
||||
int BX_remove_all_dcc_binds(char *);
|
||||
int BX_remove_all_dcc_binds(const char *);
|
||||
int BX_remove_dcc_bind(char *, int);
|
||||
|
||||
/* Function pointers for the operations implementing a DCC type.
|
||||
|
|
|
@ -606,7 +606,7 @@ extern Function_ptr *global;
|
|||
#define erase_dcc_info (*(void (*)(int, int, char *, ...))global[ERASE_DCC_INFO])
|
||||
#define add_dcc_bind (*(int (*)(char *, char *, const struct dcc_ops *))global[ADD_DCC_BIND])
|
||||
#define remove_dcc_bind (*(int (*)(char *, int ))global[REMOVE_DCC_BIND])
|
||||
#define remove_all_dcc_binds (*(int (*)(char *))global[REMOVE_ALL_DCC_BINDS])
|
||||
#define remove_all_dcc_binds (*(int (*)(const char *))global[REMOVE_ALL_DCC_BINDS])
|
||||
#define get_active_count (*(int (*)(void ))global[GET_ACTIVE_COUNT])
|
||||
#define get_num_queue (*(int (*)(void ))global[GET_NUM_QUEUE])
|
||||
#define add_to_queue (*(int (*)(char *, char *, pack *))global[ADD_TO_QUEUE])
|
||||
|
|
117
source/dcc.c
117
source/dcc.c
|
@ -74,7 +74,7 @@ extern int use_socks;
|
|||
#define DCC_HASHSIZE 11
|
||||
static HashEntry dcc_no_flood[DCC_HASHSIZE];
|
||||
|
||||
struct _dcc_types_
|
||||
struct dcc_type
|
||||
{
|
||||
char *name;
|
||||
char *module;
|
||||
|
@ -84,7 +84,7 @@ struct _dcc_types_
|
|||
|
||||
static const struct dcc_ops null_ops = { NULL, NULL, NULL, NULL, NULL };
|
||||
|
||||
static struct _dcc_types_ _dcc_types[] =
|
||||
static struct dcc_type builtin_dcc_types[] =
|
||||
{
|
||||
{"<none>", NULL, 0, NULL},
|
||||
{"CHAT", NULL, DCC_CHAT, &null_ops},
|
||||
|
@ -98,10 +98,11 @@ static struct _dcc_types_ _dcc_types[] =
|
|||
{"FTP", NULL, DCC_FTPOPEN, &null_ops},
|
||||
{"FTPGET", NULL, DCC_FTPGET, &null_ops},
|
||||
{"FTPSEND", NULL, DCC_FTPSEND, &null_ops},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
static struct _dcc_types_ **dcc_types = NULL;
|
||||
static const size_t n_builtin_dcc_types = sizeof builtin_dcc_types / sizeof builtin_dcc_types[0];
|
||||
static struct dcc_type **dcc_types = NULL;
|
||||
static size_t n_dcc_types = 0;
|
||||
|
||||
static char DCC_current_transfer_buffer[BIG_BUFFER_SIZE/4];
|
||||
unsigned int send_count_stat = 0;
|
||||
|
@ -286,9 +287,10 @@ static int get_dcc_type(const char *name)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; dcc_types[i]->name; i++)
|
||||
/* Start at 1 to ignore the <none> type */
|
||||
for (i = 1; i < n_dcc_types; i++)
|
||||
{
|
||||
if (!my_stricmp(name, dcc_types[i]->name))
|
||||
if (dcc_types[i] && !my_stricmp(name, dcc_types[i]->name))
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -4255,53 +4257,89 @@ char *nick,
|
|||
}
|
||||
}
|
||||
|
||||
/* add_dcc_bind()
|
||||
*
|
||||
* Bind a new set of DCC operations to a DCC name. This can either be a completely new DCC type,
|
||||
* or a new set of operations for a builtin DCC type. This fails if the given DCC name is already
|
||||
* bound by another module.
|
||||
*/
|
||||
int BX_add_dcc_bind(char *name, char *module, const struct dcc_ops *dcc_ops)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; dcc_types[i]->name; i++)
|
||||
int i;
|
||||
|
||||
i = get_dcc_type(name);
|
||||
|
||||
if (i < 0)
|
||||
{
|
||||
if (!my_stricmp(dcc_types[i]->name, name))
|
||||
break;
|
||||
}
|
||||
if (i >= 0xfe) return 0;
|
||||
if (!dcc_types[i])
|
||||
{
|
||||
RESIZE(dcc_types, struct _dcc_types_ *, i + 2);
|
||||
dcc_types[i] = new_malloc(sizeof(struct _dcc_types_));
|
||||
}
|
||||
if (!dcc_types[i]->name)
|
||||
/* New DCC type, requires a new entry in the list */
|
||||
for (i = 0; i < n_dcc_types; i++)
|
||||
{
|
||||
if (!dcc_types[i])
|
||||
break;
|
||||
}
|
||||
|
||||
if (i & ~DCC_TYPES)
|
||||
{
|
||||
yell("Failed to add DCC binding [%s] for module [%s], too many DCC bindings.",
|
||||
name, module);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (i >= n_dcc_types)
|
||||
{
|
||||
n_dcc_types = i + 1;
|
||||
RESIZE(dcc_types, struct dcc_type *, n_dcc_types);
|
||||
}
|
||||
|
||||
dcc_types[i] = new_malloc(sizeof(struct dcc_type));
|
||||
malloc_strcpy(&dcc_types[i]->name, name);
|
||||
dcc_types[i]->type = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dcc_types[i]->module)
|
||||
{
|
||||
yell("Failed to add DCC binding [%s] for module [%s], already bound by module [%s].",
|
||||
name, module, dcc_types[i]->module);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
malloc_strcpy(&dcc_types[i]->module, module);
|
||||
dcc_types[i]->dcc_ops = dcc_ops;
|
||||
dcc_types[i]->type = i;
|
||||
return i;
|
||||
}
|
||||
|
||||
int BX_remove_dcc_bind(char *name, int type)
|
||||
{
|
||||
int i = type & DCC_TYPES;
|
||||
if (!dcc_types[i]->module)
|
||||
if (type >= n_dcc_types || !dcc_types[type] || !dcc_types[type]->module)
|
||||
return 0;
|
||||
new_free(&dcc_types[i]->module);
|
||||
dcc_types[i]->dcc_ops = &null_ops;
|
||||
if (i > DCC_FTPSEND)
|
||||
|
||||
new_free(&dcc_types[type]->module);
|
||||
dcc_types[type]->dcc_ops = &null_ops;
|
||||
if (type >= n_builtin_dcc_types)
|
||||
{
|
||||
new_free(&dcc_types[i]->name);
|
||||
new_free(&dcc_types[i]);
|
||||
/* RESIZE(dcc_types, struct _dcc_types *, i - 1);*/
|
||||
new_free(&dcc_types[type]->name);
|
||||
new_free(&dcc_types[type]);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BX_remove_all_dcc_binds(char *name)
|
||||
/* remove_all_dcc_binds()
|
||||
*
|
||||
* Remove all DCC bindings added by a given module.
|
||||
*/
|
||||
int BX_remove_all_dcc_binds(const char *module)
|
||||
{
|
||||
int ret = 0;
|
||||
int i, j;
|
||||
/* scan to end of list */
|
||||
for (i = 0; dcc_types[i]->name; i++);
|
||||
i--;
|
||||
for (j = i; j > 0; j--)
|
||||
ret += remove_dcc_bind(dcc_types[j]->name, dcc_types[j]->type);
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_dcc_types; i++)
|
||||
{
|
||||
if (dcc_types[i] && dcc_types[i]->module && !strcasecmp(dcc_types[i]->module, module))
|
||||
ret += remove_dcc_bind(dcc_types[i]->name, i);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -4309,13 +4347,12 @@ void init_dcc_table(void)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; _dcc_types[i].name; i++);
|
||||
RESIZE(dcc_types, struct _dcc_types_ *, i + 1);
|
||||
for (i = 0; _dcc_types[i].name; i++)
|
||||
n_dcc_types = n_builtin_dcc_types;
|
||||
RESIZE(dcc_types, struct dcc_type *, n_dcc_types);
|
||||
for (i = 0; i < n_dcc_types; i++)
|
||||
{
|
||||
dcc_types[i] = &_dcc_types[i];
|
||||
dcc_types[i] = &builtin_dcc_types[i];
|
||||
}
|
||||
dcc_types[i] = new_malloc(sizeof(struct _dcc_types_));
|
||||
}
|
||||
|
||||
char *get_dcc_info(SocketList *s, DCC_int *n, int i)
|
||||
|
|
Loading…
Reference in New Issue