char *name;
void (*handler)(struct socket *sk, void *data, char *cmd, char *args);
int stop;
+ int limit;
};
struct qcommand
struct qcmdqueue
{
struct qcommand *f, *l;
+ int size;
};
struct dchub
else
queue->l->next = new;
queue->l = new;
+ queue->size++;
return(new);
}
return(NULL);
if((queue->f = qcmd->next) == NULL)
queue->l = NULL;
+ queue->size--;
return(qcmd);
}
{"$OpList", cc(cmd_oplist)},
{"$MyINFO", cc(cmd_myinfo)},
{"$ForceMove", cc(cmd_forcemove)},
- {"$Search", cc(cmd_search)},
- {"$MultiSearch", cc(cmd_search)},
- {"$ConnectToMe", cc(cmd_connecttome)},
- {"$RevConnectToMe", cc(cmd_revconnecttome)},
+ {"$Search", cc(cmd_search), .limit = 100},
+ {"$MultiSearch", cc(cmd_search), .limit = 50},
+ {"$ConnectToMe", cc(cmd_connecttome), .limit = 200},
+ {"$RevConnectToMe", cc(cmd_revconnecttome), .limit = 500},
{"$GetNetInfo", cc(cmd_getnetinfo)},
{"$To:", cc(cmd_to)},
{"$SR", cc(cmd_sr)},
{"$GetZBlock", cc(cmd_getblock)},
{"$UGetZBlock", cc(cmd_getblock)},
{"$ADCGET", cc(cmd_adcget)},
- {"$ADCSND", cc(cmd_adcsnd), 1},
- {"$Sending", cc(cmd_sending), 1},
+ {"$ADCSND", cc(cmd_adcsnd), .stop = 1},
+ {"$Sending", cc(cmd_sending), .stop = 1},
{NULL, NULL}
};
#undef cc
static void hubread(struct socket *sk, struct fnetnode *fn)
{
struct dchub *hub;
+ struct command *cmd;
char *newbuf;
- size_t datalen;
+ size_t datalen, cnlen;
char *p;
hub = (struct dchub *)fn->data;
while((datalen > 0) && ((p = memchr(p, '|', datalen)) != NULL))
{
*(p++) = 0;
- newqcmd(&hub->queue, hub->inbuf);
+ for(cmd = hubcmds; cmd->handler != NULL; cmd++)
+ {
+ cnlen = strlen(cmd->name);
+ if(!strncmp(hub->inbuf, cmd->name, cnlen) && ((hub->inbuf[cnlen] == ' ') || (hub->inbuf[cnlen] == 0)))
+ break;
+ }
+ if((cmd->limit == 0) || (hub->queue.size < cmd->limit))
+ newqcmd(&hub->queue, hub->inbuf);
memmove(hub->inbuf, p, hub->inbufdata -= p - hub->inbuf);
datalen = hub->inbufdata;
p = hub->inbuf;
}
+ if(hub->queue.size > 1000)
+ sk->ignread = 1;
+ else
+ sk->ignread = 0;
}
static void huberr(struct socket *sk, int err, struct fnetnode *fn)
static void peerread(struct socket *sk, struct dcpeer *peer)
{
char *newbuf, *p;
- size_t datalen;
+ size_t datalen, cnlen;
struct command *cmd;
if((newbuf = sockgetinbuf(sk, &datalen)) == NULL)
return;
+ if(peer->inbufdata > 500000) /* Discard possibly malicious data */
+ peer->inbufdata = 0;
sizebuf2(peer->inbuf, peer->inbufdata + datalen, 1);
memcpy(peer->inbuf + peer->inbufdata, newbuf, datalen);
free(newbuf);
while((peer->inbufdata > 0) && (p = memchr(peer->inbuf, '|', peer->inbufdata)) != NULL)
{
*(p++) = 0;
- newqcmd(&peer->queue, peer->inbuf);
for(cmd = peercmds; cmd->handler != NULL; cmd++)
{
- if(!memcmp(peer->inbuf, cmd->name, strlen(cmd->name)) && ((peer->inbuf[strlen(cmd->name)] == ' ') || (peer->inbuf[strlen(cmd->name)] == '|')))
+ cnlen = strlen(cmd->name);
+ if(!strncmp(peer->inbuf, cmd->name, cnlen) && ((peer->inbuf[cnlen] == ' ') || (peer->inbuf[cnlen] == 0)))
break;
}
+ if((cmd->limit == 0) || (peer->queue.size < cmd->limit))
+ newqcmd(&peer->queue, peer->inbuf);
memmove(peer->inbuf, p, peer->inbufdata -= p - peer->inbuf);
if(cmd->stop)
{
peer->state = PEER_STOP;
break;
+ } else {
+ if(peer->queue.size > 1000)
+ sk->ignread = 1;
+ else
+ sk->ignread = 0;
}
}
} else if(peer->state == PEER_TTHL) {