Beispiel #1
0
/** @brief Send a basic text file containig the playlist
 *
 * @param number_of_channels the number of channels
 * @param channels the channels array
 * @param Socket the socket on wich the information have to be sent
 * @param perport says if the channel have to be given by the url /bysid or by their port
 */
int
unicast_send_play_list_unicast (int number_of_channels, mumudvb_channel_t *channels, int Socket, int unicast_portOut, int perport)
{
	int curr_channel,iRet;

	struct unicast_reply* reply = unicast_reply_init();
	if (NULL == reply) {
		log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n");
		return -1;
	}

	//We get the ip address on which the client is connected
	struct sockaddr_in tempSocketAddr;
	unsigned int l;
	l = sizeof(struct sockaddr);
	iRet=getsockname(Socket, (struct sockaddr *) &tempSocketAddr, &l);
	if (iRet < 0)
	{
		log_message( log_module,  MSG_ERROR,"getsockname failed : %s while making HTTP reply", strerror(errno));
		unicast_reply_free(reply);
		return -1;
	}
	//we write the playlist
	unicast_reply_write(reply, "#EXTM3U\r\n");

	//"#EXTINF:0,title\r\nURL"
	for (curr_channel = 0; curr_channel < number_of_channels; curr_channel++)
		if (channels[curr_channel].streamed_channel)
		{
			if(!perport)
			{
				unicast_reply_write(reply, "#EXTINF:0,%s\r\nhttp://%s:%d/bysid/%d\r\n",
						channels[curr_channel].name,
						inet_ntoa(tempSocketAddr.sin_addr) ,
						unicast_portOut ,
						channels[curr_channel].service_id);
			}
			else if(channels[curr_channel].unicast_port)
			{
				unicast_reply_write(reply, "#EXTINF:0,%s\r\nhttp://%s:%d/\r\n",
						channels[curr_channel].name,
						inet_ntoa(tempSocketAddr.sin_addr) ,
						channels[curr_channel].unicast_port);
			}
		}

	unicast_reply_send(reply, Socket, 200, "audio/x-mpegurl");

	if (0 != unicast_reply_free(reply)) {
		log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n");
		return -1;
	}

	return 0;
}
Beispiel #2
0
/** @brief Send a basic JSON file containig the channel traffic
 *
 * @param number_of_channels the number of channels
 * @param channels the channels array
 * @param Socket the socket on wich the information have to be sent
 */
int
unicast_send_channel_traffic_js (int number_of_channels, mumudvb_channel_t *channels, int Socket)
{
	int curr_channel;
	extern long real_start_time;

	struct unicast_reply* reply = unicast_reply_init();
	if (NULL == reply) {
		log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n");
		return -1;
	}

	if ((time((time_t*)0L) - real_start_time) >= 10) //10 seconds for the traffic calculation to be done
	{
		unicast_reply_write(reply, "[");
		for (curr_channel = 0; curr_channel < number_of_channels; curr_channel++)
			unicast_reply_write(reply, "{\"number\":%d, \"name\":\"%s\", \"traffic\":%.2f},\n", curr_channel+1, channels[curr_channel].name, channels[curr_channel].traffic);
		reply->used_body -= 2; // dirty hack to erase the last comma
		unicast_reply_write(reply, "]\n");
	}

	unicast_reply_send(reply, Socket, 200, "application/json");

	if (0 != unicast_reply_free(reply)) {
		log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n");
		return -1;
	}
	return 0;
}
Beispiel #3
0
/** @brief Send a basic text file containig the playlist
 *
 * @param number_of_channels the number of channels
 * @param channels the channels array
 * @param Socket the socket on wich the information have to be sent
 */
int
unicast_send_play_list_multicast (int number_of_channels, mumudvb_channel_t *channels, int Socket, int vlc)
{
	int curr_channel;
	char urlheader[4];
	char vlcchar[2];
	extern multi_p_t multi_p;

	struct unicast_reply* reply = unicast_reply_init();
	if (NULL == reply) {
		log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n");
		return -1;
	}

	unicast_reply_write(reply, "#EXTM3U\r\n");

	if(vlc)
		strcpy(vlcchar,"@");
	else
		vlcchar[0]='\0';

	if(multi_p.rtp_header)
		strcpy(urlheader,"rtp");
	else
		strcpy(urlheader,"udp");

	//"#EXTINF:0,title\r\nURL"
	for (curr_channel = 0; curr_channel < number_of_channels; curr_channel++)
		if (channels[curr_channel].streamed_channel)
		{
			unicast_reply_write(reply, "#EXTINF:0,%s\r\n%s://%s%s:%d\r\n",
					channels[curr_channel].name,
					urlheader,
					vlcchar,
					channels[curr_channel].ip4Out,
					channels[curr_channel].portOut);
		}

	unicast_reply_send(reply, Socket, 200, "audio/x-mpegurl");

	if (0 != unicast_reply_free(reply)) {
		log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n");
		return -1;
	}

	return 0;
}
Beispiel #4
0
/** @brief Send a basic JSON file containig the reception power
 *
 * @param Socket the socket on wich the information have to be sent
 */
int
unicast_send_signal_power_js (int Socket, strength_parameters_t *strengthparams)
{
	struct unicast_reply* reply = unicast_reply_init();
	if (NULL == reply)
	{
		log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n");
		return -1;
	}

	unicast_reply_write(reply, "{\"ber\":%d, \"strength\":%d, \"snr\":%d, \"ub\":%d}\n", strengthparams->ber,strengthparams->strength,strengthparams->snr,strengthparams->ub);

	unicast_reply_send(reply, Socket, 200, "application/json");

	if (0 != unicast_reply_free(reply)) {
		log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n");
		return -1;
	}
	return 0;
}
Beispiel #5
0
/** @brief Send a basic html file containing the list of streamed channels
 *
 * @param number_of_channels the number of channels
 * @param channels the channels array
 * @param Socket the socket on wich the information have to be sent
 * @param host The server ip address/name (got in the HTTP GET request)
 */
