static inline void send_single(struct worker_t *self, struct client_t *c, struct pbuf_t *pb) { if (c->udp_port && c->udpclient) clientaccount_add( c, IPPROTO_UDP, 0, 0, 0, 1, 0, 0); else clientaccount_add( c, IPPROTO_TCP, 0, 0, 0, 1, 0, 0); client_write(self, c, pb->data, pb->packet_len); }
static void process_outgoing_single(struct worker_t *self, struct pbuf_t *pb) { struct client_t *c, *cnext; struct client_t *origin = pb->origin; /* reduce pointer deferencing in tight loops */ /* // debug dump if (self->id == 0) { hlog(LOG_DEBUG, "o: %*s", pb->packet_len-2, pb->data); hlog(LOG_DEBUG, "b:%s%s", (pb->flags & F_FROM_UPSTR) ? " from_upstr" : "", (pb->flags & F_FROM_DOWNSTR) ? " from_downstr" : "" ); } */ /* specific tight loops */ if (pb->flags & F_DUPE) { /* Duplicate packet. Don't send, unless client especially wants! */ for (c = self->clients_dupe; (c); c = cnext) { cnext = c->class_next; // client_write() MAY destroy the client object! if (c->state == CSTATE_CONNECTED) send_single(self, c, pb); } /* Check if I have the client which sent this dupe, and * increment it's dupe counter */ /* OPTIMIZE: we walk through all clients for each dupe - how to find it quickly? */ for (c = self->clients; (c); c = c->next) { if (c == origin) { clientaccount_add(c, -1, 0, 0, 0, 0, 0, 1); break; } } return; } if (pb->flags & F_FROM_DOWNSTR) { /* client is from downstream, send to upstreams and peers */ for (c = self->clients_ups; (c); c = cnext) { cnext = c->class_next; // client_write() MAY destroy the client object! if ((c->state == CSTATE_CONNECTED || c->state == CSTATE_COREPEER) && c != origin) send_single(self, c, pb); } } /* packet came from anywhere and is not a dupe - let's go through the * clients who connected us */ for (c = self->clients_other; (c); c = cnext) { cnext = c->class_next; // client_write() MAY destroy the client object! /* Do not send to clients that are not logged in. */ if (c->state != CSTATE_CONNECTED) { //hlog(LOG_DEBUG, "%d/%s: not sending to client: not connected", c->fd, c->username); continue; } /* If not full feed, process filters to see if the packet should be sent. */ if (( (c->flags & CLFLAGS_FULLFEED) != CLFLAGS_FULLFEED) && filter_process(self, c, pb) < 1) { //hlog(LOG_DEBUG, "fd %d: Not fullfeed or not matching filter, not sending.", c->fd); continue; } /* Do not send packet back to the source client. This may reject a packet that came from a socket that got closed a few milliseconds ago and its client_t got recycled on a newly connected client, but if the new client is a long living one, all further packets will be accepted just fine. For packet history dumps this test shall be ignored! Very unlikely check, so check for this last. */ if (c == origin) { //hlog(LOG_DEBUG, "%d: not sending to client: originated from this socketsocket", c->fd); continue; } send_single(self, c, pb); } }
static void accept_process_udpsubmit(struct listen_t *l, char *buf, int len, char *remote_host) { int packet_len; char *login_string = NULL; char *packet = NULL; char *username = NULL; char validated; int e; //hlog(LOG_DEBUG, "got udp submit: %.*s", len, buf); packet_len = loginpost_split(buf, len, &login_string, &packet); if (packet_len == -1) { hlog(LOG_DEBUG, "UDP submit [%s]: No newline (LF) found in data", remote_host); return; } if (!login_string) { hlog(LOG_DEBUG, "UDP submit [%s]: No login string in data", remote_host); return; } if (!packet) { hlog(LOG_DEBUG, "UDP submit [%s]: No packet data found in data", remote_host); return; } hlog(LOG_DEBUG, "UDP submit [%s]: login string: %s", remote_host, login_string); hlog(LOG_DEBUG, "UDP submit [%s]: packet: %s", remote_host, packet); /* process the login string */ validated = http_udp_upload_login(remote_host, login_string, &username, "UDP submit"); if (validated < 0) { hlog(LOG_DEBUG, "UDP submit [%s]: Invalid login string", remote_host); return; } if (validated != 1) { hlog(LOG_DEBUG, "UDP submit [%s]: Invalid passcode for user %s", remote_host, username); return; } /* packet size limits */ if (packet_len < PACKETLEN_MIN) { hlog(LOG_DEBUG, "UDP submit [%s]: Packet too short: %d bytes", remote_host, packet_len); return; } if (packet_len > PACKETLEN_MAX-2) { hlog(LOG_DEBUG, "UDP submit [%s]: Packet too long: %d bytes", remote_host, packet_len); return; } udp_pseudoclient->portaccount = l->portaccount; e = pseudoclient_push_packet(udp_worker, udp_pseudoclient, username, packet, packet_len); clientaccount_add(udp_pseudoclient, IPPROTO_UDP, len, 1, 0, 0, (e < 0) ? e : 0, 0); udp_pseudoclient->portaccount = NULL; if (e < 0) hlog(LOG_DEBUG, "UDP submit [%s]: Incoming packet parse failure code %d: %s", remote_host, e, packet); else hlog(LOG_DEBUG, "UDP submit [%s]: Incoming packet parsed, code %d: %s", remote_host, e, packet); }