Example #1
0
int  send_nack(rms_meta_channel *channel, rms_meta_peer *peer, rms_meta_msg* msg) {
	unsigned long *seq;
	void *data;
	int count;
	int itr;
	unsigned long seq2 = peer->sequence_sent-1;
	msg->hdr->type = RMS_NACK;
	msg->hdr->sequence = htonl(peer->sequence_rcvd);
	msg->hdr->id  = htonl(peer->id);

	count = 1;
	seq = (unsigned long*)msg->data;
	for(itr = peer->sequence_rcvd + 1; itr!=seq2; itr++) {
		if(!htbl_get(peer->ht_unseq_msgs, itr, &data)) {
			seq[count] = htonl(itr);
			count++;
			peer->lost++;
			rmsb->self->lost++;
		}
	}
	seq[0] = htonl(count);
	count = count*sizeof(unsigned long);
	msg->hdr->length = htons(count);
	rmsb->ucast_addr.sin_addr.s_addr = htonl(peer->id);
	return sendto(rmsb->mcast_sock,
			msg->buf,
			sizeof(rms_msg_hdr) + count,
			0,
			(struct sockaddr*) &rmsb->ucast_addr,
			sizeof(rmsb->mcast_addr));
}
Example #2
0
void *
http_option_get_val(struct http_ctx *c, http_opt_t o) {
	char *opt_id = NULL;
	void *opt = NULL;

	if(c == NULL) {
		libnet_error_set(LIBNET_E_INV_ARG);
		return NULL;
	}

	opt_id = http_option_get_id(o);
	opt = htbl_get(&c->options, opt_id);

	return opt;
}
Example #3
0
void* rms_manager(void* arg) {
	//init
	int 	nfound;
	int 	ret;
	int		err;
	int		itr;
	int		ipc_read;
	int		count;
	int 	gottime;
	char 	*data;
	float   t1;
	float   t2;
	fd_set	readset;
	struct 	timeval timeout;
	struct 	timeval ratechk;
	unsigned long 	*keys;
	unsigned long 	*seq;

	rms_meta_msg *msg;
	rms_meta_peer *peer;
	int		addr_len;
	rms_msg_hbeat *hbeat;

	rmscb *rmsb = (rmscb*)arg;

	gottime = 0;

	while(rmsb->active) {
		FD_ZERO(&readset);
		FD_SET(rmsb->ipc_sock, &readset);
		FD_SET(rmsb->mcast_sock, &readset);

		timeout.tv_sec	= 1;
		timeout.tv_usec = 0;

		nfound= select(rmsb->maxsock, &readset, (fd_set*)0, (fd_set*)0, &timeout);

		if(nfound > 0) {
			//available to read on mcast port
			if((nfound = FD_ISSET(rmsb->mcast_sock, &readset)) > 0) {
				msg = alloc_meta_msg();
				ret = recvfrom(rmsb->mcast_sock,
						&msg->buf,
						msg->size,
						0,
						(struct sockaddr*)&rmsb->recv_addr,
						&addr_len);
				printf("\n\tRMC: recvd %d bytes from %ld",
					ret,
					rmsb->recv_addr.sin_addr.s_addr);
				if(ret < sizeof(rms_msg_hdr)) {
					//not enough data
					continue;
				}
				msg->hdr->length = ntohs(msg->hdr->length);
				msg->hdr->sequence = ntohl(msg->hdr->sequence);
				msg->hdr->id  = ntohl(msg->hdr->id);
				if(ret < msg->hdr->length + sizeof(rms_msg_hdr)) {
					//not enough data
					continue;
				}
				switch(msg->hdr->type) {
				case RMS_DATA:
					if(!htbl_get(rmsb->ht_peers, msg->hdr->id, (void*)&peer)) {
						//peer not registered, drop packet
						release_meta_msg(msg);
					}
					else {
					peer->sequence_sent = msg->hdr->sequence;
					if(peer->sequence_rcvd + 1 != msg->hdr->sequence) {
						//gap in sequence num
						if(peer->sequence_rcvd < msg->hdr->sequence) {
							//cache msg
							htbl_put(peer->ht_unseq_msgs, msg->hdr->sequence, msg);

							//send NACK
							msg = alloc_meta_msg();
							send_nack(rmsb, peer, msg);
						}
						//else retransmitted data, drop packet
						release_meta_msg(msg);
					}
					else {
						//in sequence
						//syncqueue_signal_data(rmsb->inmsgq, msg);
						nfound = msg->hdr->length;
						ret = send(rmsb->ipc_sock, &nfound, sizeof(int),0);
						ret = 0;
						while(ret < nfound) {
							ret+=send(rmsb->ipc_sock, msg->data+ret, nfound-ret, 0);
						}
						peer->sequence_rcvd++;

						//release out of sequence data if any
						while(htbl_remove(peer->ht_unseq_msgs, peer->sequence_sent, (void*)&msg)) {
							//syncqueue_signal_data(rmsb->inmsgq, msg);
							nfound = msg->hdr->length;
							ret = send(rmsb->ipc_sock, &nfound, sizeof(int),0);
							ret = 0;
							while(ret < nfound) {
								ret+=send(rmsb->ipc_sock, msg->data+ret, nfound-ret, 0);
							}
							peer->sequence_rcvd++;
						}
					}}
					break;

				case RMS_HEARTBEAT:
					hbeat = (rms_msg_hbeat*) msg->data;
					data = msg->data + sizeof(rms_msg_hbeat);
					if(!htbl_get(rmsb->ht_peers, msg->hdr->id, (void*)&peer)) {
						//peer not registered, register it
						if(hbeat->namelen) {
							rms_meta_peer_init(&peer, msg->data, msg->hdr->id);
						}
						else {
							rms_meta_peer_init(&peer, "noname", msg->hdr->id);
						}

						htbl_put(rmsb->ht_peers, peer->id, peer);
						mqueue_add(rmsb->mq_peers, peer);
					}

					peer->lost = ntohs(hbeat->lost);
					//check for namelen
					if(hbeat->namelen) {
						hbeat->namelen = htonl(hbeat->namelen);
						data+=hbeat->namelen;
					}

					//check for acks
					if(hbeat->acks) {
						seq = (unsigned long*)data;
						hbeat->acks = ntohs(hbeat->acks);
						for(itr=0;itr < hbeat->acks; itr++) {
							if(ntohl(seq[itr*2])== rmsb->self->id) {
								peer->sequence_sync = ntohl(seq[itr*2 + 1]);
								break;
							}
						}
						data+=hbeat->acks*2*sizeof(long);
					}

					//check for piggybacked data
					if(hbeat->pgback) {
						hbeat->pgback = ntohs(hbeat->pgback);
					}

					gettimeofday(&timeout, NULL);
					gottime=1;
					peer->last_hbeat.tv_sec = timeout.tv_sec;
					peer->last_hbeat.tv_usec = timeout.tv_usec;
					if(peer->sequence_sent + 1 != msg->hdr->sequence) {
						//gap in sequence num
						if(peer->sequence_sent < msg->hdr->sequence) {
							//send NACK
							send_nack(rmsb, peer, msg);
						}
					}
					release_meta_msg(msg);
					break;

				case RMS_NACK:
					seq = (unsigned long*)msg->data;
					count = seq[0];
					rmsb->ucast_addr.sin_addr.s_addr = htonl(msg->hdr->id);
					for(itr=1; itr <= count; itr++) {
						seq[itr]=ntohl(seq[itr]);
						if(htbl_get(rmsb->outmsgbuf, seq[itr], (void*)&msg)) {
							ret = sendto(rmsb->mcast_sock,
									msg->buf,
									msg->length + sizeof(rms_msg_hdr),
									0,
									(struct sockaddr*) &rmsb->ucast_addr,
									sizeof(rmsb->ucast_addr));
						}
					}
					break;

				case RMS_LEAVE:
					if(htbl_remove(rmsb->ht_peers, msg->hdr->id, (void*)&peer)) {
						//clean up unseq msgs buffer
						count = htbl_count(peer->ht_unseq_msgs);
						keys = (unsigned long*)malloc(count*sizeof(unsigned long));
						memset(keys,0,count*sizeof(unsigned long));
						count = htbl_enum_keys(peer->ht_unseq_msgs, (void*)keys, count);
						for(itr = 0; itr < count; itr++) {
							if(htbl_remove(peer->ht_unseq_msgs, keys[itr], (void*)&msg)) {
								release_meta_msg(msg);
							}
						}
						free(keys);
						mqueue_remove_item(rmsb->mq_peers, peer);
						rms_meta_peer_free(peer);
					}
					break;

				case RMS_ACK:
				case RMS_JOIN:
				case RMS_CERT:
				default:
					//unimplemented options, drop packet
					release_meta_msg(msg);
					break;
				}
			}

			//available to read on ipc port
			if((nfound = FD_ISSET(rmsb->ipc_sock, &readset)) > 0) {
				err = 1;
				ret = recv(rmsb->ipc_sock,
						&ipc_read,
						sizeof(int),
						0);
				if(ret > 0) {
					//alloc buffer
					msg = alloc_meta_msg();
					if(ipc_read > rmsb->bufsize) {
						rmsb->bufsize =  ipc_read * 1.5;
						msg->size = rmsb->bufsize;
						msg->buf = realloc(msg->buf,msg->size);
						msg->hdr = (rms_msg_hdr*)msg->buf;
						msg->data = msg->buf + sizeof(rms_msg_hdr);
					}
					ret = recv(rmsb->ipc_sock,
							&msg->data,
							ipc_read,
							0);
					if(ret == ipc_read) {
						msg->length =  ipc_read;
						msg->hdr->type = RMS_DATA;
						msg->hdr->length = htons(msg->length);
						msg->hdr->sequence = htonl(rmsb->self->sequence_sent);
						msg->hdr->id  = htonl(rmsb->self->id);
						ret = sendto(rmsb->mcast_sock,
								msg->buf,
								ret + sizeof(rms_msg_hdr),
								0,
								(struct sockaddr*) &rmsb->mcast_addr,
								sizeof(rmsb->mcast_addr));
						if (ret > 0) {
							htbl_put(rmsb->outmsgbuf, rmsb->self->sequence_sent, msg);
							rmsb->self->sequence_sent++;
							rmsb->msg_this_sec++;
							err = 0;
						}
					}
				}
				if(err) {
					release_meta_msg(msg);
				}
			}
		}

		//do periodic things
		if(!gottime)
			gettimeofday(&timeout, NULL);
		gottime=0;

		//heartbeat
		if(timeout.tv_sec - rmsb->self->last_hbeat.tv_sec >= rmsb->hbeat_rate) {
			//time for hbeat
			send_hbeat(rmsb, NULL,0);

			//check msg send rate
			t1 = (float)timeout.tv_sec + ((float)timeout.tv_usec)/1000000;
			t2 = (float)rmsb->self->last_hbeat.tv_sec
				+ ((float)rmsb->self->last_hbeat.tv_usec)/1000000;

			rmsb->msg_per_sec = rmsb->msg_this_sec/(t1-t2);

			//calculate heartbeat rate
			rmsb->hbeat_rate  = RMS_RATE_FACTOR / rmsb->msg_per_sec;

			//clamp
			if(rmsb->hbeat_rate > 5)
				rmsb->hbeat_rate = 5;
			else if(rmsb->hbeat_rate < 1)
				rmsb->hbeat_rate = 1;

			rmsb->msg_this_sec = 0;

			rmsb->self->last_hbeat.tv_sec = timeout.tv_sec;
			rmsb->self->last_hbeat.tv_usec = timeout.tv_usec;
		}

		//if acks are used
		if(rmsb->hb_ack) {
			//clear buffers
			count = mqueue_size(rmsb->mq_peers);
			for(itr=0; itr < count; itr++) {
				peer = (rms_meta_peer*) mqueue_peek_at_index(rmsb->mq_peers, itr);
				if(peer->sequence_sync < rmsb->self->sequence_sync);
					rmsb->self->sequence_sync = peer->sequence_sync;
			}
			while(rmsb->oldest_seq < rmsb->self->sequence_sync){
				if(htbl_remove(rmsb->outmsgbuf, rmsb->oldest_seq, (void*)&msg)) {
					release_meta_msg(msg);
				}
				rmsb->oldest_seq++;
			}
		}
	}
	//send leave message
	msg = alloc_meta_msg();
	msg->hdr->type = RMS_LEAVE;
	msg->hdr->length = 0;
	msg->hdr->sequence = htonl(rmsb->self->sequence_sent);
	msg->hdr->id  = htonl(rmsb->self->id);
	ret = sendto(rmsb->mcast_sock,
			msg->buf,
			sizeof(rms_msg_hdr),
			0,
			(struct sockaddr*) &rmsb->mcast_addr,
			sizeof(rmsb->mcast_addr));
	release_meta_msg(msg);
	return 0;
}
Example #4
0
void
http_response_parse/*_and_read*/(struct http_ctx *c, http_response_t *r, buffer_t *d) {
	char buf[LIBNET_HTTP_SIZE_CHUNK] = {0}, *tok;
	uint32_t len, i = 0, chunk_size = 0;
	bool chunked = false;
	http_header_field_t *hf_e;

	if(c == NULL || r == NULL || d == NULL) {
		libnet_error_set(LIBNET_E_INV_ARG);
		return;
	}

	htbl_create(&r->header, 0);
	buffer_create(&r->body, LIBNET_BM_FILE);

	len = buffer_size(d);
	buffer_seek(d, 0);

	/* read status line */
	while(len > 0) {
		buffer_read(d, buf + i, 1);
		
		if(strstr(buf, LIBNET_HTTP_DEL)) {
			break;
		}

		++i; --len;
	}

	//printf("status line: %s", buf);

	/* do something with the http version */

	/* get status code */
	tok = strstr(buf, " ") + 1;
	sprintf(buf, "%s", tok);
	sscanf(buf, "%3d", &r->code);

	/* get reason */
	i = strcspn(buf+4, LIBNET_HTTP_DEL) + 1;

	if(i > LIBNET_HTTP_SIZE_REASON) {
		i -= LIBNET_HTTP_SIZE_REASON; // LIBNET_HTTP_DEL;
	}

	snprintf(r->reason, i, "%s", buf+4);

	/* now parse header */
	http_header_parse(&r->header, d);

	/* chunked? */
	hf_e = (http_header_field_t *)htbl_get(&r->header, "transfer-encoding");
	chunked = (!strcmp(hf_e->value, "chunked") ? true : false);

	uint32_t get_chunk_size(socket_t *s) {
		uint32_t i = 0, size;
		char buf[LIBNET_HTTP_SIZE_CHUNK] = {0};

		while(!strstr(buf, LIBNET_HTTP_DEL)) {
			if(0 == socket_read(s, buf+i++, 1)) {
				return 0;
			}
		}

		if(i >= 3) {
			buf[i-2] = 0;
		} else {
			return 0;
		}

		sscanf(buf, "%x", &size);
		return size;
	}