int
unicast_send_streamed_channels_list (int number_of_channels, mumudvb_channel_t *channels, int Socket, char *host)
{

	struct unicast_reply* reply = unicast_reply_init();
	if (NULL == reply) {
		log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n");
		return -1;
	}

	unicast_reply_write(reply, HTTP_CHANNELS_REPLY_START);

	for (int curr_channel = 0; curr_channel < number_of_channels; curr_channel++)
		if (channels[curr_channel].streamed_channel)
		{
			if(host)
				unicast_reply_write(reply, "Channel number %d : %s<br>Unicast link : <a href=\"http://%s/bysid/%d\">http://%s/bysid/%d</a><br>Multicast ip : %s:%d<br><br>\r\n",
						curr_channel+1,
						channels[curr_channel].name,
						host,channels[curr_channel].service_id,
						host,channels[curr_channel].service_id,
						channels[curr_channel].ip4Out,channels[curr_channel].portOut);
			else
				unicast_reply_write(reply, "Channel number %d : \"%s\"<br>Multicast ip : %s:%d<br><br>\r\n",curr_channel+1,channels[curr_channel].name,channels[curr_channel].ip4Out,channels[curr_channel].portOut);
		}
	unicast_reply_write(reply, HTTP_CHANNELS_REPLY_END);

	unicast_reply_send(reply, Socket, 200, "text/html");

	if (0 != unicast_reply_free(reply)) {
		log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n");
		return -1;
	}

	return 0;
}
Beispiel #6
0
/** @brief Send a basic JSON file containig the list of streamed channels
 *
 * @param number_of_channels the number of channels
 * @param channels the channels array
 * @param Socket the socket on wich the information have to be sent
 */
int unicast_send_streamed_channels_list_js (int number_of_channels, mumudvb_channel_t *channels, int Socket)
{
	int curr_channel;
	unicast_client_t *unicast_client=NULL;
	int clients=0;

	struct unicast_reply* reply = unicast_reply_init();
	if (NULL == reply) {
		log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n");
		return -1;
	}

	unicast_reply_write(reply, "[");
	for (curr_channel = 0; curr_channel < number_of_channels; curr_channel++)
	{
		clients=0;
		unicast_client=channels[curr_channel].clients;
		while(unicast_client!=NULL)
		{
			unicast_client=unicast_client->chan_next;
			clients++;
		}
		unicast_reply_write(reply, "{\"number\":%d, \"lcn\":%d, \"name\":\"%s\", \"sap_group\":\"%s\", \"ip_multicast\":\"%s\", \"port_multicast\":%d, \"num_clients\":%d, \"scrambling_ratio\":%d, \"is_up\":%d, \"pcr_pid\":%d, \"pmt_version\":%d, ",
				curr_channel+1,
				channels[curr_channel].logical_channel_number,
				channels[curr_channel].name,
				channels[curr_channel].sap_group,
				channels[curr_channel].ip4Out,
				channels[curr_channel].portOut,
				clients,
				channels[curr_channel].ratio_scrambled,
				channels[curr_channel].streamed_channel,
				channels[curr_channel].pcr_pid,
				channels[curr_channel].pmt_version );

		unicast_reply_write(reply, "\"unicast_port\":%d, \"service_id\":%d, \"service_type\":\"%s\", \"pids_num\":%d, \n",
				channels[curr_channel].unicast_port,
				channels[curr_channel].service_id,
				service_type_to_str(channels[curr_channel].channel_type),
				channels[curr_channel].num_pids);
		unicast_reply_write(reply, "\"pids\":[");
		for(int i=0;i<channels[curr_channel].num_pids;i++)
			unicast_reply_write(reply, "{\"number\":%d, \"type\":\"%s\", \"language\":\"%s\"},\n",
					channels[curr_channel].pids[i],
					pid_type_to_str(channels[curr_channel].pids_type[i]),
					channels[curr_channel].pids_language[i]);
		reply->used_body -= 2; // dirty hack to erase the last comma
		unicast_reply_write(reply, "]");
		unicast_reply_write(reply, "},\n");

	}
	reply->used_body -= 2; // dirty hack to erase the last comma
	unicast_reply_write(reply, "]\n");

	unicast_reply_send(reply, Socket, 200, "application/json");

	if (0 != unicast_reply_free(reply)) {
		log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n");
		return -1;
	}
	return 0;
}
Beispiel #7
0
/** @brief Send an action to the CAM MMI menu
 *
 * @param Socket the socket on wich the information have to be sent
 */
