summaryrefslogtreecommitdiff
path: root/server/dispatch.c
diff options
context:
space:
mode:
authorGravatar Greg Hudson <ghudson@mit.edu>1994-10-31 00:34:26 +0000
committerGravatar Greg Hudson <ghudson@mit.edu>1994-10-31 00:34:26 +0000
commit2d272b7e42c6da45cc81c504854c042f0c900d24 (patch)
tree93c4cfb8ad33db4838a5294d32083353e7319fdd /server/dispatch.c
parentdab687ed495aeadda5393257e07d2a197c4dc741 (diff)
Support for more streamlined zephyr sending and other features.
Diffstat (limited to 'server/dispatch.c')
-rw-r--r--server/dispatch.c98
1 files changed, 72 insertions, 26 deletions
diff --git a/server/dispatch.c b/server/dispatch.c
index 40dd7d1..2c2fb16 100644
--- a/server/dispatch.c
+++ b/server/dispatch.c
@@ -74,6 +74,7 @@ ZSTRING *class_control, *class_admin, *class_hm, *class_ulogin,
static void nack_cancel P((register ZNotice_t *, struct sockaddr_in *));
static void dispatch P((ZNotice_t *, int, struct sockaddr_in *, int));
+static int send_to_dest P((ZNotice_t *, int, ZDestination *dest, int));
#undef P
@@ -214,13 +215,11 @@ handle_packet()
input_sin.sin_addr.s_addr = new_notice.z_sender_addr.s_addr;
input_sin.sin_port = new_notice.z_port;
input_sin.sin_family = AF_INET;
- authentic = ZCheckAuthentication(&new_notice,
- &input_sin);
+ authentic = ZCheckAuthentication(&new_notice, &input_sin);
from_server = 1;
} else {
from_server = 0;
- authentic = ZCheckAuthentication(&new_notice,
- &whoisit);
+ authentic = ZCheckAuthentication(&new_notice, &whoisit);
}
switch (authentic) {
case ZAUTH_YES:
@@ -346,19 +345,20 @@ sendit(notice, auth, who)
int auth;
struct sockaddr_in *who;
{
- int acked = 0;
+ static int send_counter = 0;
+ int any = 0;
ZAcl_t *acl;
- register ZClientList_t *clientlist, *ptr;
- ZSTRING *z;
+ ZDestination dest;
+ ZSTRING *class;
- z = make_zstring(notice->z_class,1);
- if ((acl = class_get_acl(z)) != NULLZACLT) {
- free_zstring(z);
+ class = make_zstring(notice->z_class,1);
+ if ((acl = class_get_acl(class)) != NULLZACLT) {
/* if controlled and not auth, fail */
if (!auth) {
syslog(LOG_WARNING, "sendit unauthentic %s from %s",
notice->z_class, notice->z_sender);
clt_ack(notice, who, AUTH_FAILED);
+ free_zstring(class);
return;
}
/* if not auth to transmit, fail */
@@ -366,6 +366,7 @@ sendit(notice, auth, who)
syslog(LOG_WARNING, "sendit unauthorized %s from %s",
notice->z_class, notice->z_sender);
clt_ack(notice, who, AUTH_FAILED);
+ free_zstring(class);
return;
}
/* sender != inst and not auth to send to others --> fail */
@@ -377,6 +378,7 @@ sendit(notice, auth, who)
notice->z_class,
notice->z_class_inst);
clt_ack(notice, who, AUTH_FAILED);
+ free_zstring(class);
return;
}
}
@@ -391,38 +393,82 @@ sendit(notice, auth, who)
syslog(LOG_WARNING, "sendit unauthentic fake packet: claimed %s, real %s",
inet_ntoa(notice->z_sender_addr), buffer);
clt_ack(notice, who, AUTH_FAILED);
+ free_zstring(class);
return;
}
if (ntohl(notice->z_sender_addr.s_addr) != 0) {
syslog(LOG_WARNING, "sendit invalid address: claimed %s, real %s",
inet_ntoa(notice->z_sender_addr), buffer);
clt_ack(notice, who, AUTH_FAILED);
+ free_zstring(class);
return;
}
syslog(LOG_WARNING, "sendit addr mismatch: claimed %s, real %s",
inet_ntoa(notice->z_sender_addr), buffer);
}
- if ((clientlist = subscr_match_list(notice)) != NULLZCLT) {
- for (ptr = clientlist->q_forw;
- ptr != clientlist;
- ptr = ptr->q_forw) {
- /* for each client who gets this notice,
- send it along */
- xmit(notice, &(ptr->zclt_client->zct_sin), auth,
- ptr->zclt_client);
- if (!acked) {
- acked = 1;
- ack(notice, who);
- }
- }
- subscr_free_list(clientlist);
- }
- if (!acked)
+ /* Increment the send counter, used to prevent duplicate sends to
+ * clients. On the off-chance that we wrap around to 0, skip over
+ * it to prevent missing clients which have never had a packet
+ * sent to them. */
+ send_counter++;
+ if (send_counter == 0)
+ send_counter = 1;
+
+ /* Send to clients subscribed to the triplet itself. */
+ dest.classname = class;
+ dest.inst = make_zstring(notice->z_class_inst, 1);
+ dest.recip = make_zstring(notice->z_recipient, 0);
+ if (send_to_dest(notice, auth, &dest, send_counter))
+ any = 1;
+
+ /* Send to clients subscribed to the triplet with the instance
+ * substituted with the wildcard instance. */
+ free_zstring(dest.inst);
+ dest.inst = wildcard_instance;
+ if (send_to_dest(notice, auth, &dest, send_counter))
+ any = 1;
+
+ free_zstring(class);
+ free_zstring(dest.recip);
+ if (any)
+ ack(notice, who);
+ else
nack(notice, who);
}
/*
+ * Send to each client in the list. Avoid duplicates by setting
+ * last_send on each client to send_counter, a nonce which is updated
+ * by sendit() above.
+ */
+
+static int
+send_to_dest(notice, auth, dest, send_counter)
+ ZNotice_t *notice;
+ int auth;
+ ZDestination *dest;
+ int send_counter;
+{
+ register ZClientList_t *list, *p;
+ register ZClient_t *client;
+ register int any = 0;
+
+ list = triplet_lookup(dest);
+ if (list != NULLZCLT) {
+ for (p = list->q_forw; p != list; p = p->q_forw) {
+ client = p->zclt_client;
+ if (client->last_send == send_counter)
+ continue;
+ client->last_send = send_counter;
+ xmit(notice, &(client->zct_sin), auth, client);
+ any = 1;
+ }
+ }
+ return any;
+}
+
+/*
* Clean up the not-yet-acked queue and release anything destined
* for the client.
*/