Пример #1
0
void snmp_process(void) {
    int nfds = 0;
    int block = 1;
    fd_set fdset;
    struct timeval timeout;

	if (snmp_repeaterinfo_received) {
		snmp_repeaterinfo_received = 0;
		if (snmp_session_repeaterinfo != NULL) {
			snmp_close(snmp_session_repeaterinfo);
			snmp_session_repeaterinfo = NULL;
		}
	}

	if (snmp_rssi_received) {
		snmp_rssi_received = 0;
		if (snmp_session_rssi != NULL) {
			snmp_close(snmp_session_rssi);
			snmp_session_rssi = NULL;
		}
	}

	FD_ZERO(&fdset);
	if (snmp_select_info(&nfds, &fdset, &timeout, &block) <= 0)
		return;
	// Timeout is handled by daemon-poll.
	daemon_poll_setmaxtimeout(timeout.tv_sec*1000+timeout.tv_usec/1000);
	// As timeout is handled by daemon-poll, we want select() to return immediately here.
	timeout.tv_sec = timeout.tv_usec = 0;
	nfds = select(nfds, &fdset, NULL, NULL, &timeout);
	if (nfds > 0)
		snmp_read(&fdset);
	else
		snmp_timeout();
}
Пример #2
0
void repeaters_add_to_ipsc_packet_buffer(repeater_t *repeater, dmr_timeslot_t ts, ipscpacket_raw_t *ipscpacket_raw, flag_t nowait) {
	ipscrawpacketbuf_t *newpbentry;
	ipscrawpacketbuf_t *pbentry;

	if (repeater == NULL || ipscpacket_raw == NULL)
		return;

	console_log(LOGLEVEL_REPEATERS LOGLEVEL_DEBUG "repeaters [%s]: adding entry to ts%u ipsc packet buffer\n", repeaters_get_display_string_for_ip(&repeater->ipaddr), ts+1);

	newpbentry = (ipscrawpacketbuf_t *)calloc(1, sizeof(ipscrawpacketbuf_t));
	if (newpbentry == NULL) {
		console_log(LOGLEVEL_REPEATERS "repeaters [%s] error: couldn't allocate memory for new ipsc packet buffer entry\n", repeaters_get_display_string_for_ip(&repeater->ipaddr));
		return;
	}

	memcpy(&newpbentry->ipscpacket_raw, ipscpacket_raw, sizeof(ipscpacket_raw_t));
	newpbentry->nowait = nowait;

	pbentry = repeater->slot[ts].ipsc_tx_rawpacketbuf;
	if (pbentry == NULL)
		repeater->slot[ts].ipsc_tx_rawpacketbuf = newpbentry;
	else {
		// Searching for the last element in the packet buffer.
		while (pbentry->next)
			pbentry = pbentry->next;
		pbentry->next = newpbentry;
	}

	daemon_poll_setmaxtimeout(0);
}
Пример #3
0
void data_packet_txbuf_add(flag_t broadcast_to_all_repeaters, repeater_t *repeater, dmr_timeslot_t ts, dmrpacket_data_packet_t *data_packet) {
	data_packet_txbuf_t *new_data_packet_txbuf_entry;

	if (data_packet == NULL)
		return;

	new_data_packet_txbuf_entry = (data_packet_txbuf_t *)calloc(1, sizeof(data_packet_txbuf_t));
	if (new_data_packet_txbuf_entry == NULL) {
		console_log("  error: can't allocate memory for new data packet tx buffer entry\n");
		return;
	}

	memcpy(&new_data_packet_txbuf_entry->data_packet, data_packet, sizeof(dmrpacket_data_packet_t));
	new_data_packet_txbuf_entry->added_at = time(NULL);
	new_data_packet_txbuf_entry->broadcast_to_all_repeaters = broadcast_to_all_repeaters;
	new_data_packet_txbuf_entry->repeater = repeater;
	new_data_packet_txbuf_entry->ts = ts;

	console_log(LOGLEVEL_DATAQ "data packet txbuf: adding new entry:\n");
	data_packet_txbuf_print_entry(new_data_packet_txbuf_entry);

	if (data_packet_txbuf_last_entry == NULL) {
		data_packet_txbuf_last_entry = data_packet_txbuf_first_entry = new_data_packet_txbuf_entry;
	} else {
		// Putting the new entry to the end of the linked list.
		data_packet_txbuf_last_entry->next = new_data_packet_txbuf_entry;
		data_packet_txbuf_last_entry = new_data_packet_txbuf_entry;
	}
	daemon_poll_setmaxtimeout(0);
}
Пример #4
0
static void repeaters_process_ipsc_tx_rawpacketbuf(repeater_t *repeater) {
	struct timeval currtime = {0,};
	struct timeval difftime = {0,};
	ipscrawpacketbuf_t *ipsc_tx_rawpacketbuf_entry_to_send;
	dmr_timeslot_t ts;
	flag_t nowait = 0;

	if (repeater == NULL)
		return;

	if (repeater->slot[0].ipsc_tx_rawpacketbuf != NULL || repeater->slot[1].ipsc_tx_rawpacketbuf != NULL)
		daemon_poll_setmaxtimeout(0);

	if (repeater->last_ipsc_packet_sent_from_slot == 1)
		ts = 0;
	else
		ts = 1;

	gettimeofday(&currtime, NULL);
	timersub(&currtime, &repeater->last_ipsc_packet_sent_time, &difftime);
	if (difftime.tv_sec*1000+difftime.tv_usec/1000 < IPSC_PACKET_SEND_INTERVAL_IN_MS)
		return;

	if (repeater->slot[ts].ipsc_tx_rawpacketbuf != NULL && repeater->slot[ts].ipsc_tx_rawpacketbuf->nowait)
		nowait = 1;

	if (nowait == 0)
		repeater->last_ipsc_packet_sent_from_slot = ts;

	if (repeater->slot[ts].ipsc_tx_rawpacketbuf == NULL) {
		gettimeofday(&repeater->last_ipsc_packet_sent_time, NULL);
		return;
	}

	if (repeaters_is_there_a_call_not_for_us_or_by_us(repeater, ts))
		return;

	ipsc_tx_rawpacketbuf_entry_to_send = repeater->slot[ts].ipsc_tx_rawpacketbuf;

	console_log(LOGLEVEL_REPEATERS "repeaters [%s]: sending ipsc packet from tx buffer\n", repeaters_get_display_string_for_ip(&repeater->ipaddr));
	if (repeaters_send_raw_ipsc_packet(repeater, &ipsc_tx_rawpacketbuf_entry_to_send->ipscpacket_raw)) {
		// Sending the packet to our IPSC processing loop too.
		//ipsc_processpacket(&ipsc_tx_rawpacketbuf_entry_to_send->ipscpacket_raw, sizeof(ipscpacket_raw_t));

		// Shifting the buffer.
		repeater->slot[ts].ipsc_tx_rawpacketbuf = repeater->slot[ts].ipsc_tx_rawpacketbuf->next;
		free(ipsc_tx_rawpacketbuf_entry_to_send);
	}
	if (nowait == 0)
		gettimeofday(&repeater->last_ipsc_packet_sent_time, NULL);
	if (repeater->slot[ts].ipsc_tx_rawpacketbuf == NULL)
		console_log(LOGLEVEL_REPEATERS "repeaters [%s]: tx packet buffer got empty\n", repeaters_get_display_string_for_ip(&repeater->ipaddr));
}
Пример #5
0
void data_packet_txbuf_process(void) {
	uint16_t timeout;

	if (data_packet_txbuf_first_entry == NULL)
		return;

	if (repeaters_is_there_a_call_not_for_us_or_by_us(data_packet_txbuf_first_entry->repeater, data_packet_txbuf_first_entry->ts))
		return;

	timeout = config_get_mindatapacketsendretryintervalinsec()+ceil(dmrpacket_data_get_time_in_ms_needed_to_send(&data_packet_txbuf_first_entry->data_packet)/1000.0);
	if (time(NULL)-data_packet_txbuf_last_send_try_at < timeout) {
		daemon_poll_setmaxtimeout(timeout-(time(NULL)-data_packet_txbuf_last_send_try_at));
		return;
	}

	if (data_packet_txbuf_first_entry->send_tries >= config_get_datapacketsendmaxretrycount()) {
		console_log(LOGLEVEL_DATAQ "data packet txbuf: all tries of sending the first entry has failed, removing:\n");
		data_packet_txbuf_print_entry(data_packet_txbuf_first_entry);
		data_packet_txbuf_remove_first_entry();
		if (data_packet_txbuf_first_entry == NULL)
			return;
	}

	data_packet_txbuf_first_entry->selective_ack_tries = 0;
	console_log(LOGLEVEL_DATAQ "data packet txbuf: sending entry:\n");
	data_packet_txbuf_print_entry(data_packet_txbuf_first_entry);

	if (data_packet_txbuf_first_entry->broadcast_to_all_repeaters)
		repeaters_send_broadcast_data_packet(&data_packet_txbuf_first_entry->data_packet);
	else
		repeaters_send_data_packet(data_packet_txbuf_first_entry->repeater, data_packet_txbuf_first_entry->ts, NULL, 0, &data_packet_txbuf_first_entry->data_packet);

	if (data_packet_txbuf_first_entry->data_packet.header.common.dst_is_a_group || // Group messages are unconfirmed, so we send them only once.
		!data_packet_txbuf_first_entry->data_packet.header.common.response_requested) {
			data_packet_txbuf_remove_first_entry();
	} else
		data_packet_txbuf_first_entry->send_tries++;
	data_packet_txbuf_reset_last_send_try_time();
	daemon_poll_setmaxtimeout(0);
}
Пример #6
0
void repeaters_process(void) {
	repeater_t *repeater = repeaters;
	repeater_t *repeater_to_remove;
	struct timeval currtime = {0,};
	struct timeval difftime = {0,};

	while (repeater) {
		if (repeater->slot[0].state != REPEATER_SLOT_STATE_IDLE || repeater->slot[1].state != REPEATER_SLOT_STATE_IDLE)
			daemon_poll_setmaxtimeout(IPSC_PACKET_SEND_INTERVAL_IN_MS);

		repeaters_process_ipsc_tx_rawpacketbuf(repeater);

		if (!comm_is_masteripaddr(&repeater->ipaddr) && time(NULL)-repeater->last_active_time > config_get_repeaterinactivetimeoutinsec()) {
			console_log(LOGLEVEL_REPEATERS "repeaters [%s]: timed out\n", repeaters_get_display_string_for_ip(&repeater->ipaddr));
			repeater_to_remove = repeater;
			repeater = repeater->next;
			repeaters_remove(repeater_to_remove);
			continue;
		}

		if (!repeater->snmpignored && config_get_repeaterinfoupdateinsec() > 0 && time(NULL)-repeater->last_repeaterinfo_request_time > config_get_repeaterinfoupdateinsec()) {
			console_log(LOGLEVEL_REPEATERS LOGLEVEL_DEBUG "repeaters [%s]: sending snmp info update request\n", repeaters_get_display_string_for_ip(&repeater->ipaddr));
			snmp_start_read_repeaterinfo(comm_get_ip_str(&repeater->ipaddr));
			repeater->last_repeaterinfo_request_time = time(NULL);
		}

		if (repeater->slot[0].state == REPEATER_SLOT_STATE_VOICE_CALL_RUNNING && time(NULL)-repeater->slot[0].last_call_or_data_packet_received_at > config_get_calltimeoutinsec())
			dmr_handle_voice_call_timeout(repeater, 0);

		if (repeater->slot[1].state == REPEATER_SLOT_STATE_VOICE_CALL_RUNNING && time(NULL)-repeater->slot[1].last_call_or_data_packet_received_at > config_get_calltimeoutinsec())
			dmr_handle_voice_call_timeout(repeater, 1);

		if (repeater->auto_rssi_update_enabled_at > 0 && repeater->auto_rssi_update_enabled_at <= time(NULL)) {
			if (config_get_rssiupdateduringcallinmsec() > 0) {
				gettimeofday(&currtime, NULL);
				timersub(&currtime, &repeater->last_rssi_request_time, &difftime);
				if (difftime.tv_sec*1000+difftime.tv_usec/1000 > config_get_rssiupdateduringcallinmsec()) {
					snmp_start_read_repeaterstatus(comm_get_ip_str(&repeater->ipaddr));
					repeater->last_rssi_request_time = currtime;
				}
			}
		}

		if (repeater->slot[0].state == REPEATER_SLOT_STATE_DATA_CALL_RUNNING && time(NULL)-repeater->slot[0].last_call_or_data_packet_received_at > config_get_datatimeoutinsec())
			dmr_handle_data_call_timeout(repeater, 0);

		if (repeater->slot[1].state == REPEATER_SLOT_STATE_DATA_CALL_RUNNING && time(NULL)-repeater->slot[1].last_call_or_data_packet_received_at > config_get_datatimeoutinsec())
			dmr_handle_data_call_timeout(repeater, 1);

		repeater = repeater->next;
	}
}
Пример #7
0
void data_packet_txbuf_remove_first_entry(void) {
	data_packet_txbuf_t *nextentry;

	if (data_packet_txbuf_first_entry == NULL)
		return;

	nextentry = data_packet_txbuf_first_entry->next;
	free(data_packet_txbuf_first_entry);
	data_packet_txbuf_first_entry = nextentry;
	if (data_packet_txbuf_first_entry == NULL)
		data_packet_txbuf_last_entry = NULL;
	else
		daemon_poll_setmaxtimeout(0);
}
Пример #8
0
void repeaters_send_data_packet(repeater_t *repeater, dmr_timeslot_t ts, flag_t *selective_blocks, uint8_t selective_blocks_size, dmrpacket_data_packet_t *data_packet) {
	uint16_t i;
	dmrpacket_csbk_t csbk;
	ipscpacket_payload_t *ipscpacket_payload;
	dmrpacket_data_block_t *data_blocks;
	uint8_t data_blocks_needed = 0;

	if (repeater == NULL || data_packet == NULL)
		return;

	repeater->slot[ts].ipsc_tx_seqnum = 0;

	console_log(LOGLEVEL_REPEATERS LOGLEVEL_DMRDATA "repeaters [%s]: sending %s sap: %s dpf: %s to %u on ts%u\n", repeaters_get_display_string_for_ip(&repeater->ipaddr),
		dmr_get_readable_call_type(data_packet->header.common.dst_is_a_group ? DMR_CALL_TYPE_GROUP : DMR_CALL_TYPE_PRIVATE),
		dmrpacket_data_header_get_readable_sap(data_packet->header.common.service_access_point),
		dmrpacket_data_header_get_readable_dpf(data_packet->header.common.data_packet_format),
		data_packet->header.common.dst_llid, ts+1);

	// If which blocks to send is set. Used for selective ACK reply.
	if (selective_blocks != NULL && selective_blocks_size > 0) {
		console_log(LOGLEVEL_REPEATERS LOGLEVEL_DMRDATA "  sending only selective blocks: ");
		for (i = 0; i < selective_blocks_size; i++) {
			if (selective_blocks[i]) {
				console_log(LOGLEVEL_REPEATERS LOGLEVEL_DMRDATA "%u ", i);
				data_blocks_needed++;
			}
		}
		console_log(LOGLEVEL_REPEATERS LOGLEVEL_DMRDATA "\n");
	} else {
		data_blocks_needed = data_packet->fragment.data_blocks_needed;
		console_log(LOGLEVEL_REPEATERS LOGLEVEL_DMRDATA "  sending full message (all %u blocks)\n", data_blocks_needed);
	}

	data_blocks = dmrpacket_data_construct_data_blocks(&data_packet->fragment, data_packet->data_type, data_packet->header.common.response_requested);
	if (data_blocks == NULL)
		return;

	// Filling up missing fields from the header.
	switch (data_packet->header.common.data_packet_format) {
		case DMRPACKET_DATA_HEADER_DPF_UDT:
			data_packet->header.udt.appended_blocks = data_blocks_needed;
			break;
		case DMRPACKET_DATA_HEADER_DPF_RESPONSE:
			data_packet->header.response.blocks_to_follow = data_blocks_needed;
			break;
		case DMRPACKET_DATA_HEADER_DPF_UNCONFIRMED_DATA:
			data_packet->header.unconfirmed_data.pad_octet_count = data_blocks_needed*dmrpacket_data_get_block_size(data_packet->data_type, data_packet->header.common.response_requested)-data_packet->fragment.bytes_stored-4;
			data_packet->header.unconfirmed_data.blocks_to_follow = data_blocks_needed;
			data_packet->header.unconfirmed_data.full_message = (selective_blocks == NULL && selective_blocks_size == 0);
			break;
		case DMRPACKET_DATA_HEADER_DPF_CONFIRMED_DATA:
			data_packet->header.confirmed_data.pad_octet_count = data_blocks_needed*dmrpacket_data_get_block_size(data_packet->data_type, data_packet->header.common.response_requested)-data_packet->fragment.bytes_stored-4;
			data_packet->header.confirmed_data.blocks_to_follow = data_blocks_needed;
			data_packet->header.confirmed_data.full_message = (selective_blocks == NULL && selective_blocks_size == 0);
			break;
		case DMRPACKET_DATA_HEADER_DPF_SHORT_DATA_DEFINED:
			data_packet->header.short_data_defined.appended_blocks = data_blocks_needed;
			data_packet->header.short_data_defined.full_message = (selective_blocks == NULL && selective_blocks_size == 0);
			break;
		case DMRPACKET_DATA_HEADER_DPF_SHORT_DATA_RAW:
			data_packet->header.short_data_raw.appended_blocks = data_blocks_needed;
			data_packet->header.short_data_raw.full_message = (selective_blocks == NULL && selective_blocks_size == 0);
			break;
		default:
			break;
	}

	// Constructing the CSBK preamble.
	csbk.last_block = 1;
	csbk.csbko = DMRPACKET_CSBKO_PREAMBLE;
	csbk.data.preamble.data_follows = 1;
	csbk.data.preamble.dst_is_group = data_packet->header.common.dst_is_a_group;
	csbk.data.preamble.csbk_blocks_to_follow = data_packet->number_of_csbk_preambles_to_send+data_blocks_needed+1; // +1 - header
	csbk.dst_id = data_packet->header.common.dst_llid;
	csbk.src_id = data_packet->header.common.src_llid;

	// Sending CSBK preambles.
	for (i = 0; i < data_packet->number_of_csbk_preambles_to_send; i++) {
		console_log(LOGLEVEL_REPEATERS LOGLEVEL_DMRDATA LOGLEVEL_DEBUG "  sending csbk #%u/%u\n", i, data_packet->number_of_csbk_preambles_to_send);
		csbk.data.preamble.csbk_blocks_to_follow--;
		ipscpacket_payload = ipscpacket_construct_payload_csbk(&csbk);
		repeaters_add_to_ipsc_packet_buffer(repeater, ts, ipscpacket_construct_raw_packet(&repeater->ipaddr, ipscpacket_construct_raw_payload(repeater->slot[ts].ipsc_tx_seqnum++, ts, IPSCPACKET_SLOT_TYPE_CSBK,
			(data_packet->header.common.dst_is_a_group ? DMR_CALL_TYPE_GROUP : DMR_CALL_TYPE_PRIVATE), data_packet->header.common.dst_llid, data_packet->header.common.src_llid, ipscpacket_payload)), 0);
	}

	repeaters_send_ipsc_sync(repeater, ts, (data_packet->header.common.dst_is_a_group ? DMR_CALL_TYPE_GROUP : DMR_CALL_TYPE_PRIVATE), data_packet->header.common.dst_llid, data_packet->header.common.src_llid);

	// Sending data header.
	console_log(LOGLEVEL_REPEATERS LOGLEVEL_DMRDATA LOGLEVEL_DEBUG "  sending data header\n");
	ipscpacket_payload = ipscpacket_construct_payload_data_header(&data_packet->header);
	repeaters_add_to_ipsc_packet_buffer(repeater, ts, ipscpacket_construct_raw_packet(&repeater->ipaddr, ipscpacket_construct_raw_payload(repeater->slot[ts].ipsc_tx_seqnum++, ts, IPSCPACKET_SLOT_TYPE_DATA_HEADER,
		(data_packet->header.common.dst_is_a_group ? DMR_CALL_TYPE_GROUP : DMR_CALL_TYPE_PRIVATE), data_packet->header.common.dst_llid, data_packet->header.common.src_llid, ipscpacket_payload)), 0);

	// Sending data blocks.
	for (i = 0; i < data_packet->fragment.data_blocks_needed; i++) { // Note: iterating through all blocks.
		// Sending this block if no selective blocks given, or they are given and this block is in the list
		// of blocks need to be sent.
		if (selective_blocks == NULL || (selective_blocks != NULL && i < selective_blocks_size && selective_blocks[i])) {
			console_log(LOGLEVEL_REPEATERS LOGLEVEL_DMRDATA LOGLEVEL_DEBUG "  sending block #%u\n", i);
			switch (data_packet->data_type) {
				default:
				case DMRPACKET_DATA_TYPE_RATE_34_DATA: ipscpacket_payload = ipscpacket_construct_payload_data_block_rate_34(&data_blocks[i]); break;
				case DMRPACKET_DATA_TYPE_RATE_12_DATA: ipscpacket_payload = ipscpacket_construct_payload_data_block_rate_12(&data_blocks[i]); break;
			}
			repeaters_add_to_ipsc_packet_buffer(repeater, ts, ipscpacket_construct_raw_packet(&repeater->ipaddr, ipscpacket_construct_raw_payload(repeater->slot[ts].ipsc_tx_seqnum++, ts,
				ipscpacket_get_slot_type_for_data_type(data_packet->data_type), (data_packet->header.common.dst_is_a_group ? DMR_CALL_TYPE_GROUP : DMR_CALL_TYPE_PRIVATE), data_packet->header.common.dst_llid, data_packet->header.common.src_llid,
				ipscpacket_payload)), 0);
		}
	}

	free(data_blocks);
	daemon_poll_setmaxtimeout(0);
}