Example #1
0
int main(int argc, char **argv) {
	ssize_t readen;
	int have_data = 1;
	int ntimeouts = 0;
	time_t timeout_start = time(NULL);
	int rtp_hdr_pos = 0, num_packets = 0;
	struct rlimit rl;

	if (getrlimit(RLIMIT_STACK, &rl) == 0) {
		if (rl.rlim_cur > THREAD_STACK_SIZE) {
			rl.rlim_cur = THREAD_STACK_SIZE;
			setrlimit(RLIMIT_STACK, &rl);
		}
	}

	memset(rtp_hdr[0], 0, RTP_HDR_SZ);
	memset(rtp_hdr[1], 0, RTP_HDR_SZ);

	data_init(&ts);

	ts_set_log_func(LOG_func);

	parse_options(&ts, argc, argv);

	if (ts.pidfile)
		daemonize(ts.pidfile);

	if (ts.syslog_active) {
		if (ts.syslog_remote) {
			log_init(ts.ident, 1, 1, ts.syslog_host, ts.syslog_port);
			remote_syslog = 1;
		} else {
			openlog(ts.ident, LOG_NDELAY | LOG_PID, LOG_USER);
			local_syslog = 1;
		}
	}

	ts.notify = notify_alloc(&ts);

	ts_LOGf("Start %s\n", program_id);
	notify(&ts, "START", "Starting %s", program_id);

	if (ts.input.type == NET_IO && udp_connect_input(&ts.input) < 1)
		goto EXIT;
	if (ts.output.type == NET_IO && udp_connect_output(&ts.output) < 1)
		goto EXIT;

	signal(SIGCHLD, SIG_IGN);
	signal(SIGPIPE, SIG_IGN);

	signal(SIGINT , signal_quit);
	signal(SIGTERM, signal_quit);

	if (ts.threaded) {
		pthread_create(&ts.decode_thread, &ts.thread_attr, &decode_thread, &ts);
		pthread_create(&ts.write_thread , &ts.thread_attr, &write_thread , &ts);
	}

	ts.emm_last_report = time(NULL) + FIRST_REPORT_SEC;
	ts.ecm_last_report = time(NULL) + FIRST_REPORT_SEC;
	camd_start(&ts);

	if (packet_from_file) {
		uint8_t tmp[2048];
		ts_hex_dump_buf((char *)tmp, sizeof(tmp), packet_buf, packet_buflen, 16);
		ts_LOGf("%s | Processing packet with CAID 0x%04x\n", packet_type == ECM_MSG ? "ECM" : "EMM", ts.forced_caid);
		ts_LOGf("%s | Packet dump:\n%s\n", packet_type == ECM_MSG ? "ECM" : "EMM", tmp);
		camd_process_packet(&ts, camd_msg_alloc(packet_type, ts.forced_caid, ts.forced_service_id, packet_buf, packet_buflen));
		goto EXIT;
	}

	do {
		if (!ts.camd.constant_codeword)
			do_reports(&ts);

		if (ts.input.type == NET_IO) {
			set_log_io_errors(0);
			if (!ts.rtp_input) {
				readen = fdread_ex(ts.input.fd, (char *)ts_packet, FRAME_SIZE, 250, 4, 1);
			} else {
				readen = fdread_ex(ts.input.fd, (char *)ts_packet, FRAME_SIZE + RTP_HDR_SZ, 250, 4, 1);
				if (readen > RTP_HDR_SZ) {
					memcpy(rtp_hdr[rtp_hdr_pos], ts_packet, RTP_HDR_SZ);
					memmove(ts_packet, ts_packet + RTP_HDR_SZ, FRAME_SIZE);
					readen -= RTP_HDR_SZ;
					uint16_t ssrc  = (rtp_hdr[rtp_hdr_pos][2] << 8) | rtp_hdr[rtp_hdr_pos][3];
					uint16_t pssrc = (rtp_hdr[!rtp_hdr_pos][2] << 8) | rtp_hdr[!rtp_hdr_pos][3];
					rtp_hdr_pos = !rtp_hdr_pos;
					if (pssrc + 1 != ssrc && (ssrc != 0 && pssrc != 0xffff) && num_packets > 2)
						if (ts.ts_discont)
							ts_LOGf("--- | RTP discontinuity last_ssrc %5d, curr_ssrc %5d, lost %d packet\n",
								pssrc, ssrc, ((ssrc - pssrc)-1) & 0xffff);
					num_packets++;
				}
			}
			set_log_io_errors(1);
			if (!keep_running)
				break;
			if (readen < 0) {
				ts_LOGf("--- | Input read timeout.\n");
				if (!ntimeouts) {
					timeout_start = time(NULL);
					notify(&ts, "INPUT_TIMEOUT", "Read timeout on input %s://%s:%s/",
							ts.rtp_input ? "rtp" : "udp",
							ts.input.hostname, ts.input.service);
				}
				ts.no_input = 1;
				ntimeouts++;
			} else {
				if (ntimeouts && readen > 0) {
					time_t now = time(NULL);
					ts_LOGf("+++ | Input OK after %ld sec timeout.\n", (now - timeout_start) + 2);
					notify(&ts, "INPUT_OK", "Data is available on input %s://%s:%s/ after %ld seconds timeout.",
							ts.rtp_input ? "rtp" : "udp",
							ts.input.hostname, ts.input.service,
							(now - timeout_start) + 2); // Timeout is detected when ~2 seconds there is no incoming data
					ts.no_input = 0;
					ntimeouts = 0;
				}
			}
		} else {
			readen = read(ts.input.fd, ts_packet, FRAME_SIZE);
			have_data = !(readen <= 0);
		}
		if (readen > 0) {
			if (ts.input_dump_file)
				fwrite(ts_packet, readen, 1, ts.input_dump_file);
			process_packets(&ts, ts_packet, readen);
		}
	} while (have_data && keep_running);
EXIT:
	camd_stop(&ts);

	// If pthread_join failes make sure we exit...
	signal(SIGINT , SIG_DFL);
	signal(SIGTERM, SIG_DFL);
	signal(SIGALRM, signal_alarm);
	alarm(2);
	if (ts.threaded) {
		ts.decode_stop = 1;
		ts.write_stop = 1;

		if (ts.decode_thread)
			pthread_join(ts.decode_thread, NULL);
		if (ts.write_thread)
			pthread_join(ts.write_thread, NULL);
	}

	show_pid_report(&ts);

	notify_sync(&ts, "STOP", "Stopping %s", program_id);
	ts_LOGf("Stop %s\n", program_id);

	if (ts.syslog_active) {
		if (ts.syslog_remote)
			log_close();
		else
			closelog();
	}

	if (ts.input_dump_file)
		fclose(ts.input_dump_file);

	if (ts.pidfile)
		unlink(ts.pidfile);

	if (log_file)
		fclose(log_file);

	notify_free(&ts.notify);
	data_free(&ts);

	exit(EXIT_SUCCESS);
}
Example #2
0
int main(int argc, char **argv) {
	struct videohub_data *data = &maindata;

	parse_options(data, argc, argv);
	set_log_io_errors(0);

	if (!test_data) {
		data->dev_fd = connect_client(SOCK_STREAM, data->dev_host, data->dev_port);
		if (data->dev_fd < 0)
			exit(EXIT_FAILURE);
	}

	reset_routed_to(&data->inputs);
	reset_routed_to(&data->outputs);
	reset_routed_to(&data->serial);
	reset_routed_to(&data->proc_units);
	reset_routed_to(&data->frames);
	read_device_command_stream(data);

	if (test_data)
		parse_text_buffer(data, test_data);

	if (!strlen(data->device.protocol_ver) || !strlen(data->device.model_name))
		die("The device does not respond correctly. Is it Videohub?");

	if (strstr(data->device.protocol_ver, "2.") != data->device.protocol_ver)
		q("WARNING: Device protocol is %s but this program is tested with 2.x only.\n",
			data->device.protocol_ver);

	if (!data->device.dev_present) {
		if (data->device.needs_fw_update) {
			die("Device reports that it needs firmware update.");
		}
		die("Device reports that it is not present.");
	}

	check_number_of_ports(&data->inputs);
	check_number_of_ports(&data->outputs);
	check_number_of_ports(&data->mon_outputs);
	check_number_of_ports(&data->serial);
	check_number_of_ports(&data->proc_units);
	check_number_of_ports(&data->frames);

	if (num_parsed_cmds) {
		unsigned int i;
		for (i = 0; i < ARRAY_SIZE(parsed_cmds.entry); i++) {
			struct vcmd_entry *ve = &parsed_cmds.entry[i];
			if (!ve->p1.param)
				continue;
			prepare_cmd_entry(data, &parsed_cmds.entry[i]);
		}

		for (i = 0; i < ARRAY_SIZE(parsed_cmds.entry); i++) {
			char cmd_buffer[1024];
			struct vcmd_entry *ve = &parsed_cmds.entry[i];
			if (!ve->p1.param)
				continue;
			format_cmd_text(ve, cmd_buffer, sizeof(cmd_buffer));
			if (strlen(cmd_buffer)) {
				show_cmd(data, ve);
				send_device_command(data, cmd_buffer);
				read_device_command_stream(data);
			}
		}
		// Show the result after commands
		if (test_data)
			print_device_full(data);
	} else if (show_monitor) {
		while (1) {
			int sleeps = 0;
			printf("\e[2J\e[H"); // Clear screen
			time_t now = time(NULL);
			struct tm *tm = localtime(&now);
			printf("Last update: %s\n", asctime(tm));
			print_device_info(data);
			print_device_video_inputs(data);
			print_device_video_outputs(data);
			fflush(stdout);
			do {
				usleep(500000);
				if (++sleeps >= 20)
					send_device_command(data, "PING:\n\n");
			} while (read_device_command_stream(data) == 0);
		}
	} else if (show_list) {