int
unicast_send_cam_action (int Socket, char *Key, void *cam_p_v)
{
#ifndef ENABLE_CAM_SUPPORT
	(void) cam_p_v; //to make compiler happy
#else
	cam_p_t *cam_p=(cam_p_t *)cam_p_v;
#endif
	struct unicast_reply* reply = unicast_reply_init();
	if (NULL == reply)
	{
		log_message( log_module, MSG_INFO,"Unicast : Error when creating the HTTP reply\n");
		return -1;
	}

	// UTF-8 Byte Order Mark (BOM)
	unicast_reply_write(reply, "\xef\xbb\xbf");

	// Date time formatting
	time_t rawtime;
	time (&rawtime);
	char sdatetime[25];
	snprintf(sdatetime,25,"%s",ctime(&rawtime));

	// XML header
	unicast_reply_write(reply, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");

	// Starting XML content
	unicast_reply_write(reply, "<action>\n");
	unicast_reply_write(reply, "\t<datetime><![CDATA[%.24s]]></datetime>\n",ctime(&rawtime));
	unicast_reply_write(reply, "\t<key><![CDATA[%c]]></key>\n",*Key);

#ifdef ENABLE_CAM_SUPPORT
	// Check if valid action to be done [0-9] and 'M' and 'C' and 'O'
	int iKey=(int)*Key;
	if ((iKey>=48 && iKey<=57) || iKey==77 || iKey==67 || iKey==79)
	{
		// Check if CAM is initialized
		if (cam_p->ca_resource_connected!=0)
		{
			// Disable auto response from now (as a manual action is asked)
			cam_p->cam_mmi_autoresponse=0;
			// Numbers for MENU/LIST answer
			if (cam_p->mmi_state==MMI_STATE_MENU && iKey>=48 && iKey<=57)
			{
				log_message( log_module,  MSG_INFO, "Send CAM MENU key number %d\n",iKey-48);
				en50221_app_mmi_menu_answ(cam_p->stdcam->mmi_resource, cam_p->stdcam->mmi_session_number, iKey-48);
				cam_p->mmi_state=MMI_STATE_OPEN;
			}
			// 'M' = ask the menu - Always possible
			if (iKey==77)
			{
				log_message( log_module,  MSG_INFO, "Ask CAM to enter MENU\n");
				en50221_app_ai_entermenu(cam_p->stdcam->ai_resource, cam_p->stdcam->ai_session_number);
				cam_p->mmi_state=MMI_STATE_OPEN;
			}
			// Numbers for ENQUIRY answer
			if (cam_p->mmi_state==MMI_STATE_ENQ && iKey>=48 && iKey<=57)
			{
				// We store the new key
				cam_p->mmi_enq_answer[cam_p->mmi_enq_entered]=iKey;
				cam_p->mmi_enq_entered++;
				log_message( log_module,  MSG_INFO, "Received CAM ENQUIRY key number %d (%d of %d expected)\n", iKey-48, cam_p->mmi_enq_entered, cam_p->mmi_enq_length);
				// Test if the expected length is received
				if (cam_p->mmi_enq_entered == cam_p->mmi_enq_length)
				{
					// We send the anwser
					log_message( log_module,  MSG_INFO, "Sending ENQUIRY answer to CAM (answer has the expected length of %d)\n",cam_p->mmi_enq_entered);
					en50221_app_mmi_answ(cam_p->stdcam->mmi_resource, cam_p->stdcam->mmi_session_number, MMI_ANSW_ID_ANSWER, (uint8_t*)cam_p->mmi_enq_answer, cam_p->mmi_enq_entered);
					cam_p->mmi_state=MMI_STATE_OPEN;
				}
			}
			// 'C' = send CANCEL as an ENQUIRY answer
			if (cam_p->mmi_state==MMI_STATE_ENQ && iKey==67)
			{
				log_message( log_module,  MSG_INFO, "Send CAM ENQUIRY key CANCEL\n");
				en50221_app_mmi_answ(cam_p->stdcam->mmi_resource, cam_p->stdcam->mmi_session_number, MMI_ANSW_ID_CANCEL, NULL, 0);
				cam_p->mmi_state=MMI_STATE_OPEN;
			}
			// OK
			unicast_reply_write(reply, "\t<result><![CDATA[OK]]></result>\n");
		}
		else
		{
			unicast_reply_write(reply, "\t<result><![CDATA[ERROR: CAM not initialized!]]></result>\n");
		}
	}
	else
	{
		unicast_reply_write(reply, "\t<result><![CDATA[ERROR: Unknown key!]]></result>\n");
	}
#else
	unicast_reply_write(reply, "\t<result><![CDATA[Compiled without CAM support]]></result>\n");
#endif

	// Ending XML content
	unicast_reply_write(reply, "</action>\n");

	// Cleaning all non acceptable characters for pseudo UTF-8 (in fact, US-ASCII) - Skipping BOM and last zero character
	unsigned char c;
	int j;
	for (j=3; j<reply->used_body; j++)
	{
		c=reply->buffer_body[j];
		if ((c<32 || c>127) && c!=9 && c!=10 && c!=13)
			reply->buffer_body[j]=32;
	}
	unicast_reply_send(reply, Socket, 200, "application/xml; charset=UTF-8");

	// End of HTTP reply
	if (0 != unicast_reply_free(reply)) {
		log_message( log_module, MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n");
		return -1;
	}
	return 0;
}
Beispiel #8
0
/** @brief Return the last MMI menu sent by CAM
 *
 * @param Socket the socket on wich the information have to be sent
 */
int
unicast_send_cam_menu (int Socket, void *cam_p_v)
{
#ifndef ENABLE_CAM_SUPPORT
	(void) cam_p_v; //to make compiler happy
#else
	cam_p_t *cam_p=(cam_p_t *)cam_p_v;
#endif
	struct unicast_reply* reply = unicast_reply_init();
	if (NULL == reply)
	{
		log_message( log_module, MSG_INFO,"Unicast : Error when creating the HTTP reply\n");
		return -1;
	}

	// UTF-8 Byte Order Mark (BOM)
	unicast_reply_write(reply, "\xef\xbb\xbf");

	// Date time formatting
	time_t rawtime;
	time (&rawtime);
	char sdatetime[25];
	snprintf(sdatetime,25,"%s",ctime(&rawtime));

	// XML header
	unicast_reply_write(reply, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");

	// Starting XML content
	unicast_reply_write(reply, "<menu>\n");

#ifdef ENABLE_CAM_SUPPORT
	// Sending the last menu if existing
	if (cam_p->ca_resource_connected!=0)
	{
		if (cam_p->cam_menulist_str.length>0)
		{
			unicast_reply_write(reply, "%s",cam_p->cam_menulist_str.string);
		}
		else
		{
			unicast_reply_write(reply, "\t<datetime><![CDATA[%s]]></datetime>\n",sdatetime);
			unicast_reply_write(reply, "\t<cammenustring><![CDATA[%s]]></cammenustring>\n",cam_p->cam_menu_string.string);
			unicast_reply_write(reply, "\t<object><![CDATA[NONE]]></object>\n");
			unicast_reply_write(reply, "\t<title><![CDATA[No menu to display]]></title>\n");
		}
	}
	else
	{
		unicast_reply_write(reply, "\t<datetime><![CDATA[%s]]></datetime>\n",sdatetime);
		unicast_reply_write(reply, "\t<object><![CDATA[NONE]]></object>\n");
		unicast_reply_write(reply, "\t<title><![CDATA[CAM not initialized!]]></title>\n");
	}
#else
	unicast_reply_write(reply, "\t<datetime><![CDATA[%s]]></datetime>\n",sdatetime);
	unicast_reply_write(reply, "\t<object><![CDATA[NONE]]></object>\n");
	unicast_reply_write(reply, "\t<title><![CDATA[Compiled without CAM support]]></title>\n");
#endif

	// Ending XML content
	unicast_reply_write(reply, "</menu>\n");

	// Cleaning all non acceptable characters for pseudo UTF-8 (in fact, US-ASCII) - Skipping BOM and last zero character
	unsigned char c;
	int j;
	for (j=3; j<reply->used_body; j++)
	{
		c=reply->buffer_body[j];
		if ((c<32 || c>127) && c!=9 && c!=10 && c!=13)
			reply->buffer_body[j]=32;
	}
	unicast_reply_send(reply, Socket, 200, "application/xml; charset=UTF-8");

	// End of HTTP reply
	if (0 != unicast_reply_free(reply)) {
		log_message( log_module, MSG_INFO,"Unicast : Error when releasing the HTTP reply after sendinf it\n");
		return -1;
	}
	return 0;
}
Beispiel #9
0
/** @brief Send a full XML state of the mumudvb instance
 *
 * @param number_of_channels the number of channels
 * @param channels the channels array
 * @param Socket the socket on wich the information have to be sent
 * @param fds the frontend device structure
 */
int
unicast_send_xml_state (int number_of_channels, mumudvb_channel_t *channels, int Socket, strength_parameters_t *strengthparams, auto_p_t *auto_p, void *cam_p_v, void *scam_vars_v)
{
#ifndef ENABLE_CAM_SUPPORT
	(void) cam_p_v; //to make compiler happy
#else
	cam_p_t *cam_p=(cam_p_t *)cam_p_v;
#endif

#ifndef ENABLE_SCAM_SUPPORT
	(void) scam_vars_v; //to make compiler happy
#else
	scam_parameters_t *scam_vars=(scam_parameters_t *)scam_vars_v;
#endif
	// Prepare the HTTP reply
	struct unicast_reply* reply = unicast_reply_init();
	if (NULL == reply) {
		log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n");
		return -1;
	}

	// Date time formatting
	time_t rawtime;
	time (&rawtime);
	char sdatetime[25];
	snprintf(sdatetime,25,"%s",ctime(&rawtime));

	// XML header
	unicast_reply_write(reply, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");

	// Starting XML content
	unicast_reply_write(reply, "<mumudvb card=\"%d\" frontend=\"%d\">\n",strengthparams->tune_p->card,strengthparams->tune_p->tuner);

	// Mumudvb information
	unicast_reply_write(reply, "\t<global_version><![CDATA[%s]]></global_version>\n",VERSION);
	unicast_reply_write(reply, "\t<global_pid>%d</global_pid>\n",getpid ());

	// Uptime
	extern long real_start_time;
	struct timeval tv;
	gettimeofday (&tv, (struct timezone *) NULL);
	unicast_reply_write(reply, "\t<global_uptime>%d</global_uptime>\n",(tv.tv_sec - real_start_time));

	// Frontend setup
	unicast_reply_write(reply, "\t<frontend_name><![CDATA[%s]]></frontend_name>\n",strengthparams->tune_p->fe_name);
	unicast_reply_write(reply, "\t<frontend_tuned>%d</frontend_tuned>\n",strengthparams->tune_p->card_tuned);
	if (strengthparams->tune_p->fe_type==FE_QPSK) // Do some test for always showing frequency in kHz
	{
		unicast_reply_write(reply, "\t<frontend_frequency>%d</frontend_frequency>\n",strengthparams->tune_p->freq);
		unicast_reply_write(reply, "\t<frontend_satnumber>%d</frontend_satnumber>\n",strengthparams->tune_p->sat_number);
	}
	else
		unicast_reply_write(reply, "\t<frontend_frequency>%d</frontend_frequency>\n",(strengthparams->tune_p->freq)/1000);
	if (strengthparams->tune_p->pol==0)
		unicast_reply_write(reply, "\t<frontend_polarization><![CDATA[-]]></frontend_polarization>\n");
	else
		unicast_reply_write(reply, "\t<frontend_polarization><![CDATA[%c]]></frontend_polarization>\n",strengthparams->tune_p->pol);
	unicast_reply_write(reply, "\t<frontend_symbolrate>%d</frontend_symbolrate>\n",strengthparams->tune_p->srate);

	// Frontend type
	char fetype[10]="Unkonwn";
	if (strengthparams->tune_p->fe_type==FE_OFDM)
#ifdef DVBT2
		if (strengthparams->tune_p->delivery_system==SYS_DVBT2)
			snprintf(fetype,10,"DVB-T2");
		else
			snprintf(fetype,10,"DVB-T");
#else
	snprintf(fetype,10,"DVB-T");
#endif
	if (strengthparams->tune_p->fe_type==FE_QAM)  snprintf(fetype,10,"DVB-C");
	if (strengthparams->tune_p->fe_type==FE_ATSC) snprintf(fetype,10,"ATSC");
	if (strengthparams->tune_p->fe_type==FE_QPSK)
	{
#if DVB_API_VERSION >= 5
		if (strengthparams->tune_p->delivery_system==SYS_DVBS2)
			snprintf(fetype,10,"DVB-S2");
#ifdef DVBT2
		else if (strengthparams->tune_p->delivery_system==SYS_DVBT2)
			snprintf(fetype,10,"DVB-T2");
#endif
		else
			snprintf(fetype,10,"DVB-S");
#else
		snprintf(fetype,10,"DVB-S");
#endif
	}
	unicast_reply_write(reply, "\t<frontend_system><![CDATA[%s]]></frontend_system>\n",fetype);

	// Frontend status
	char SCVYL[6]="-----";
	if (strengthparams->festatus & FE_HAS_SIGNAL)  SCVYL[0]=83; // S
	if (strengthparams->festatus & FE_HAS_CARRIER) SCVYL[1]=67; // C
	if (strengthparams->festatus & FE_HAS_VITERBI) SCVYL[2]=86; // V
	if (strengthparams->festatus & FE_HAS_SYNC)    SCVYL[3]=89; // Y
	if (strengthparams->festatus & FE_HAS_LOCK)    SCVYL[4]=76; // L
	SCVYL[5]=0;
	unicast_reply_write(reply, "\t<frontend_status><![CDATA[%s]]></frontend_status>\n",SCVYL);

	// Frontend signal
	unicast_reply_write(reply, "\t<frontend_ber>%d</frontend_ber>\n",strengthparams->ber);
	unicast_reply_write(reply, "\t<frontend_signal>%d</frontend_signal>\n",strengthparams->strength);
	unicast_reply_write(reply, "\t<frontend_snr>%d</frontend_snr>\n",strengthparams->snr);
	unicast_reply_write(reply, "\t<frontend_ub>%d</frontend_ub>\n",strengthparams->ub);
	unicast_reply_write(reply, "\t<ts_discontinuities>%d</ts_discontinuities>\n",strengthparams->ts_discontinuities);


	// Autoconfiguration state
	if (auto_p->autoconfiguration!=0)
		unicast_reply_write(reply, "\t<autoconf_end>%d</autoconf_end>\n",0);
	else
		unicast_reply_write(reply, "\t<autoconf_end>%d</autoconf_end>\n",1);

	// CAM information
#ifdef ENABLE_CAM_SUPPORT
	unicast_reply_write(reply, "\t<cam_support>%d</cam_support>\n",cam_p->cam_support);
	unicast_reply_write(reply, "\t<cam_number>%d</cam_number>\n",cam_p->cam_number);
	unicast_reply_write(reply, "\t<cam_menustring><![CDATA[%s]]></cam_menustring>\n",cam_p->cam_menu_string.string);
	unicast_reply_write(reply, "\t<cam_initialized>%d</cam_initialized>\n",cam_p->ca_resource_connected);
#else
	unicast_reply_write(reply, "\t<cam_support>%d</cam_support>\n",0);
	unicast_reply_write(reply, "\t<cam_number>%d</cam_number>\n",0);
	unicast_reply_write(reply, "\t<cam_menustring><![CDATA[No CAM support]]></cam_menustring>\n");
	unicast_reply_write(reply, "\t<cam_initialized>%d</cam_initialized>\n",0);
#endif

	// SCAM information
#ifdef ENABLE_SCAM_SUPPORT
	unicast_reply_write(reply, "\t<scam_support>%d</scam_support>\n",scam_vars->scam_support);
	if (scam_vars->scam_support) {
		unicast_reply_write(reply, "\t<ring_buffer_default_size>%u</ring_buffer_default_size>\n",scam_vars->ring_buffer_default_size);
		unicast_reply_write(reply, "\t<decsa_default_delay>%u</decsa_default_delay>\n",scam_vars->decsa_default_delay);
		unicast_reply_write(reply, "\t<send_default_delay>%u</send_default_delay>\n",scam_vars->send_default_delay);
	}
	else {
		unicast_reply_write(reply, "\t<ring_buffer_default_size>%u</ring_buffer_default_size>\n",0);
		unicast_reply_write(reply, "\t<decsa_default_delay>%u</decsa_default_delay>\n",0);
		unicast_reply_write(reply, "\t<send_default_delay>%u</send_default_delay>\n",0);
	}
#else
	unicast_reply_write(reply, "\t<scam_support>%d</scam_support>\n",0);
	unicast_reply_write(reply, "\t<ring_buffer_default_size>%u</ring_buffer_default_size>\n",0);
	unicast_reply_write(reply, "\t<decsa_default_delay>%u</decsa_default_delay>\n",0);
	unicast_reply_write(reply, "\t<send_default_delay>%u</send_default_delay>\n",0);
#endif

	// Channels list
	int curr_channel;
	for (curr_channel = 0; curr_channel < number_of_channels; curr_channel++)
	{
		unicast_reply_write(reply, "\t<channel number=\"%d\" is_up=\"%d\">\n",curr_channel+1,channels[curr_channel].streamed_channel);
		unicast_reply_write(reply, "\t\t<lcn>%d</lcn>\n",channels[curr_channel].logical_channel_number);
		unicast_reply_write(reply, "\t\t<name><![CDATA[%s]]></name>\n",channels[curr_channel].name);
		unicast_reply_write(reply, "\t\t<service_type type=\"%d\"><![CDATA[%s]]></service_type>\n",channels[curr_channel].channel_type,service_type_to_str(channels[curr_channel].channel_type));
		if (channels[curr_channel].portOut==0)
			unicast_reply_write(reply, "\t\t<ip_multicast><![CDATA[0.0.0.0]]></ip_multicast>\n");
		else
			unicast_reply_write(reply, "\t\t<ip_multicast><![CDATA[%s]]></ip_multicast>\n",channels[curr_channel].ip4Out);
		unicast_reply_write(reply, "\t\t<port_multicast>%d</port_multicast>\n",channels[curr_channel].portOut);
		unicast_reply_write(reply, "\t\t<traffic>%.0f</traffic>\n",channels[curr_channel].traffic);
		unicast_reply_write(reply, "\t\t<ratio_scrambled>%d</ratio_scrambled>\n",channels[curr_channel].ratio_scrambled);
		unicast_reply_write(reply, "\t\t<service_id>%d</service_id>\n",channels[curr_channel].service_id);
		unicast_reply_write(reply, "\t\t<pmt_pid>%d</pmt_pid>\n",channels[curr_channel].pmt_pid);
		unicast_reply_write(reply, "\t\t<pmt_version>%d</pmt_version>\n",channels[curr_channel].pmt_version);
		unicast_reply_write(reply, "\t\t<pcr_pid>%d</pcr_pid>\n",channels[curr_channel].pcr_pid);
		unicast_reply_write(reply, "\t\t<unicast_port>%d</unicast_port>\n",channels[curr_channel].unicast_port);
		// SCAM information
#ifdef ENABLE_SCAM_SUPPORT
		if (scam_vars->scam_support) {
			unicast_reply_write(reply, "\t\t<scam descrambled=\"%d\">\n",channels[curr_channel].scam_support);
			if (channels[curr_channel].scam_support) {
				unsigned int ring_buffer_num_packets = 0;

				if (channels[curr_channel].ring_buf) {
					pthread_mutex_lock(&channels[curr_channel].ring_buf->lock);
					ring_buffer_num_packets = channels[curr_channel].ring_buf->to_descramble + channels[curr_channel].ring_buf->to_send;
					pthread_mutex_unlock(&channels[curr_channel].ring_buf->lock);
				}

				unicast_reply_write(reply, "\t\t\t<ring_buffer_size>%u</ring_buffer_size>\n",channels[curr_channel].ring_buffer_size);
				unicast_reply_write(reply, "\t\t\t<decsa_delay>%u</decsa_delay>\n",channels[curr_channel].decsa_delay);
				unicast_reply_write(reply, "\t\t\t<send_delay>%u</send_delay>\n",channels[curr_channel].send_delay);
				unicast_reply_write(reply, "\t\t\t<num_packets>%u</num_packets>\n",ring_buffer_num_packets);
			}
			unicast_reply_write(reply, "\t\t</scam>\n");
		}
#endif
		unicast_reply_write(reply, "\t\t<ca_sys>\n");
		for(int i=0;i<32;i++)
			if(channels[curr_channel].ca_sys_id[i]!=0)
				unicast_reply_write(reply, "\t\t\t<ca num=\"%d\"><![CDATA[%s]]></ca>\n",channels[curr_channel].ca_sys_id[i],ca_sys_id_to_str(channels[curr_channel].ca_sys_id[i]));
		unicast_reply_write(reply, "\t\t</ca_sys>\n");
		unicast_reply_write(reply, "\t\t<pids>\n");
		for(int i=0;i<channels[curr_channel].num_pids;i++)
			unicast_reply_write(reply, "\t\t\t<pid number=\"%d\" language=\"%s\" scrambled=\"%d\"><![CDATA[%s]]></pid>\n", channels[curr_channel].pids[i], channels[curr_channel].pids_language[i], channels[curr_channel].pids_scrambled[i], pid_type_to_str(channels[curr_channel].pids_type[i]));
		unicast_reply_write(reply, "\t\t</pids>\n");
		unicast_reply_write(reply, "\t</channel>\n");
	}

	// Ending XML content
	unicast_reply_write(reply, "</mumudvb>\n");

	unicast_reply_send(reply, Socket, 200, "application/xml; charset=UTF-8");

	// End of HTTP reply
	if (0 != unicast_reply_free(reply)) {
		log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n");
		return -1;
	}
	return 0;
}
Beispiel #10
0
/** @brief Deal with an incoming message on the unicast client connection
 * This function will store and answer the HTTP requests
 *
 *
 * @param unicast_vars the unicast parameters
 * @param client The client from which the message was received
 * @param channels the channel array
 * @param number_of_channels quite explicit ...
 */
int unicast_handle_message(unicast_parameters_t *unicast_vars, unicast_client_t *client, mumudvb_channel_t *channels, int number_of_channels, strength_parameters_t *strengthparams, auto_p_t *auto_p, void *cam_p, void *scam_vars)
{
	int received_len;
	(void) unicast_vars;

	/************ auto increasing buffer to receive the message **************/
	if((client->buffersize-client->bufferpos)<RECV_BUFFER_MULTIPLE)
	{
		client->buffer=realloc(client->buffer,(client->buffersize + RECV_BUFFER_MULTIPLE+1)*sizeof(char)); //the +1 if for the \0 at the end
		if(client->buffer==NULL)
		{
			log_message( log_module, MSG_ERROR,"Problem with realloc for the client buffer : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__);
			client->buffersize=0;
			client->bufferpos=0;
			return -1;
		}
		memset (client->buffer+client->buffersize, 0, RECV_BUFFER_MULTIPLE*sizeof(char)); //We fill the buffer with zeros to be sure
		client->buffersize += RECV_BUFFER_MULTIPLE;
	}

	received_len=recv(client->Socket, client->buffer+client->bufferpos, RECV_BUFFER_MULTIPLE, 0);

	if(received_len>0)
	{
		if(client->bufferpos==0)
			log_message( log_module, MSG_FLOOD,"beginning of buffer %c%c%c%c%c\n",client->buffer[0],client->buffer[1],client->buffer[2],client->buffer[3],client->buffer[4]);
		client->bufferpos+=received_len;
		log_message( log_module, MSG_FLOOD,"We received %d, buffer len %d new buffer pos %d\n",received_len,client->buffersize, client->bufferpos);
	}

	if(received_len==-1)
	{
		log_message( log_module, MSG_ERROR,"Problem with recv : %s\n",strerror(errno));
		return -1;
	}
	if(received_len==0)
		return -2; //To say to the main program to close the connection

	/***************** Now we parse the message to see if something was asked  *****************/
	client->buffer[client->buffersize]='\0'; //For avoiding strlen to look too far (other option is to use the gnu extension strnlen)
	//We search for the end of the HTTP request
	if(strlen(client->buffer)>5 && strstr(client->buffer, "\n\r\n\0"))
	{
		int pos,err404;
		char *substring=NULL;
		int requested_channel;
		int iRet;
		requested_channel=0;
		pos=0;
		err404=0;
		struct unicast_reply* reply=NULL;

		log_message( log_module, MSG_FLOOD,"End of HTTP request, we parse it\n");

		if(strstr(client->buffer,"GET ")==client->buffer)
		{
			//to implement :
			//Information ???
			//GET /monitor/???

			pos=4;

			/* preselected channels via the port of the connection */
			//if the client have already an asked channel we don't parse the GET
			if(client->askedChannel!=-1)
			{
				requested_channel=client->askedChannel+1; //+1 because requested channel starts at 1 and asked channel starts at 0
				log_message( log_module, MSG_DEBUG,"Channel by socket, number %d\n",requested_channel);
				client->askedChannel=-1;
			}
			//Channel by number
			//GET /bynumber/channelnumber
			else if(strstr(client->buffer +pos ,"/bynumber/")==(client->buffer +pos))
			{
				if(client->chan_ptr!=NULL)
				{
					log_message( log_module, MSG_INFO,"A channel (%s) is already streamed to this client, it shouldn't ask for a new one without closing the connection, error 501\n",client->chan_ptr->name);
					iRet=write(client->Socket,HTTP_501_REPLY, strlen(HTTP_501_REPLY));
					if(iRet<0)
						log_message( log_module, MSG_INFO,"Error writing reply\n");

					return -2; //to delete the client
				}

				pos+=strlen("/bynumber/");
				substring = strtok (client->buffer+pos, " ");
				if(substring == NULL)
					err404=1;
				else
				{
					requested_channel=atoi(substring);
					if(requested_channel && requested_channel<=number_of_channels)
						log_message( log_module, MSG_DEBUG,"Channel by number, number %d\n",requested_channel);
					else
					{
						log_message( log_module, MSG_INFO,"Channel by number, number %d out of range\n",requested_channel);
						err404=1;
						requested_channel=0;
					}
				}
			}
			//Channel by autoconf_sid_list
			//GET /bysid/sid
			else if(strstr(client->buffer +pos ,"/bysid/")==(client->buffer +pos))
			{
				if(client->chan_ptr!=NULL)
				{
					log_message( log_module, MSG_INFO,"A channel (%s) is already streamed to this client, it shouldn't ask for a new one without closing the connection, error 501\n",client->chan_ptr->name);
					iRet=write(client->Socket,HTTP_501_REPLY, strlen(HTTP_501_REPLY)); //iRet is to make the copiler happy we will close the connection anyways
					return -2; //to delete the client
				}
				pos+=strlen("/bysid/");
				substring = strtok (client->buffer+pos, " ");
				if(substring == NULL)
					err404=1;
				else
				{
					int requested_sid;
					requested_sid=atoi(substring);
					for(int current_channel=0; current_channel<number_of_channels;current_channel++)
					{
						if(channels[current_channel].service_id == requested_sid)
							requested_channel=current_channel+1;
					}
					if(requested_channel)
						log_message( log_module, MSG_DEBUG,"Channel by service id,  service_id %d number %d\n", requested_sid, requested_channel);
					else
					{
						log_message( log_module, MSG_INFO,"Channel by service id, service_id  %d not found\n",requested_sid);
						err404=1;
						requested_channel=0;
					}
				}
			}
			//Channel by name
			//GET /byname/channelname
			else if(strstr(client->buffer +pos ,"/byname/")==(client->buffer +pos))
			{
				if(client->chan_ptr!=NULL)
				{
					log_message( log_module, MSG_INFO,"A channel (%s) is already streamed to this client, it shouldn't ask for a new one without closing the connection, error 501\n",client->chan_ptr->name);
					iRet=write(client->Socket,HTTP_501_REPLY, strlen(HTTP_501_REPLY));//iRet is to make the copiler happy we will close the connection anyways
					return -2; //to delete the client
				}
				pos+=strlen("/byname/");
				log_message( log_module, MSG_DEBUG,"Channel by number\n");
				substring = strtok (client->buffer+pos, " ");
				if(substring == NULL)
					err404=1;
				else
				{
					log_message( log_module, MSG_DEBUG,"Channel by name, name %s\n",substring);
					//search the channel
					err404=1;//Temporary
					/** @todo implement the search without the spaces*/
				}
			}
			//Channels list
			else if(strstr(client->buffer +pos ,"/channels_list.html ")==(client->buffer +pos))
			{
				//We get the host name if availaible
				char *hoststr;
				hoststr=strstr(client->buffer ,"Host: ");
				if(hoststr)
				{
					substring = strtok (hoststr+6, "\r");
				}
				else
					substring=NULL;
				log_message( log_module, MSG_DETAIL,"Channel list\n");
				unicast_send_streamed_channels_list (number_of_channels, channels, client->Socket, substring);
				return -2; //We close the connection afterwards
			}
			//playlist, m3u
			else if(strstr(client->buffer +pos ,"/playlist.m3u ")==(client->buffer +pos))
			{
				log_message( log_module, MSG_DETAIL,"play list\n");
				unicast_send_play_list_unicast (number_of_channels, channels, client->Socket, unicast_vars->portOut, 0 );
				return -2; //We close the connection afterwards
			}
			//playlist, m3u
			else if(strstr(client->buffer +pos ,"/playlist_port.m3u ")==(client->buffer +pos))
			{
				log_message( log_module, MSG_DETAIL,"play list\n");
				unicast_send_play_list_unicast (number_of_channels, channels, client->Socket, unicast_vars->portOut, 1 );
				return -2; //We close the connection afterwards
			}
			else if(strstr(client->buffer +pos ,"/playlist_multicast.m3u ")==(client->buffer +pos))
			{
				log_message( log_module, MSG_DETAIL,"play list\n");
				unicast_send_play_list_multicast (number_of_channels, channels, client->Socket, 0 );
				return -2; //We close the connection afterwards
			}
			else if(strstr(client->buffer +pos ,"/playlist_multicast_vlc.m3u ")==(client->buffer +pos))
			{
				log_message( log_module, MSG_DETAIL,"play list\n");
				unicast_send_play_list_multicast (number_of_channels, channels, client->Socket, 1 );
				return -2; //We close the connection afterwards
			}
			//statistics, text version
			else if(strstr(client->buffer +pos ,"/channels_list.json ")==(client->buffer +pos))
			{
				log_message( log_module, MSG_DETAIL,"Channel list Json\n");
				unicast_send_streamed_channels_list_js (number_of_channels, channels, client->Socket);
				return -2; //We close the connection afterwards
			}
			else if(strstr(client->buffer +pos ,"/monitor/signal_power.json ")==(client->buffer +pos))
			{
				log_message( log_module, MSG_DETAIL,"Signal power json\n");
				unicast_send_signal_power_js(client->Socket, strengthparams);
				return -2; //We close the connection afterwards
			}
			else if(strstr(client->buffer +pos ,"/monitor/channels_traffic.json ")==(client->buffer +pos))
			{
				log_message( log_module, MSG_DETAIL,"Channel traffic json\n");
				unicast_send_channel_traffic_js(number_of_channels, channels, client->Socket);
				return -2; //We close the connection afterwards
			}
			else if(strstr(client->buffer +pos ,"/monitor/state.xml ")==(client->buffer +pos))
			{
				log_message( log_module, MSG_DETAIL,"HTTP request for XML State\n");
				unicast_send_xml_state(number_of_channels, channels, client->Socket, strengthparams, auto_p, cam_p, scam_vars);
				return -2; //We close the connection afterwards
			}
			else if(strstr(client->buffer +pos ,"/cam/menu.xml ")==(client->buffer +pos))
			{
				log_message( log_module, MSG_DETAIL,"HTTP request for CAM menu display \n");
				unicast_send_cam_menu(client->Socket, cam_p);
				return -2; //We close the connection afterwards
			}
			else if(strstr(client->buffer +pos ,"/cam/action.xml?key=")==(client->buffer +pos))
			{
				log_message( log_module, MSG_DETAIL,"HTTP request for CAM menu action\n");
				pos+=strlen("/cam/action.xml?key=");
				unicast_send_cam_action(client->Socket,client->buffer+pos, cam_p);
				return -2; //We close the connection afterwards
			}

			//Not implemented path --> 404
			else
				err404=1;


			if(err404)
			{
				log_message( log_module, MSG_INFO,"Path not found i.e. 404\n");
				reply = unicast_reply_init();
				if (NULL == reply) {
					log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n");
					return -2;
				}
				unicast_reply_write(reply, HTTP_404_REPLY_HTML, VERSION);
				unicast_reply_send(reply, client->Socket, 404, "text/html");
				if (0 != unicast_reply_free(reply)) {
					log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n");
					return -2;
				}
				return -2; //to delete the client
			}
			//We have found a channel, we add the client
			if(requested_channel)
			{
				if(!channel_add_unicast_client(client,&channels[requested_channel-1]))
					client->chan_ptr=&channels[requested_channel-1];
				else
					return -2;
			}

		}
		else
		{
			//We don't implement this http method, but if the client is already connected, we keep the connection
			if(client->chan_ptr==NULL)
			{
				log_message( log_module, MSG_INFO,"Unhandled HTTP method : \"%s\", error 501\n",  strtok (client->buffer+pos, " "));
				iRet=write(client->Socket,HTTP_501_REPLY, strlen(HTTP_501_REPLY));//iRet is to make the copiler happy we will close the connection anyways
				return -2; //to delete the client
			}
			else
			{
				log_message( log_module, MSG_INFO,"Unhandled HTTP method : \"%s\", error 501 but we keep the client connected\n",  strtok (client->buffer+pos, " "));
				iRet=write(client->Socket,HTTP_501_REPLY, strlen(HTTP_501_REPLY));//iRet is to make the copiler happy we will close the connection anyways
				return 0;
			}
		}
		//We don't need the buffer anymore
		free(client->buffer);
		client->buffer=NULL;
		client->bufferpos=0;
		client->buffersize=0;
	}

	return 0;
}