char *name;
void (*handler)(struct socket *sk, void *data, char *cmd, char *args);
int stop;
+ int limit;
};
struct qcommand
char *string;
};
+struct qcmdqueue
+{
+ struct qcommand *f, *l;
+ int size;
+};
+
struct dchub
{
struct socket *sk;
char *inbuf;
size_t inbufdata, inbufsize;
- struct qcommand *queue;
+ struct qcmdqueue queue;
int extended, dcppemu;
char *charset;
char *nativename;
off_t curread, totalsize;
int freeing;
struct timer *timeout;
- struct qcommand *queue;
+ struct qcmdqueue queue;
struct transfer *transfer;
int state;
int ptclose; /* Close after transfer is complete */
return(ep);
}
-static struct qcommand *newqcmd(struct qcommand **queue, char *string)
+static struct qcommand *newqcmd(struct qcmdqueue *queue, char *string)
{
struct qcommand *new;
- while(*queue != NULL)
- queue = &(*queue)->next;
new = smalloc(sizeof(*new));
new->string = sstrdup(string);
- new->next = *queue;
- *queue = new;
+ new->next = NULL;
+ if(queue->l == NULL)
+ queue->f = new;
+ else
+ queue->l->next = new;
+ queue->l = new;
+ queue->size++;
return(new);
}
-static struct qcommand *ulqcmd(struct qcommand **queue)
+static struct qcommand *ulqcmd(struct qcmdqueue *queue)
{
struct qcommand *qcmd;
- if((qcmd = *queue) == NULL)
+ if((qcmd = queue->f) == NULL)
return(NULL);
- *queue = qcmd->next;
+ if((queue->f = qcmd->next) == NULL)
+ queue->l = NULL;
+ queue->size--;
return(qcmd);
}
struct dchub *hub;
char *p;
wchar_t *buf;
- struct fnetpeer *peer, *npeer;
+ struct fnetpeer *peer;
hub = fn->data;
- for(peer = fn->peers; peer != NULL; peer = peer->next)
+ for(peer = btreeiter(fn->peers); peer != NULL; peer = btreeiter(NULL))
peer->flags.b.delete = 1;
while((p = strstr(args, "$$")) != NULL)
{
}
args = p + 2;
}
- for(peer = fn->peers; peer != NULL; peer = npeer)
- {
- npeer = peer->next;
- if(peer->flags.b.delete)
- fnetdelpeer(peer);
- }
+ fnetpeerdm(fn);
hubhandleaction(sk, fn, cmd, args);
}
struct fnetpeer *peer;
hub = fn->data;
- for(peer = fn->peers; peer != NULL; peer = peer->next)
+ for(peer = btreeiter(fn->peers); peer != NULL; peer = btreeiter(NULL))
peer->flags.b.op = 0;
while((p = strstr(args, "$$")) != NULL)
{
{"$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;
}
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)
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 > 50)
+ sk->ignread = 1;
}
}
} else if(peer->state == PEER_TTHL) {
handletthl(peer);
}
+ if(peer->inbufdata > 500000)
+ sk->ignread = 1;
}
static void peererror(struct socket *sk, int err, struct dcpeer *peer)
struct dchub *hub;
struct dcpeer *peer, *nextpeer;
struct qcommand *qcmd;
- int ret;
+ int ret, quota;
ret = 0;
+ quota = 20;
for(fn = fnetnodes; fn != NULL; fn = nextfn)
{
nextfn = fn->next;
if(fn->data == NULL)
continue;
hub = (struct dchub *)fn->data;
- if((qcmd = ulqcmd(&hub->queue)) != NULL)
+ while((quota > 0) && ((qcmd = ulqcmd(&hub->queue)) != NULL))
{
if(*qcmd->string == '$')
{
}
freeqcmd(qcmd);
ret = 1;
- break;
+ quota--;
}
+ if(hub->queue.size < 1000)
+ hub->sk->ignread = 0;
+ if(quota < 1)
+ break;
}
+ quota = 20;
for(peer = peers; peer != NULL; peer = nextpeer)
{
nextpeer = peer->next;
- if((qcmd = ulqcmd(&peer->queue)) != NULL)
+ while((quota > 0) && ((qcmd = ulqcmd(&peer->queue)) != NULL))
{
if(peer->timeout != NULL)
canceltimer(peer->timeout);
dispatchcommand(qcmd, peercmds, peer->sk, peer);
freeqcmd(qcmd);
ret = 1;
- break;
+ quota--;
}
+ if((peer->queue.size < 50) && (peer->inbufdata < 500000))
+ peer->sk->ignread = 0;
+ if(quota < 1)
+ break;
}
return(ret);
}