Beispiel #1
0
/**
 * \brief Verse server main function
 * \param	argc	The number of options and arguments.
 * \param	argv	The array of options and arguments.
 * \return Function returns 0, when it is ended successfully and non-zero
 * value, when there some error occurs. This function never reach the end,
 * because it is server.
 */
int main(int argc, char *argv[])
{
	VS_CTX vs_ctx;
	int opt;
	char *config_file=NULL;
	int debug_level_set = 0;
	void *res;

	/* Set up initial state */
	vs_ctx.state = SERVER_STATE_CONF;

	/* Default debug prints of verse server */
	v_init_print_log(VRS_PRINT_WARNING, stdout);

	/* When server received some arguments */
	if(argc>1) {
		while( (opt = getopt(argc, argv, "c:hd:")) != -1) {
			switch(opt) {
			case 'c':
				config_file = strdup(optarg);
				break;
			case 'd':
				debug_level_set = vs_set_debug_level(optarg);
				break;
			case 'h':
				vs_print_help(argv[0]);
				exit(EXIT_SUCCESS);
			case ':':
				exit(EXIT_FAILURE);
			case '?':
				exit(EXIT_FAILURE);
			}
		}
	}

	/* Initialize default values first */
	vs_init(&vs_ctx);

	/* Try to load Verse server configuration file */
	vs_load_config_file(&vs_ctx, config_file);

	/* When debug level wasn't specified as option at command line, then use
	 * configuration from file */
	if(debug_level_set == 1) {
		uint8 log_level = v_log_level();
		v_init_print_log(log_level, vs_ctx.log_file);
	} else {
		v_init_print_log(vs_ctx.print_log_level, vs_ctx.log_file);
	}

	/* Add superuser account to the list of users */
	vs_add_superuser_account(&vs_ctx);

	/* Add fake account for other users to the list of users*/
	vs_add_other_users_account(&vs_ctx);

	/* Load user accounts and save them in the linked list of verse server
	 * context */
	switch (vs_ctx.auth_type) {
		case AUTH_METHOD_CSV_FILE:
			if(vs_load_user_accounts(&vs_ctx) != 1) {
				v_print_log(VRS_PRINT_ERROR, "vs_load_user_accounts(): failed\n");
				vs_destroy_ctx(&vs_ctx);
				exit(EXIT_FAILURE);
			}
			break;
		case AUTH_METHOD_PAM:
			/* TODO: read list of supported usernames and their uids somehow */
			exit(EXIT_FAILURE);
		case AUTH_METHOD_LDAP:
			/* TODO: not implemented yet */
			exit(EXIT_FAILURE);
		default:
			/* Not supported method */
			v_print_log(VRS_PRINT_ERROR, "unsupported auth method: %d\n", vs_ctx.auth_type);
			vs_destroy_ctx(&vs_ctx);
			exit(EXIT_FAILURE);
	}

	/* Initialize data mutex */
	if( pthread_mutex_init(&vs_ctx.data.mutex, NULL) != 0) {
		v_print_log(VRS_PRINT_ERROR, "pthread_mutex_init(): failed\n");
		vs_destroy_ctx(&vs_ctx);
		exit(EXIT_FAILURE);
	}

	/* Create basic node structure of node tree */
	if(vs_nodes_init(&vs_ctx) == -1) {
		v_print_log(VRS_PRINT_ERROR, "vs_nodes_init(): failed\n");
		vs_destroy_ctx(&vs_ctx);
		exit(EXIT_FAILURE);
	}

	if(vs_ctx.stream_protocol == TCP) {
		/* Initialize Verse server context */
		if(vs_init_stream_ctx(&vs_ctx) == -1) {
			v_print_log(VRS_PRINT_ERROR, "vs_init_stream_ctx(): failed\n");
			vs_destroy_ctx(&vs_ctx);
			exit(EXIT_FAILURE);
		}
	} else {
		vs_destroy_ctx(&vs_ctx);
		exit(EXIT_FAILURE);
	}

	if(vs_ctx.flag & SERVER_DEBUG_MODE) {
		/* Set up signal handlers (only for debug mode, real server should ignore most of signals) */
		if(vs_config_signal_handling() == -1 ) {
			vs_destroy_ctx(&vs_ctx);
			exit(EXIT_FAILURE);
		}
	} else {
#if 0
		/* Make from verse server real verse application:
		 * - detach from standard file descriptors, terminals, PPID process etc. */
		if(vs_init_server(&vs_ctx) == -1) {
			vs_destroy_ctx(&vs_ctx);
			exit(EXIT_FAILURE);
		}
#endif
	}

	/* Initialize data semaphore */
	if( (vs_ctx.data.sem = sem_open(DATA_SEMAPHORE_NAME, O_CREAT, 0644, 1)) == SEM_FAILED) {
		v_print_log(VRS_PRINT_ERROR, "sem_init(): %s\n", strerror(errno));
		vs_destroy_ctx(&vs_ctx);
		exit(EXIT_FAILURE);
	}

	/* Try to create new data thread */
	if(pthread_create(&vs_ctx.data_thread, NULL, vs_data_loop, (void*)&vs_ctx) != 0) {
		v_print_log(VRS_PRINT_ERROR, "pthread_create(): %s\n", strerror(errno));
		vs_destroy_ctx(&vs_ctx);
		exit(EXIT_FAILURE);
	}

	/* Try to create cli thread */
	if(pthread_create(&vs_ctx.cli_thread, NULL, vs_server_cli, (void*)&vs_ctx) != 0) {
		v_print_log(VRS_PRINT_ERROR, "pthread_create(): %s\n", strerror(errno));
		vs_destroy_ctx(&vs_ctx);
		exit(EXIT_FAILURE);
	}

	/* Set up pointer to local server CTX -> server server could be terminated
	 * with signal now. */
	local_vs_ctx = &vs_ctx;

	vs_ctx.state = SERVER_STATE_READY;

	if(vs_ctx.stream_protocol == TCP) {
		if(vs_main_listen_loop(&vs_ctx) == -1) {
			v_print_log(VRS_PRINT_ERROR, "vs_main_listen_loop(): failed\n");
			vs_destroy_ctx(&vs_ctx);
			exit(EXIT_FAILURE);
		}
	} else {
		v_print_log(VRS_PRINT_ERROR, "unsupported stream protocol: %d\n", vs_ctx.stream_protocol);
		vs_destroy_ctx(&vs_ctx);
		exit(EXIT_FAILURE);
	}

	/* Free Verse server context */
	vs_destroy_ctx(&vs_ctx);

	/* Join cli thread */
	if(pthread_join(vs_ctx.cli_thread, &res) != 0) {
		v_print_log(VRS_PRINT_ERROR, "pthread_join(): %s\n", strerror(errno));
		exit(EXIT_FAILURE);
	} else {
		if(res != PTHREAD_CANCELED && res != NULL) free(res);
	}

	/* TODO: replace following ifdef */
#ifndef __APPLE__
	/* Join data thread */
	if(pthread_join(vs_ctx.data_thread, &res) != 0) {
		v_print_log(VRS_PRINT_ERROR, "pthread_join(): %s\n", strerror(errno));
		exit(EXIT_FAILURE);
	} else {
		if(res != PTHREAD_CANCELED && res != NULL) free(res);
	}

	/* Try to close named semaphore s*/
	if(sem_close(vs_ctx.data.sem) == -1) {
		v_print_log(VRS_PRINT_ERROR, "sem_close(): %s\n", strerror(errno));
	}
#endif

	/* Try to unlink named semphore */
	if(vs_ctx.data.sem != NULL && sem_unlink(DATA_SEMAPHORE_NAME) == -1) {
		v_print_log(VRS_PRINT_ERROR, "sem_unlink(): %s\n", strerror(errno));
	}

	return EXIT_SUCCESS;
}
Beispiel #2
0
int main (int   argc, char *argv[])
{
	int opt;
	int quiet = 0;

	/* Initialize the app_data structure */
	vc_init_data(&app_data);

	/* Parse command line */
	while ((opt = getopt(argc, argv, "dqs:h")) != -1) {
		switch (opt) {
		case 'd':
			/* Daemonize - do not open /dev/stdin */
			app_data.daemonize = 1;
			break;
		case 'q':
			/* Quiet - do not print startup messages */
			quiet = 1;
			break;
		case 's':
			/* Server IP address */
			strcpy(app_data.cfg.server_ip_addr, optarg);
			break;
		case 'h':
		default: /* '?' */
			vs_print_help();
			return 0;
		}
	}
	
	if(!strlen(app_data.cfg.server_ip_addr)){
		vs_print_help();
		return 0;
	}

	if(!quiet){
		printf("glivec - Gstreamer Live Example Client \n"
				"(C) John Weber, Avnet Electronics Marketing\n");
	}

	/* Initialize configuration data */
	app_data.cfg.rtp_recv_port  = DEFAULT_RX_RTP_PORT;
	app_data.cfg.rtcp_send_port = DEFAULT_TX_RTCP_PORT;
	app_data.cfg.rtcp_recv_port = DEFAULT_RX_RTCP_PORT;
	app_data.cfg.server_port    = DEFAULT_SERVER_PORT;

	printf( "Server IP address:           %s\n"
			"Server port:                 %d\n"
			"Sending RTP data on port:    %d\n"
			"Sending RTCP data on port:   %d\n"
			"Expecting RTCP data on port: %d\n",
			app_data.cfg.server_ip_addr,
			app_data.cfg.server_port,
			app_data.cfg.rtp_recv_port,
			app_data.cfg.rtcp_send_port,
			app_data.cfg.rtcp_recv_port);

	/* Setup the file descriptors for polling, starting with /dev/stdin */
	if(!app_data.daemonize){
		app_data.fds[FD_INDEX_STDIN].fd = open("/dev/stdin", O_RDONLY);
		if( app_data.fds[FD_INDEX_STDIN].fd == -1) {
			printf("Error opening /dev/stdin for reading\n");
			return -1;
		}
		app_data.fds[FD_INDEX_STDIN].events = POLLIN;
	}
	else {
		printf("glivec starting as background task.\n");
	}

	if(link_init_as_client((char*)app_data.cfg.server_ip_addr, app_data.cfg.server_port) < 0){
		debug_printf("%s: Failed to init link as client\n", __func__);
		return -1;
	}

	/* Initialization */
	gst_init (&argc, &argv);

	vc_sigint_setup();

	/* Main Loop */
	printf ("Running...\n");

	vc_mainloop(&app_data);

	/* Out of the main loop, clean up nicely */
	printf ("Returned, stopping playback\n");

	return vc_cleanup(&app_data);

}