コード例 #1
0
ファイル: gpac_ts_muxer.c プロジェクト: erelh/gpac
/*!
 * Sends the TS mux to socket
 * \param avr The AVRedirect structure pointer
 */
static GF_Err sendTSMux(GF_AbstractTSMuxer * ts)
{
    u32 status;
    const char * pkt;
    GF_Err e;
    u32 padding, data;
    padding = data = 0;
    while ( (NULL!= ( pkt = gf_m2ts_mux_process ( ts->muxer, &status ))))
    {
        switch (status) {
        case GF_M2TS_STATE_IDLE:
            break;
        case GF_M2TS_STATE_DATA:
            data+=188;
            break;
        case GF_M2TS_STATE_PADDING:
            padding+=188;
            break;
        default:
            break;
        }
        if (ts->ts_output_udp_sk) {
            e = gf_sk_send ( ts->ts_output_udp_sk, pkt, 188);
            if ( e )
            {
                GF_LOG ( GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Unable to send TS data : %s\n", gf_error_to_string(e)) );
                return e;
            }
        }
    }
    if (data || padding)
        GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[AVRedirect] : Sent TS data=%u/padding=%u\n", data, padding));
    return GF_OK;
}
コード例 #2
0
ファイル: RTP_serv_sender.c プロジェクト: erelh/gpac
GF_Err PNC_SendRTP(PNC_CallbackData *data, char *payload, int payloadSize)
{
	GF_Err e;
	unsigned char feedback_buffer[250];

	if (!data->hdr->TimeStamp)
		data->hdr->TimeStamp = ((PNC_CallbackExt * )data->extension)->lastTS;

	((PNC_CallbackExt * )data->extension)->lastTS = data->hdr->TimeStamp;

	e = gf_rtp_send_packet(data->chan, data->hdr, payload, payloadSize, 0);
	dprintf(DEBUG_RTP_serv_sender, "SendPacket : %d, TimeStamp RTP = %d, sz= %d\n",
			e, data->hdr->TimeStamp, payloadSize);

	// sending feedback bytes
	memset(feedback_buffer, 0, sizeof(feedback_buffer));
	sprintf((char *) feedback_buffer, "DataSent=%d\nRAPsent=%d\n", payloadSize, data->RAPsent);
	e = gf_sk_send(data->feedback_socket, feedback_buffer, strlen((char *) feedback_buffer));
	dprintf(DEBUG_RTP_serv_packetizer, "Sent feedback data %d byte, return %d\n", payloadSize, e);

	return GF_OK;
}
コード例 #3
0
ファイル: broadcaster.c プロジェクト: golgol7777/gpac
u32 tcp_server(void *par)
{
	TCP_Input *input = par;
	u32 *timer = input->RAPtimer;
	char buffer[MAX_BUF];
	unsigned char temp[MAX_BUF];
	FILE *fp;
	u32 byte_read;
	int ret;
	GF_Config *gf_config_file;
	GF_Socket *TCP_socket;
	GF_Socket *conn_socket;
	GF_Err e;
	
	int debug = input->debug;
	input->status = 1;

	TCP_socket = gf_sk_new(GF_SOCK_TYPE_TCP);
	e = gf_sk_bind(TCP_socket, NULL, input->port, NULL, 0, 0);
	e = gf_sk_listen(TCP_socket, 1);
	e = gf_sk_set_block_mode(TCP_socket, 1);
	e = gf_sk_server_mode(TCP_socket, 0);
	
	while(input->status == 1)
	{	
		memset(buffer, 0, sizeof(buffer));	
		e = gf_sk_accept(TCP_socket, &conn_socket);
		if (e == GF_OK) {
			memset(buffer, 0, sizeof(buffer));
			e = gf_sk_receive(conn_socket, buffer, MAX_BUF, 0, &byte_read);
		}

		switch (e) {
			case GF_IP_NETWORK_EMPTY:
				gf_sleep(33);
				continue;
			case GF_OK:					
				break;
			default:
				fprintf(stderr, "Error with TCP socket : %s\n", gf_error_to_string(e));
				exit(1);
				break;
		}

		if((*(input->config_flag)) == 0)
		{
			u32 num_retry;
			fp = fopen("temp.cfg", "w+");
			if (!fp) {
				fprintf(stderr, "Error opening temp file for the configuration\n");
				exit(1);
			}
			ret = fwrite(buffer, 1, byte_read, fp);
			fclose(fp);
			
			/* parsing config info */
			gf_config_file = gf_cfg_new(".", "temp.cfg");
			if (!gf_config_file) {
				fprintf(stderr, "Error opening the config file %s\n", gf_error_to_string(e));
				exit(-1);
			}
			parse_config(gf_config_file, input->config, debug);

			/* Acknowledging the configuration */ 
			gf_sk_send(conn_socket, "OK\n", 3);

			memset(temp, 0, sizeof(temp));
			fp = fopen(input->config->scene_init_file, "w+");
			if (!fp) {
				fprintf(stderr, "Error opening temp file for reception of the initial scene\n");
				exit(1);
			}
			num_retry=10;

			while (1)
			{
				GF_Err e = gf_sk_receive(conn_socket, temp, sizeof(temp), 0, &byte_read);

				if (e == GF_OK) {
					fwrite(temp, 1, byte_read, fp);
				} else if (e==GF_IP_NETWORK_EMPTY) {
					num_retry--;
					if (!num_retry)
						break;
					gf_sleep(1);
				} else {
					fprintf(stderr, "Error receiving initial scene: %s\n", gf_error_to_string(e));
					break;
				}
			}
			fclose(fp);
			*(input->config_flag) = 1;
		}
		/* we only wait now for the config updates */
		if ( (*(input->config_flag)) == 1) {
			ret = sscanf(buffer, "DelaiMax=%d\n", timer);							
			fprintf(stdout, "RAP timer changed, now : %d\n", *timer);
		}
		gf_sk_del(conn_socket);
	}

	input->status = 2;
	return GF_OK;
}
コード例 #4
0
void http_do_requests(GF_DownloadSession *sess)
{
	GF_Err e;
	Bool is_ice;
	GF_NETIO_Parameter par;
	char sHTTP[GF_DOWNLOAD_BUFFER_SIZE];
	char buf[1024];
	char comp[400];
	char *new_location;
	char *hdr, *hdr_val;
	u32 bytesRead, res;
	s32 LinePos, Pos;
	u32 rsp_code, ContentLength, first_byte, last_byte, total_size, range, no_range;
	s32 BodyStart;

	/*sent HTTP request*/
	if (sess->status==GF_NETIO_CONNECTED) {
		char range_buf[1024];
		char pass_buf[1024];
		const char *user_agent;
		u32 size;
		Bool has_accept, has_connection, has_range, has_agent;

		/*setup authentification*/
		strcpy(pass_buf, "");
		if (sess->user) {
			if (!sess->passwd) {
				char szUSR[50], szPASS[50];
				strcpy(szUSR, sess->user);
				strcpy(szPASS, "");
				/*failed getting pass*/
				if (!sess->dm->GetUserPassword || !sess->dm->GetUserPassword(sess->dm->usr_cbk, sess->server_name, szUSR, szPASS)) {
					sess->status = GF_NETIO_STATE_ERROR;
					return;
				}
				sess->passwd = strdup(szPASS);
			}
			sprintf(pass_buf, "%s:%s", sess->user, sess->passwd);
			size = gf_base64_encode(pass_buf, strlen(pass_buf), range_buf, 1024);
			range_buf[size] = 0;
			sprintf(pass_buf, "Authorization: Basic %s", range_buf);
		}


		/*MIX2005 KMS project*/
#if 0
		if (strstr(sess->remote_path, "getKey.php?")) {
			char *sLogin, *sPass;
			sLogin = gf_cfg_get_key(sess->dm->cfg, "General", "KMS_User");
			sPass = gf_cfg_get_key(sess->dm->cfg, "General", "KMS_Password");
			if (!sLogin) sLogin = "******";
			if (!sPass) sPass = "******";
			sprintf(https_get_buffer, "%s&login=%s&password=%s", sess->remote_path, sLogin, sPass);
		}
#endif	

		user_agent = gf_cfg_get_key(sess->dm->cfg, "Downloader", "UserAgent");
		if (!user_agent) user_agent = GF_DOWNLOAD_AGENT_NAME;

		par.error = 0;
		par.msg_type = GF_NETIO_GET_METHOD;
		par.name = NULL;
		gf_dm_sess_user_io(sess, &par);

		if (par.name) {
			if (!strcmp(par.name, "GET")) sess->http_read_type = 0;
			else if (!strcmp(par.name, "HEAD")) sess->http_read_type = 1;
			else sess->http_read_type = 2;
		} else {
			sess->http_read_type = 0;
		}

		sprintf(sHTTP, "%s %s HTTP/1.0\r\nHost: %s\r\n" ,
			par.name ? par.name : "GET", sess->remote_path, sess->server_name);

		/*signal we support title streaming*/
		if (!strcmp(sess->remote_path, "/")) strcat(sHTTP, "icy-metadata:1\r\n");

		/*get all headers*/
		has_agent = has_accept = has_connection = has_range = 0;
		while (1) {
			par.msg_type = GF_NETIO_GET_HEADER;
			par.name = NULL;
			par.value = NULL;
			gf_dm_sess_user_io(sess, &par);
			if (!par.name) break;
			strcat(sHTTP, par.name);
			strcat(sHTTP, ": ");
			strcat(sHTTP, par.value);
			strcat(sHTTP, "\r\n");
			if (!strcmp(par.name, "Accept")) has_accept = 1;
			else if (!strcmp(par.name, "Connection")) has_connection = 1;
			else if (!strcmp(par.name, "Range")) has_range = 1;
			else if (!strcmp(par.name, "User-Agent")) has_agent = 1;
		}
		if (!has_agent) {
			strcat(sHTTP, "User-Agent: ");
			strcat(sHTTP, user_agent);
			strcat(sHTTP, "\r\n");
		}
		if (!has_accept) strcat(sHTTP, "Accept: */*\r\n");
		if (!has_connection) strcat(sHTTP, "Connection: Keep-Alive\r\n");
		if (!has_range && sess->cache_start_size) {
			sprintf(range_buf, "Range: bytes=%d-\r\n", sess->cache_start_size);
			strcat(sHTTP, range_buf);
		}
		if (strlen(pass_buf)) {
			strcat(sHTTP, pass_buf);
			strcat(sHTTP, "\r\n");
		}
		if (sess->flags & GF_DOWNLOAD_IS_ICY) strcat(sHTTP, "Icy-Metadata: 1\r\n");
		
		par.msg_type = GF_NETIO_GET_CONTENT;
		par.data = NULL;
		par.size = 0;
		gf_dm_sess_user_io(sess, &par);
		if (par.data && par.size) {
			sprintf(range_buf, "Content-Length: %d\r\n", par.size);
			strcat(sHTTP, range_buf);
		}
		strcat(sHTTP, "\r\n");

#ifdef GPAC_HAS_SSL
		if (sess->ssl) {
			e = GF_IP_NETWORK_FAILURE;
			if (!SSL_write(sess->ssl, sHTTP, strlen(sHTTP))) e = GF_OK;
		} else 
#endif
			e = gf_sk_send(sess->sock, sHTTP, strlen(sHTTP));

		GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[HTTP] %s\n\n", sHTTP));
		if (e) {
			sess->status = GF_NETIO_STATE_ERROR;
			sess->last_error = e;
			gf_dm_sess_notify_state(sess, GF_NETIO_STATE_ERROR, e);
			return;
		}

		if (par.size && par.data) {
			u32 done = 0;
			while (done<par.size) {
			
#ifdef GPAC_HAS_SSL
				if (sess->ssl) {
					e = GF_IP_NETWORK_FAILURE;
					if (!SSL_write(sess->ssl, par.data+done, par.size-done)) e = GF_OK;
				} else 
#endif
					e = gf_sk_send(sess->sock, par.data+done, par.size-done);

				if (e) {
					sess->status = GF_NETIO_STATE_ERROR;
					sess->last_error = e;
					gf_dm_sess_notify_state(sess, GF_NETIO_STATE_ERROR, e);
					return;
				}
			}
		}
		sess->status = GF_NETIO_WAIT_FOR_REPLY;
		gf_dm_sess_notify_state(sess, GF_NETIO_WAIT_FOR_REPLY, GF_OK);
		return;
	}

	/*process HTTP request*/
	if (sess->status == GF_NETIO_WAIT_FOR_REPLY) {
		bytesRead = res = 0;
		new_location = NULL;
		while (1) {
			e = gf_dm_read_data(sess, sHTTP + bytesRead, GF_DOWNLOAD_BUFFER_SIZE - bytesRead, &res);
	
			switch (e) {
			case GF_IP_NETWORK_EMPTY:
				if (!bytesRead) return;
				continue;
			/*socket has been closed while configuring, retry (not sure if the server got the GET)*/
			case GF_IP_CONNECTION_CLOSED:
				gf_dm_disconnect(sess);
				if (sess->num_retry)
					sess->status = GF_NETIO_SETUP;
				else {
					sess->last_error = e;
					sess->status = GF_NETIO_STATE_ERROR;
				}
				return;
			case GF_OK:
				if (!res) return;
				break;
			default:
				goto exit;
			}
			bytesRead += res;

			/*locate body start*/
			BodyStart = gf_token_find(sHTTP, 0, bytesRead, "\r\n\r\n");
			if (BodyStart <= 0) {
				BodyStart=0;
				continue;
			}
			BodyStart += 4;
			break;
		}
		if (bytesRead < 0) {
			e = GF_REMOTE_SERVICE_ERROR;
			goto exit;
		}
		if (!BodyStart) 
			BodyStart = bytesRead;

		sHTTP[BodyStart-1] = 0;
		GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[HTTP] %s\n\n", sHTTP));

		LinePos = gf_token_get_line(sHTTP, 0, bytesRead, buf, 1024);
		Pos = gf_token_get(buf, 0, " \t\r\n", comp, 400);

		if (sess->mime_type) free(sess->mime_type);
		sess->mime_type = NULL;

		is_ice = 0;
		if (!strncmp("ICY", comp, 4)) {
			is_ice = 1;
			/*be prepared not to recieve any mime type from ShoutCast servers*/
			sess->mime_type = strdup("audio/mpeg");
		} else if ((strncmp("HTTP", comp, 4) != 0)) {
			e = GF_REMOTE_SERVICE_ERROR;
			goto exit;
		}
		Pos = gf_token_get(buf, Pos, " ", comp, 400);
		if (Pos <= 0) {
			e = GF_REMOTE_SERVICE_ERROR;
			goto exit;
		}
		rsp_code = (u32) atoi(comp);
		Pos = gf_token_get(buf, Pos, " \r\n", comp, 400);

		no_range = range = ContentLength = first_byte = last_byte = total_size = 0;
		//parse header
		while (1) {
			char *sep, *hdr_sep;
			if ( (u32) LinePos + 4 > BodyStart) break;
			LinePos = gf_token_get_line(sHTTP, LinePos , bytesRead, buf, 1024);
			if (LinePos < 0) break;

			hdr_sep = NULL;
			hdr_val = NULL;
			hdr = buf;
			sep = strchr(buf, ':');
			if (sep) {
				sep[0]=0;
				hdr_val = sep+1;
				while (hdr_val[0]==' ') hdr_val++;
				hdr_sep = strrchr(hdr_val, '\r');
				if (hdr_sep) hdr_sep[0] = 0;
			}

			par.error = 0;
			par.msg_type = GF_NETIO_PARSE_HEADER;
			par.name = hdr;
			par.value = hdr_val;
			gf_dm_sess_user_io(sess, &par);

			if (!stricmp(hdr, "Content-Length") ) ContentLength = (u32) atoi(hdr_val);
			else if (!stricmp(hdr, "Content-Type")) {			
				if (sess->mime_type) free(sess->mime_type);
				sess->mime_type = strdup(hdr_val);
				while (1) {
					u32 len = strlen(sess->mime_type);
					char c = len ? sess->mime_type[len-1] : 0;
					if ((c=='\r') || (c=='\n')) {
						sess->mime_type[len-1] = 0;
					} else {
						break;
					}
				}
				hdr = strchr(sess->mime_type, ';');
				if (hdr) hdr[0] = 0;
			}
			else if (!stricmp(hdr, "Content-Range")) {			
				range = 1;
				if (!strncmp(hdr_val, "bytes", 5)) {
					hdr_val += 5;
					if (hdr_val[0] == ':') hdr_val += 1;
					hdr_val += http_skip_space(hdr_val);
					if (hdr_val[0] == '*') {
						sscanf(hdr_val, "*/%d", &total_size);
					} else {
						sscanf(hdr_val, "%d-%d/%d", &first_byte, &last_byte, &total_size);
					}
				}
			}
			else if (!stricmp(hdr, "Accept-Ranges")) {
				if (strstr(hdr_val, "none")) no_range = 1;
			}
			else if (!stricmp(hdr, "Location")) 
				new_location = strdup(hdr_val);
			else if (!stricmp(hdr, "icy-metaint")) 
				sess->icy_metaint = atoi(hdr_val);
			else if (!stricmp(hdr, "ice") || !stricmp(hdr, "icy") ) 
				is_ice = 1;

			if (sep) sep[0]=':';
			if (hdr_sep) hdr_sep[0] = '\r';
		}
		if (no_range) first_byte = 0;

		if (sess->cache_start_size) {
			if (total_size && (sess->cache_start_size >= total_size) ) {
				rsp_code = 200;
				ContentLength = total_size;
			}
			if (ContentLength && (sess->cache_start_size == ContentLength) ) rsp_code = 200;
		}	

		par.msg_type = GF_NETIO_PARSE_REPLY;
		par.error = GF_OK;
		par.reply = rsp_code;
		par.value = comp;

		switch (rsp_code) {
		case 200:
		case 201:
		case 202:
		case 206:
			gf_dm_sess_user_io(sess, &par);
			e = GF_OK;
			break;
		/*redirection: extract the new location*/
		case 301:
		case 302:
			if (!new_location || !strlen(new_location) ) {
				gf_dm_sess_user_io(sess, &par);
				e = GF_URL_ERROR;
				goto exit;
			}
			while (
				(new_location[strlen(new_location)-1] == '\n') 
				|| (new_location[strlen(new_location)-1] == '\r')  )
				new_location[strlen(new_location)-1] = 0;

			/*reset and reconnect*/
			gf_dm_disconnect(sess);
			sess->status = GF_NETIO_SETUP;
			e = gf_dm_setup_from_url(sess, new_location);
			if (e) {
				sess->status = GF_NETIO_STATE_ERROR;
				sess->last_error = e;
				gf_dm_sess_notify_state(sess, sess->status, e);
				return;
			}
			return;
		case 404:
		case 416:
			/*try without cache (some servers screw up when content-length is specified)*/
			if (sess->cache_start_size) {
				gf_dm_disconnect(sess);
				sess->status = GF_NETIO_SETUP;
				return;
			} else if (is_ice && !(sess->flags & GF_DOWNLOAD_IS_ICY)) {
				gf_dm_disconnect(sess);
				sess->status = GF_NETIO_SETUP;
				sess->flags |= GF_DOWNLOAD_IS_ICY;
				return;
			}
			gf_dm_sess_user_io(sess, &par);
			e = GF_URL_ERROR;
			goto exit;
		case 503:
		default:
			gf_dm_sess_user_io(sess, &par);
			e = GF_REMOTE_SERVICE_ERROR;
			goto exit;
		}

		/*head*/
		if (sess->http_read_type==1) {
			gf_dm_disconnect(sess);
			gf_dm_sess_notify_state(sess, GF_NETIO_DATA_TRANSFERED, GF_OK);
			sess->status = GF_NETIO_DISCONNECTED;
			sess->http_read_type = 0;
			return;
		}

		if (!ContentLength && sess->mime_type && strstr(sess->mime_type, "ogg")) is_ice = 1;

		/*some servers may reply without content length, but we MUST have it*/
//		if (!is_ice && !ContentLength) e = GF_REMOTE_SERVICE_ERROR;
		if (e) goto exit;

		/*force disabling cache (no content length)*/
		if (is_ice) {
			sess->flags |= GF_NETIO_SESSION_NOT_CACHED;
			if (sess->mime_type && !stricmp(sess->mime_type, "video/nsv")) {
				free(sess->mime_type);
				sess->mime_type = strdup("audio/aac");
			}
		}


		/*done*/
		if (sess->cache_start_size 
			&& ( (total_size && sess->cache_start_size >= total_size) || (sess->cache_start_size == ContentLength)) ) {
			sess->total_size = sess->bytes_done = sess->cache_start_size;
			/*disconnect*/
			gf_dm_disconnect(sess);
			BodyStart = bytesRead;
			gf_dm_sess_notify_state(sess, GF_NETIO_DATA_TRANSFERED, GF_OK);
		}
		else if (sess->flags & GF_DOWNLOAD_IS_ICY) {
			sess->icy_bytes = 0;
			sess->status = GF_NETIO_DATA_EXCHANGE;
		}
		/*we don't expect anything*/
		else if (!ContentLength && sess->http_read_type) {
			gf_dm_disconnect(sess);
			gf_dm_sess_notify_state(sess, GF_NETIO_DATA_TRANSFERED, GF_OK);
			sess->status = GF_NETIO_DISCONNECTED;
			sess->http_read_type = 0;
		}
		/*no range header, Accep-Ranges deny or dumb server : restart*/
		else if (!range || !first_byte || (first_byte != sess->cache_start_size) ) {
			sess->cache_start_size = sess->bytes_done = 0;
			sess->total_size = ContentLength;
			if (! (sess->flags & GF_NETIO_SESSION_NOT_CACHED) ) {
				sess->cache = fopen(sess->cache_name, "wb");
				if (!sess->cache) {
					e = GF_IO_ERR;
					goto exit;
				}
			}
			sess->status = GF_NETIO_DATA_EXCHANGE;
		}
		/*resume*/
		else {
			sess->total_size = ContentLength + sess->cache_start_size;
			if (! (sess->flags & GF_NETIO_SESSION_NOT_CACHED) ) {
				sess->cache = fopen(sess->cache_name, "ab");
				if (!sess->cache) {
					e = GF_IO_ERR;
					goto exit;
				}
			}
			sess->status = GF_NETIO_DATA_EXCHANGE;
			sess->bytes_done = sess->cache_start_size;
		}

		sess->window_start = sess->start_time = gf_sys_clock();
		sess->bytes_in_wnd = 0;


		//we may have existing data in this buffer ...
		if (!e && (BodyStart < (u32) bytesRead)) {
			gf_dm_data_recieved(sess, sHTTP + BodyStart, bytesRead - BodyStart);
			/*store data if no callbacks or cache*/
			if (sess->flags & GF_NETIO_SESSION_NOT_CACHED) {
				if (sess->init_data) free(sess->init_data);
				sess->init_data_size = bytesRead - BodyStart;
				sess->init_data = (char *) malloc(sizeof(char) * sess->init_data_size);
				memcpy(sess->init_data, sHTTP+BodyStart, sess->init_data_size);
			}
		}
exit:
		if (e) {
			gf_dm_disconnect(sess);
			sess->status = GF_NETIO_STATE_ERROR;
			sess->last_error = e;
			gf_dm_sess_notify_state(sess, sess->status, e);
		}
		return;
	}
	/*fetch data*/
	while (1) {
		u32 size;
#if 1
		if (sess->limit_data_rate && sess->bytes_per_sec) {
			if (sess->bytes_per_sec>sess->limit_data_rate) {
				/*update state*/
				u32 runtime = gf_sys_clock() - sess->window_start;
				sess->bytes_per_sec = (1000 * (sess->bytes_in_wnd)) / runtime;
				if (sess->bytes_per_sec > sess->limit_data_rate) return;
			}
		}
#endif
		e = gf_dm_read_data(sess, sHTTP, GF_DOWNLOAD_BUFFER_SIZE, &size);
		if (!size || e == GF_IP_NETWORK_EMPTY) {
		
			if (!sess->total_size && (gf_sys_clock() - sess->window_start > 1000)) {
				sess->total_size = sess->bytes_done;
				gf_dm_sess_notify_state(sess, GF_NETIO_DATA_TRANSFERED, GF_OK);
			}
			return;
		}

		if (e) {
			gf_dm_disconnect(sess);
			sess->last_error = e;
			gf_dm_sess_notify_state(sess, sess->status, e);
			return;
		}
		gf_dm_data_recieved(sess, sHTTP, size);
		/*socket empty*/
		if (size < GF_DOWNLOAD_BUFFER_SIZE) return;
	}
}