summaryrefslogtreecommitdiff
path: root/server/dispatch.c
diff options
context:
space:
mode:
authorGravatar Greg Hudson <ghudson@mit.edu>1998-08-21 02:25:30 +0000
committerGravatar Greg Hudson <ghudson@mit.edu>1998-08-21 02:25:30 +0000
commit761175ea525dc5204f02411518a594213f48392b (patch)
treee0272741b1a4f76e36e81dd1af710c68a4e6152d /server/dispatch.c
parent8d55abeae716c5dab7e2237dac09e0c374fdbd85 (diff)
Don't penalize clients when we get an EAGAIN or ENOBUFS from sendto().
Diffstat (limited to 'server/dispatch.c')
-rw-r--r--server/dispatch.c61
1 files changed, 35 insertions, 26 deletions
diff --git a/server/dispatch.c b/server/dispatch.c
index 50769a7..db66bbe 100644
--- a/server/dispatch.c
+++ b/server/dispatch.c
@@ -499,9 +499,7 @@ nack_release(client)
for (i = 0; i < NACKTAB_HASHSIZE; i++) {
for (nacked = nacktab[i]; nacked; nacked = next) {
next = nacked->next;
- if (nacked->dest.addr.sin_addr.s_addr ==
- client->addr.sin_addr.s_addr &&
- nacked->dest.addr.sin_port == client->addr.sin_port) {
+ if (nacked->client == client) {
timer_reset(nacked->timer);
LIST_DELETE(nacked);
free(nacked->packet);
@@ -529,12 +527,14 @@ xmit_frag(notice, buf, len, waitforack)
char *savebuf;
Unacked *nacked;
Code_t retval;
- int hashval;
+ int hashval, sendfail = 0;
retval = ZSendPacket(buf, len, 0);
if (retval != ZERR_NONE) {
syslog(LOG_WARNING, "xmit_frag send: %s", error_message(retval));
- return retval;
+ if (retval != EAGAIN)
+ return retval;
+ sendfail = 1;
}
/* now we've sent it, mark it as not ack'ed */
@@ -556,7 +556,8 @@ xmit_frag(notice, buf, len, waitforack)
memcpy(savebuf, buf, len);
sin = ZGetDestAddr();
- nacked->rexmits = 0;
+ nacked->client = NULL;
+ nacked->rexmits = (sendfail) ? -1 : 0;
nacked->packet = savebuf;
nacked->dest.addr = sin;
nacked->packsz = len;
@@ -580,7 +581,7 @@ xmit(notice, dest, auth, client)
{
char *noticepack;
Unacked *nacked;
- int packlen;
+ int packlen, sendfail = 0;
Code_t retval;
#if 0
@@ -641,8 +642,11 @@ xmit(notice, dest, auth, client)
if (retval != ZERR_NONE) {
syslog(LOG_WARNING, "xmit xmit: (%s/%d) %s", inet_ntoa(dest->sin_addr),
ntohs(dest->sin_port), error_message(retval));
- free(noticepack);
- return;
+ if (retval != EAGAIN) {
+ free(noticepack);
+ return;
+ }
+ sendfail = 1;
}
/* now we've sent it, mark it as not ack'ed */
@@ -655,7 +659,8 @@ xmit(notice, dest, auth, client)
return;
}
- nacked->rexmits = 0;
+ nacked->client = client;
+ nacked->rexmits = (sendfail) ? -1 : 0;
nacked->packet = noticepack;
nacked->dest.addr = *dest;
nacked->packsz = packlen;
@@ -676,7 +681,6 @@ rexmit(arg)
{
Unacked *nacked = (Unacked *) arg;
int retval;
- Client *client;
#if 1
syslog(LOG_DEBUG, "rexmit %s/%d #%d time %d",
@@ -686,22 +690,23 @@ rexmit(arg)
nacked->rexmits++;
if (rexmit_times[nacked->rexmits] == -1) {
- /* Unresponsive client, find it in our database. */
- client = client_find(&nacked->dest.addr.sin_addr,
- nacked->dest.addr.sin_port);
-
- /* unlink & free nacked */
- LIST_DELETE(nacked);
- free(nacked->packet);
- free(nacked);
-
- /* Kill the client. */
- if (client) {
- server_kill_clt(client);
- client_deregister(client, 1);
+ if (!nacked->client
+ || NOW - nacked->client->last_ack >= CLIENT_GIVEUP_MIN) {
+ /* The client (if there was one) has been unresponsive. Give up
+ * sending this packet, and kill the client if there was one. */
+ LIST_DELETE(nacked);
+ free(nacked->packet);
+ free(nacked);
+ if (nacked->client) {
+ server_kill_clt(nacked->client);
+ client_deregister(nacked->client, 1);
+ }
+ return;
+ } else {
+ /* The client has sent us an ack recently. Retry with the maximum
+ * retransmit time. */
+ nacked->rexmits--;
}
-
- return;
}
/* retransmit the packet */
@@ -716,6 +721,8 @@ rexmit(arg)
retval = ZSendPacket(nacked->packet, nacked->packsz, 0);
if (retval != ZERR_NONE)
syslog(LOG_WARNING, "rexmit xmit: %s", error_message(retval));
+ if (retval == EAGAIN)
+ nacked->rexmits--;
}
/* reset the timer */
@@ -834,6 +841,8 @@ nack_cancel(notice, who)
if (nacked->dest.addr.sin_addr.s_addr == who->sin_addr.s_addr
&& nacked->dest.addr.sin_port == who->sin_port
&& ZCompareUID(&nacked->uid, &notice->z_uid)) {
+ if (nacked->client)
+ nacked->client->last_ack = NOW;
timer_reset(nacked->timer);
free(nacked->packet);
LIST_DELETE(nacked);