Пример #1
0
int send_sync_message(Router *router, Message *m)
{
    int ret=0;
    /* sync_message_status is a pointer to a location allocated on heap
        because, we have separate identity of its 'status' per sync message.
        This is necessary because, internal data structures (such as messageq)
        makes copies of messages. Therefore, we don't loose the identity of 
        status because pointer is also copied. 
    */
    m->sync_message_status=malloc(sizeof(SyncMessageStatus));
    assert(m->sync_message_status);
    *m->sync_message_status=NOT_PROCESSED;
    
    ret=mqueue_add(&router->mqueue, m)? 0 /* SUCCESS */ : 1 /* ERROR */;
    
    if(0 == ret)
    {
        if (pthread_self() == dispatch_thread)
            dispatch(router);  
        else
        {
            // Wait till SYNC message m is yet to be processed by dispatch thread
            while (NOT_PROCESSED == *m->sync_message_status)
                sched_yield();
        }    
        free(m->sync_message_status); // SYNC message m processed 
    }
    return ret;
}
Пример #2
0
/**
 * Function to get the ETA of a specific preset from the phone.
 * @param preset Specific preset that will be sent to the phone.
 */
void send_eta_req(Preset *preset){
	if (preset->eta == PRESET_SENT_REQUEST)
		return;
	preset->eta = PRESET_SENT_REQUEST;
	char* data = malloc(21);
	snprintf(data, 21, "%s|%s", preset->stop_id, preset->route_id);
	mqueue_add("PRESET", "PRESET_ETA", data);
	free(data);
}
Пример #3
0
int send_message(Router *router, Message *m)
{
    int ret=0;
    assert(router && m);

    if(REQUEST == m->type)
    {
        GLIST(InputInterface) * iface_list;
        pthread_mutex_lock(&router->bindings_mutex);    
        iface_list=&(router->comm_bindings[m->senderid].pattern_bindings[m->pattern_id]);
        if (Glist_empty(iface_list))
        {
            /* There is no tool to honor this request so I do not accept this reqeust */
            ret=1; /* ERROR */
        }
        else
        {
            RequestTool rt;
            rt.toolid=m->senderid;
            rt.reqrepid=m->reqrepid;
            Glist_add(&router->request_tool_list, &rt, sizeof(RequestTool),
                      (void *)requesttool_copyfunc);
            ret=0;
        }        
        pthread_mutex_unlock(&router->bindings_mutex);
    }
    
    if(0 == ret)
    {    
        if (SYNC_MODE == m->mode)
            ret=send_sync_message(router, m);
        else
            ret=mqueue_add(&router->mqueue, m)? 0 /* SUCCESS */ : 1 /* ERROR */;
    }
    return ret;
}
Пример #4
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;
}
Пример #5
0
void release_meta_msg(rmscb *rmsb, rms_meta_msg *msg) {
	mqueue_add(rmsb->sq_meta_msg_pool, msg);
}
Пример #6
0
/**
 * Function to ask the phone for the ETAs of every preset.
 */
void send_all_eta_req(){
	for (int i = 0; i < presets_get_count(); i++){
		presets_get(i)->eta = PRESET_SENT_REQUEST;
	}
	mqueue_add("PRESET","PRESET_ETA", " ");
}
Пример #7
0
/**
 * Clears all the presets in localStorage on the phone. This is used when the user clears
 * all presets from inside the app, so that the phone doesn't remember the saved presets the
 * next time the user goes to the Settings page.
 */
void presets_clear_from_phone(){
	mqueue_add("PRESET", "PRESET_CLEAR", " ");
}
Пример #8
0
/**
 * Function to restore the presets from the localStorage on the phone.
 * Only is used when persistent storage is broken, as loading the presets
 * from the phone is much slower and battery draining than persistent storage.
 */
void presets_restore_from_phone(){
	mqueue_add("PRESET", "PRESET_RESTORE"," ");
}
Пример #9
0
void analytics_track_event(char* name, char* data) {
  mqueue_add("ANALYTICS", name, data);
}
Пример #10
0
void tube_fetch_details(TubeLine* line) {
  mqueue_add("TUBE", "DETAILS", line->name);
}
Пример #11
0
void tube_update_lines(void) {
  mqueue_add("TUBE", "UPDATE", " ");
}