예제 #1
0
파일: outgoing.c 프로젝트: n8ohu/aprsc
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);
}
예제 #2
0
파일: outgoing.c 프로젝트: n8ohu/aprsc
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);
	}
}
예제 #3
0
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);
}