Ejemplo n.º 1
0
// hogehoge/abc/ddd/// -> hogehoge/abc/
char *get_parent_path(char *dst, char *src, size_t len)
{
	char *p;

	if (strlen(src) > len || len <= 0) {
		debug_log_output("get_parent_path: no enough space");
		strncpy(dst, "/", len);
		return dst;
	}
	// とりあえず全部コピー。
	strncpy(dst, src, len);

	// 一番後ろの '/' を削除
	for (p = dst + strlen(dst) - 1; p > dst && *p == '/'; p--) *p = '\0';

	p = strrchr(dst, '/');
	if (p == NULL || p == dst) {
		debug_log_output("get_parent_path: no / anymore..., i.e., root.");
		strncpy(dst, "/", len);
		return dst;
	}

	// 残った最後の '/' より後ろを削除
	*++p = '\0';

	return dst;
}
Ejemplo n.º 2
0
// **************************************************************************
// accept_socketから、1行(CRLFか、LF単独が現れるまで)受信
// CRLFは削除する。
// 受信したサイズをreturnする。
// **************************************************************************
int line_receive(int accept_socket, char *line_buf_p, int line_max)
{
    char byte_buf;
    int 	line_len=0;
    int		recv_len;
    // 1行受信実行
    while ( 1 ){
        recv_len = recv(accept_socket, &byte_buf, 1, 0);
        if ( recv_len != 1 ){ // 受信失敗チェック
#ifdef linux
            debug_log_output("header read error cnt = %d error=%s\n", recv_len, strerror(errno));
#else
            debug_log_output("header read error cnt = %d socket=%d error=%d\n", recv_len, accept_socket, WSAGetLastError());
#endif
            return ( -1 );
        }
        // CR/LFチェック
        if       ( byte_buf == '\r' ){
            continue;
        }else if ( byte_buf == '\n' ){
            *line_buf_p = 0;
            break;
        }
        // バッファにセット
        *line_buf_p++ = byte_buf;
        // 受信バッファサイズチェック
        if ( ++line_len >= line_max){
            // バッファオーバーフロー検知
            debug_log_output("line_buf over flow.");
            return ( -1 );
        }
    }
    return line_len;
}
Ejemplo n.º 3
0
FILETYPES http_index( HTTP_RECV_INFO* http_recv_info_p )
{
    char       document_path[FILENAME_MAX];
    char       read_filename[FILENAME_MAX];
    char       file_extension[16];
    //Path Normalize.
    strncpy(document_path, http_recv_info_p->send_filename, sizeof(document_path) );
    if ( document_path[ strlen(document_path)-1 ] != DELIMITER[0] ){// 最後が'/'じゃなかったら、'/'を追加
        strncat(document_path, DELIMITER, sizeof(document_path) -strlen(document_path) );
    }
    // ----------------------------------------------
    // document_root/index.* のフルパス生成
    // ----------------------------------------------
    snprintf(read_filename, sizeof( read_filename),"%sindex.html",document_path );
    if( access( read_filename , 0 ) == 0 ){
        strcat(http_recv_info_p->request_uri,"index.html");
        strcpy(http_recv_info_p->send_filename,read_filename);
        // ファイルの拡張子より、Content-type を決定
        filename_to_extension(http_recv_info_p->send_filename, file_extension, sizeof(file_extension));
        debug_log_output("http_recv_info_p->send_filename='%s', file_extension='%s'\n", http_recv_info_p->send_filename, file_extension);
        // 拡張子から、mime_typeを導く。
        check_file_extension_to_mime_type(file_extension, http_recv_info_p->mime_type,  sizeof(http_recv_info_p->mime_type));
        return _FILE;
    }
    snprintf(read_filename, sizeof( read_filename),"%sindex.htm",document_path );
    if( access( read_filename , 0 ) == 0 ){
        strcat(http_recv_info_p->request_uri,"index.htm");
        strcpy(http_recv_info_p->send_filename,read_filename);
        // ファイルの拡張子より、Content-type を決定
        filename_to_extension(http_recv_info_p->send_filename, file_extension, sizeof(file_extension));
        debug_log_output("http_recv_info_p->send_filename='%s', file_extension='%s'\n", http_recv_info_p->send_filename, file_extension);
        // 拡張子から、mime_typeを導く。
        check_file_extension_to_mime_type(file_extension, http_recv_info_p->mime_type,  sizeof(http_recv_info_p->mime_type));
        return _FILE;
    }
    snprintf(read_filename, sizeof( read_filename),"%sindex.php",document_path );
    if( access( read_filename , 0 ) == 0 ){
        strcat(http_recv_info_p->request_uri,"index.php");
        strcpy(http_recv_info_p->send_filename,read_filename);
        // ファイルの拡張子より、Content-type を決定
        filename_to_extension(http_recv_info_p->send_filename, file_extension, sizeof(file_extension));
        debug_log_output("http_recv_info_p->send_filename='%s', file_extension='%s'\n", http_recv_info_p->send_filename, file_extension);
        // 拡張子から、mime_typeを導く。
        check_file_extension_to_mime_type(file_extension, http_recv_info_p->mime_type,  sizeof(http_recv_info_p->mime_type));
        return _CGI;
    }
    snprintf(read_filename, sizeof( read_filename),"%sindex.jss",document_path );
    if( access( read_filename , 0 ) == 0 ){
        strcat(http_recv_info_p->request_uri,"index.jss");
        strcpy(http_recv_info_p->send_filename,read_filename);
        // ファイルの拡張子より、Content-type を決定
        filename_to_extension(http_recv_info_p->send_filename, file_extension, sizeof(file_extension));
        debug_log_output("http_recv_info_p->send_filename='%s', file_extension='%s'\n", http_recv_info_p->send_filename, file_extension);
        // 拡張子から、mime_typeを導く。
        check_file_extension_to_mime_type(file_extension, http_recv_info_p->mime_type,  sizeof(http_recv_info_p->mime_type));
        return _CGI;
    }
    return _DIR;
}
Ejemplo n.º 4
0
static int http_not_found_response(int accept_socket, HTTP_RECV_INFO *http_recv_info_p)
{
	char buffer[WIZD_FILENAME_MAX];

	if((strlen(http_recv_info_p->mime_type)==0) || (strcmp(http_recv_info_p->mime_type, "text/html") == 0)) {
	    snprintf(buffer, sizeof(buffer),
		HTTP_NOT_FOUND
		HTTP_CONNECTION
		HTTP_CONTENT_TYPE
		HTTP_END
		"<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>\r\n"
		"<BODY>File not found<P>\r\n"
		"%s\r\n"
		"</BODY></HTML>\r\n", http_recv_info_p->mime_type, http_recv_info_p->recv_uri
	    );
	} else {
	    snprintf(buffer, sizeof(buffer),
			HTTP_NOT_FOUND
			HTTP_CONNECTION
			HTTP_CONTENT_TYPE
			HTTP_END, "text/plain" );
	}
	debug_log_output("Not found: %s\n%s", http_recv_info_p->recv_uri, buffer);
	write(accept_socket, buffer, strlen(buffer)+1);

	return 0;

/*
	return http_redirect_response(accept_socket, http_recv_info_p, "/");
*/
}
Ejemplo n.º 5
0
static int http_redirect_response(int accept_socket, HTTP_RECV_INFO *http_recv_info, char *location)
{
    IGNORE_PARAMETER(http_recv_info);
    char buffer[FILENAME_MAX];
    snprintf(buffer, sizeof(buffer),"HTTP/1.1 301 Found\r\n" "Location: %s\r\n" "\r\n", location );
    send( accept_socket , buffer , strlen( buffer ) + 1 , 0 );
    debug_log_output("Redirect to %s",location);
    return 0;
}
Ejemplo n.º 6
0
void set_blocking_mode(int fd, int flag)
{
	int res, nonb = 0;

	nonb |= O_NONBLOCK;

	if ((res = fcntl(fd, F_GETFL, 0)) == -1) {
		debug_log_output("fcntl(fd, F_GETFL) failed");
	}
	if (flag) {
		res |= O_NONBLOCK;
	} else {
		res &= ~O_NONBLOCK;
	}
	if (fcntl(fd, F_SETFL, res) == -1) {
		debug_log_output("fcntl(fd, F_SETFL, nonb) failed");
	}
}
Ejemplo n.º 7
0
int
http_find_and_replace(int accept_socket, HTTP_RECV_INFO *http_recv_info)
{
	char		*index_array[] = {"wizd.htm", "wizd.html", "index.htm", "index.html"};
	char		 wizd_buf[256];
	int			 i;
	SKIN_T 		*index_skin;
	char		*p;
	SKIN_REPLASE_GLOBAL_DATA_T	*skin_rep_data_global_p;
	extern void send_menu(int accept_socket, SKIN_REPLASE_GLOBAL_DATA_T *skin_rep_data_global_p, HTTP_RECV_INFO *http_recv_info_p, int skip);

	for (i = 0; i < 4; i++) {
		if (find_real_path(index_array[i], http_recv_info, wizd_buf)) {
			if (strncasecmp(index_array[i], "wizd", 4) == 0) {
				debug_log_output("HTTP: got wizd.htm\n");

				http_send_ok_header(accept_socket, 0, NULL);
				index_skin = malloc(sizeof(SKIN_T));
				index_skin->buffer = skin_file_read(wizd_buf, &index_skin->buffer_size);
				skin_rep_data_global_p = skin_create_global_data(http_recv_info, 0);
				skin_direct_replace_global(index_skin, skin_rep_data_global_p);
				if ((p = strstr(index_skin->buffer, SKIN_KEYWORD_MENU)) != 0) {
					// add in the menu (mid_*.html) info
					send(accept_socket, index_skin->buffer, p - index_skin->buffer, 0);
					send_menu(accept_socket, skin_rep_data_global_p, http_recv_info, 0);
					p += strlen(SKIN_KEYWORD_MENU);
					send(accept_socket, p, index_skin->buffer + strlen(index_skin->buffer) - p, 0);

				} else
					skin_direct_send(accept_socket, index_skin);
				skin_close(index_skin);
				free( skin_rep_data_global_p );
			} else {
				debug_log_output("HTTP: got index.htm\n");
				strcpy(http_recv_info->send_filename, wizd_buf);
				http_file_response(accept_socket, http_recv_info);
			}

			return(1);
		}
	}

	return(0);
}
Ejemplo n.º 8
0
static int http_not_found_response(int accept_socket, HTTP_RECV_INFO *http_recv_info)
{
    char buffer[1024];
    sprintf(buffer,  HTTP_NOT_FOUND1 HTTP_SERVER_NAME HTTP_CONTENT_TYPE HTTP_CONTENT_LENGTH HTTP_END "%s"
    ,SERVER_NAME
    , "text/html"
    , (size_t)9
    ,"Not Found" );
    send(accept_socket, buffer, strlen(buffer),0);
    debug_log_output("Not Found %s", http_recv_info->request_uri);
    return 0;
}
Ejemplo n.º 9
0
// **************************************************************************
// 拡張子変更処理。削除用。
//	extension_convert_listに従い、rename → org への変換を行う。
//
// 例) "hogehoge.m2p.mpg" → "hogehoge.m2p"
// **************************************************************************
void extension_del_rename(unsigned char *rename_filename_p, size_t rename_filename_size)
{
	int i;
	unsigned char	renamed_ext[WIZD_FILENAME_MAX];
	unsigned char	ext[WIZD_FILENAME_MAX];

	if ( rename_filename_p == NULL )
		return;

	for ( i=0; extension_convert_list[i].org_extension != NULL; i++ )
	{
		debug_log_output("org='%s', rename='%s'"
			, extension_convert_list[i].org_extension
			, extension_convert_list[i].rename_extension);

		snprintf(renamed_ext, sizeof(renamed_ext), ".%s.%s"
			, extension_convert_list[i].org_extension
			, extension_convert_list[i].rename_extension);

		// 比較する拡張子と同じ長さにそろえる。
		strncpy(ext, rename_filename_p, sizeof(ext));
		cat_before_n_length(ext, strlen(renamed_ext));

		// 拡張子一致?
		if ( strcasecmp(ext, renamed_ext) == 0 )
		{
			debug_log_output(" HIT!!!" );
			// 拡張子を「削除」
			cat_after_n_length(rename_filename_p
				, strlen(extension_convert_list[i].rename_extension) + 1);

			debug_log_output("rename_filename_p='%s'", rename_filename_p);
			break;
		}
	}


	return;
}
Ejemplo n.º 10
0
//******************************************************************
// EUC文字列を、n byteに削除。文字列境界を見て良きに計らう。
// もし menu_font_metric が指定されており menu_font_metric_string が
// 指定されていれば、その値に従ってちょんぎる。
//******************************************************************
void euc_string_cut_n_length(unsigned char *euc_sentence,  unsigned int n)
{
	int	euc_flag = 0;
	unsigned char	*p, *prev_p;
	int total_len = 0;
	int size = 0;

	total_len = global_param.menu_font_metric * n;


	prev_p = p = euc_sentence;
	while (*p && total_len > 0) {
		if (*p >= sizeof(global_param.menu_font_metric_string)) {
			size = global_param.menu_font_metric;
		} else {
			char ch;
			ch = global_param.menu_font_metric_string[*p];
			if (ch < 'a' || ch > 'z') {
				size = global_param.menu_font_metric;
			} else {
				size = ch - 'a';
				if (size <= 0) {
					//debug_log_output("damn. old size: %d", size);
					size = global_param.menu_font_metric;
				}
			}
		}
		if (total_len < size) {
			if (euc_flag == 1) {
				*prev_p = '\0';
			} else {
				*p = '\0';
			}
			return ;
		}
		if (euc_flag == 0 && (( *p >= 0xA1 ) || ( *p == 0x8E ))) {
			// EUC-Code or 半角カタカナの上位
			euc_flag = 1;
		} else {
			euc_flag = 0;
		}
		total_len -= size;
		prev_p = p++;
	}

	debug_log_output("debug: rest %d", total_len);
	*p = '\0';

	return;
}
Ejemplo n.º 11
0
// **************************************************************************
// 拡張子変更処理。追加用。
//	extension_convert_listに従い、org → rename への変換を行う。
//
// 例) "hogehoge.m2p" → "hogehoge.m2p.mpg"
// **************************************************************************
void extension_add_rename(unsigned char *rename_filename_p, size_t rename_filename_size)
{
	int i;
	unsigned char	ext[WIZD_FILENAME_MAX];

	if ( rename_filename_p == NULL )
		return;

	filename_to_extension(rename_filename_p, ext, sizeof(ext));

	if (strlen(ext) <= 0) return;

	for ( i=0; extension_convert_list[i].org_extension != NULL; i++ )
	{
		debug_log_output("org='%s', rename='%s'"
			, extension_convert_list[i].org_extension
			, extension_convert_list[i].rename_extension);

		// 拡張子一致?
		if ( strcasecmp(ext, extension_convert_list[i].org_extension) == 0 )
		{
			debug_log_output(" HIT!!!" );
			// 拡張子を「追加」
			strncat(rename_filename_p, "."
				, rename_filename_size - strlen(rename_filename_p));
			strncat(rename_filename_p
				, extension_convert_list[i].rename_extension
				, rename_filename_size - strlen(rename_filename_p));

			debug_log_output("rename_filename_p='%s'", rename_filename_p);
			break;
		}
	}


	return;
}
Ejemplo n.º 12
0
// **************************************************************************
// accept_socketから、1行(CRLFか、LF単独が現れるまで)受信
// CRLFは削除する。
// 受信したサイズをreturnする。
// **************************************************************************
int line_receive(int accept_socket, unsigned char *line_buf_p, int line_max)
{
	unsigned char byte_buf;
	int 	line_len;
	int		recv_len;

	unsigned char *line_buf_work_p;

	line_buf_work_p = line_buf_p;
	line_len = 0;

	// 1行受信実行
	while ( 1 )
	{
		recv_len = recv(accept_socket, &byte_buf, 1, 0);
		if ( recv_len != 1 ) // 受信失敗チェック
		{
			//debug_log_output("line_receive: read_len == -1");
			return ( -1 );
		}

		// CR/LFチェック
		if ( byte_buf == '\r' )
		{
			continue;
		}
		else if ( byte_buf == '\n' )
		{
			break;
		}

		// バッファにセット
		*line_buf_work_p = byte_buf;
		line_buf_work_p++;
		line_len++;

		// printf("line_len=%d, buf='%s'\n", line_len, line_buf_p);

		// 受信バッファサイズチェック
		if ( line_len >= line_max)
		{
			// バッファオーバーフロー検知
			debug_log_output("line_buf over flow.");
			return line_len;
		}
	}

	return line_len;
}
Ejemplo n.º 13
0
int
http_find_and_replace_html(int accept_socket, HTTP_RECV_INFO *http_recv_info)
{
	char		 wizd_buf[256];
	int			 i;
	int			 len;
	SKIN_T 		*index_skin;
	char		*p;
	SKIN_REPLASE_GLOBAL_DATA_T	*skin_rep_data_global_p;
	struct stat		dir_stat;
	int			found = 0;
	extern void send_menu(int accept_socket, SKIN_REPLASE_GLOBAL_DATA_T *skin_rep_data_global_p, HTTP_RECV_INFO *http_recv_info_p, int skip);

	for (i = 0; i < global_param.num_aliases; i++) {
		len = strlen(global_param.alias_name[i]);
		if (strncmp(&(http_recv_info->recv_uri[1]), global_param.alias_name[i], len) == 0) {
			strcpy(wizd_buf, global_param.alias_path[i]);
			strcat(wizd_buf, http_recv_info->recv_uri + len + 1);
			if (stat(wizd_buf, &dir_stat) == 0) {
				found = 1;
				break;
			}
		}
	}

	if (found == 0)
		return(0);

	debug_log_output("HTTP: got wizd.htm\n");

	http_send_ok_header(accept_socket, 0, NULL);
	index_skin = malloc(sizeof(SKIN_T));
	index_skin->buffer = skin_file_read(wizd_buf, &index_skin->buffer_size);
	skin_rep_data_global_p = skin_create_global_data(http_recv_info, 0);
	skin_direct_replace_global(index_skin, skin_rep_data_global_p);
	if ((p = strstr(index_skin->buffer, SKIN_KEYWORD_MENU)) != 0) {
		// add in the menu (mid_*.html) info
		send(accept_socket, index_skin->buffer, p - index_skin->buffer, 0);
		send_menu(accept_socket, skin_rep_data_global_p, http_recv_info, 0);
		p += strlen(SKIN_KEYWORD_MENU);
		send(accept_socket, p, index_skin->buffer + strlen(index_skin->buffer) - p, 0);

	} else
		skin_direct_send(accept_socket, index_skin);
	skin_close(index_skin);
	free( skin_rep_data_global_p );

	return(1);
}
Ejemplo n.º 14
0
// **************************************************************************
//  SVI m2pファイルtotalサイズ読み込み
// **************************************************************************
u_int64_t  svi_file_total_size(unsigned char *svi_filename)
{
	int		fd;

	int			i;
	off_t		lseek_ret;
	ssize_t		read_length;

	unsigned char	total_size_work[SVI_TOTAL_SIZE_LENGTH];
	u_int64_t		total_size;

	// --------------------------------
	// SVIファイルから情報取り出す
	// --------------------------------

	// SVIファイル開く
	fd = open(svi_filename, O_RDONLY);
	if ( fd < 0 )
	{
		debug_log_output("oepn() error.");
		return 0;
	}

	// SVIファイルのファイル位置をGET
	lseek_ret = lseek(fd, SVI_TOTAL_SIZE_OFFSET, SEEK_SET);
	if ( lseek_ret < 0 )
	{
		debug_log_output("lseek() error.");
		return 0;
	}

	// SVIファイルから、m2pファイル 合計サイズをget
	read_length = read(fd, total_size_work, SVI_TOTAL_SIZE_LENGTH);
	debug_log_output("read_length=%d", read_length);
	debug_log_output("total_size=%02X,%02X,%02X,%02X,%02X"
		, total_size_work[0], total_size_work[1],total_size_work[2],total_size_work[3], total_size_work[4]);
	if (read_length != SVI_TOTAL_SIZE_LENGTH)
	{
		debug_log_output("read() error.");
		return 0;
	}

	close( fd );

	total_size = 0;
	for ( i=0; i<SVI_TOTAL_SIZE_LENGTH; i++ )
	{
		total_size += (u_int64_t)total_size_work[i] << (8 * i);
	}

	debug_log_output("total_size=%lld", total_size);

	return total_size;


}
Ejemplo n.º 15
0
static int http_unauthorized_response(int accept_socket, HTTP_RECV_INFO *http_recv_info)
{
	char buffer[WIZD_FILENAME_MAX];

	snprintf(buffer, sizeof(buffer),
		"HTTP/1.1 401 Authorization Required\r\n"
		"WWW-Authenticate: Basic realm=NEED AUTHENTICATE!\r\n"
		"\r\n"
	);
	debug_log_output("unauthorized response.");
	write(accept_socket, buffer, strlen(buffer)+1);

	return 0;
/*
	return http_redirect_response(accept_socket, http_recv_info, "/");
*/
}
Ejemplo n.º 16
0
// **************************************************************************
// ファイルの実体の送信実行部
// **************************************************************************
static off_t http_file_send(int accept_socket, unsigned char *filename, off_t content_length, off_t range_start_pos )
{
	off_t			seek_ret;
	off_t		written=0;

	// ---------------------
	// ファイルオープン
	// ---------------------
	if(global_param.buffer_size < 2) {
		FILE *fp = fopen(filename, "rb");
		if ( fp == NULL )
		{
			debug_log_output("errno = %s\n", strerror(errno));
			debug_log_output("fopen() error. file = '%s'", filename);
			return ( 0 );
		}
		seek_ret = fseek(fp, range_start_pos, SEEK_SET);
		if ( seek_ret < 0 )	// lseek エラーチェック
		{
			debug_log_output("fseek() error.");
			fclose(fp);
			return ( 0 );
		}
		written = copy_FILE_to_descriptor(fp, accept_socket, content_length);
		fclose(fp);	// File Close.
	} else {
		int fd = open(filename, O_RDONLY);
		if ( fd < 0 )
		{
			debug_log_output("errno = %s\n", strerror(errno));
			debug_log_output("open() error. file = '%s'", filename);
			return ( 0 );
		}

		// ------------------------------------------
		// range_start_posへファイルシーク
		// ------------------------------------------
		seek_ret = lseek(fd, range_start_pos, SEEK_SET);
		if ( seek_ret < 0 )	// lseek エラーチェック
		{
			debug_log_output("lseek() error.");
			close(fd);
			return ( 0 );
		}
		written = copy_descriptors(fd, accept_socket, content_length, NULL);
		close(fd);
	}

	// 正常終了
	return written;
}
Ejemplo n.º 17
0
static int next_file(int *in_fd_p, JOINT_FILE_INFO_T *joint_file_info_p)
{
	off_t	ret;

	if (in_fd_p && joint_file_info_p)
	{
		// 読み終わったファイルをCLOSE()
		debug_log_output("[%02d] '%s' close()", joint_file_info_p->current_file_num, joint_file_info_p->file[joint_file_info_p->current_file_num].name);
		close(*in_fd_p);

		// 次のファイルがあるか?
		joint_file_info_p->current_file_num++;
		if ( joint_file_info_p->current_file_num >= joint_file_info_p->file_num )
		{
			debug_log_output("EOF Detect.");
			//printf("EOF Detect.");
			return 1;		// これで終了
		}

		// 次のファイルをOPEN()
		debug_log_output("[%02d] '%s' open(), start_pos %lld\n", joint_file_info_p->current_file_num, joint_file_info_p->file[joint_file_info_p->current_file_num].name, joint_file_info_p->file[joint_file_info_p->current_file_num].start_pos);
		//printf("[%02d] '%s' open(), start_pos %lld, size %lld\n",
		//	joint_file_info_p->current_file_num,
		//	joint_file_info_p->file[joint_file_info_p->current_file_num].name,
		//	joint_file_info_p->file[joint_file_info_p->current_file_num].start_pos,
		//	joint_file_info_p->file[joint_file_info_p->current_file_num].size
		//	);

		*in_fd_p = open(joint_file_info_p->file[joint_file_info_p->current_file_num].name, O_RDONLY);
		if ( *in_fd_p < 0 )
		{
			debug_log_output("errno = %s\n", strerror(errno));
			debug_log_output("open() error. '%s'", joint_file_info_p->file[joint_file_info_p->current_file_num].name);
			return ( -1 );
		}

		ret = lseek(*in_fd_p, joint_file_info_p->file[joint_file_info_p->current_file_num].start_pos, SEEK_SET);

		debug_log_output("seek to %lld returned %lld\n", joint_file_info_p->file[joint_file_info_p->current_file_num].start_pos, ret);
		//printf("seek to %lld returned %lld\n", joint_file_info_p->file[joint_file_info_p->current_file_num].start_pos, ret);

		// ブロックモードの設定
		set_blocking_mode(*in_fd_p, 0);	/* blocking */

		return 0;		// 次のファイルの準備完了
	} else {
		// パラメータがNULLの場合には1ファイルのみの処理とする
		return 1;		// これで終了
	}
}
Ejemplo n.º 18
0
// **************************************************************************
// * SJIS文字列の中から、codeをを含む文字(2byte文字)を、固定文字列で置換する。
// **************************************************************************
void sjis_code_thrust_replase(unsigned char *sentence, const unsigned char code)
{
	int i;
	unsigned char rep_code[2];

	// 置換する文字列。(SJISで'*')
	rep_code[0] = 0x81;
	rep_code[1] = 0x96;

	// 文字列長が、1byte以下なら、処理必要なし。
	if ( strlen(sentence) <= 1 )
	{
		return;
	}


	// 置換対象文字 捜索
	for ( i=1; sentence[i] != '\0' ;i++ )
	{
		// code にヒット?
		if ( sentence[i] == code )
		{
			// 1byte前が、SJIS 1byte目の範囲?(0x81〜0x9F、0xE0〜〜0xFC)
			if ((( sentence[i-1] >= 0x81 ) && (sentence[i-1] <= 0x9F)) ||
				(( sentence[i-1] >= 0xE0 ) && (sentence[i-1] <= 0xFC))		)
			{

				debug_log_output("SJIS Replase HIT!!!!");

				// 置換実行
				sentence[i-1] = rep_code[0];
				sentence[i  ] = rep_code[1];
			}
		}
	}

	return;

}
Ejemplo n.º 19
0
off_t copy_descriptors(int in_fd, int out_fd, off_t content_length, JOINT_FILE_INFO_T *joint_file_info_p)
{
	int i;
	struct _buff {
		int inuse;
		int pos;
		int len;
		unsigned char *p;
	} *buff;
	unsigned char *p;
	int read_idx = 0;
	int write_idx = 0;
	int idx_count = 0;
	off_t read_cnt = 0;

	off_t			total_read_size = 0;
	size_t			target_read_size;
	int				len;

	int flag_finish = 0;
	int flag_first_time = 0;
	int flag_verbose = 0;
	time_t first_timeout = 0;
	off_t written = 0;
	
	struct timeb marker1,marker2; //,marker3;
	int marker_count;

	if(global_param.buffer_size < 1) global_param.buffer_size = 1;
	if(global_param.stream_chunk_size < 512) global_param.stream_chunk_size = 512;

	ssize_t blocks_read = 0;
	int offset = 0;
	if (joint_file_info_p) offset = joint_file_info_p->iso_seek;
	
	// ======================
	// 送信バッファを確保
	// ======================

	debug_log_output("Allocating %d buffers of %d bytes each\n", global_param.buffer_size, global_param.stream_chunk_size);

	buff = malloc(global_param.buffer_size * sizeof(struct _buff));
	if ( buff == NULL )
	{
		debug_log_output("malloc() error.\n");
		return (-1 );
	}
	p = malloc(global_param.buffer_size * global_param.stream_chunk_size);
	if ( p == NULL )
	{
		debug_log_output("malloc() error.\n");
		return ( 0 );
	}
	for (i=0; i<global_param.buffer_size; i++) {
		buff[i].pos = 0;
		buff[i].inuse = 0;
		buff[i].len = 0;
		buff[i].p = p + i*global_param.stream_chunk_size;
	}

	// ブロックモードの設定
	//set_blocking_mode(in_fd, 0);	/* blocking */
	set_blocking_mode(out_fd, (global_param.buffer_size>1));	/* non-blocking if multiple buffers */
	//debug_log_output("set non-blocking mode");

	// Do the calculation this way so global_param.buffer_size<4 always gets flag_first_time
	//No, don't force this!!!  :  if (content_length < global_param.stream_chunk_size * (global_param.buffer_size>>2)) flag_first_time = 1;
	if (global_param.buffer_size < 4) flag_first_time = 1;
	// If only one buffer, then we work the same as the http_simple_file_send()
	if (global_param.buffer_size == 1) global_param.flag_buffer_send_asap = 1;

	ftime(&marker1);
	marker_count = 0;

	first_timeout = time(NULL);
	// ================
	// 実体転送開始
	// ================
	while ( flag_finish < 2 )
	{
		struct timeval tv;
		fd_set writefds;

		if (flag_first_time == 0 && first_timeout + 13 <= time(NULL)) {
				debug_log_output( 
				   "****************************************************\n"
				   "**  Low bandwidth? send it anyway...              **\n"
				   "****************************************************");
				flag_first_time = 1;
		}
		if (flag_finish || flag_first_time || (idx_count >= (global_param.buffer_size-2))) 
		{
			if (flag_first_time == 0) {
				debug_log_output( 
				   "*********************************************************\n"
				   "**                    CACHE FILLED!                    **\n"
				   "*********************************************************");
				flag_first_time = 1;
			}
			while(buff[write_idx].inuse) {
				// If there is nothing more to read, concentrate on writing
				FD_ZERO(&writefds);
				FD_SET(out_fd, &writefds);
				tv.tv_sec = 0;
				if (flag_finish == 0 && !buff[read_idx].inuse) {
					// Don't wait for the select because we have room to read
					tv.tv_usec = 0;
				} else {
					tv.tv_usec = 100000; // 100msec maximum wait = 10Hz polling rate
				}
//ftime(&marker2);
				i = select(FD_SETSIZE, NULL, &writefds, NULL, &tv);
//ftime(&marker3);
//len = (marker3.time-marker2.time)*1000 + (marker3.millitm-marker2.millitm);
//if(len>9) fputc('0'+len/10, stderr);
				if (i < 0) {
					// Select returned an error - socket must be closed
					debug_log_output("select failed. err = %s", strerror(errno));
					flag_finish = 2;
					break;
				} else if(i > 0) {
//ftime(&marker2);
					len = write(out_fd, buff[write_idx].p + buff[write_idx].pos,
						(buff[write_idx].len < global_param.socket_chunk_size) ? buff[write_idx].len : global_param.socket_chunk_size );
//ftime(&marker3);
//i = (marker3.time-marker2.time)*1000 + (marker3.millitm-marker2.millitm);
//if(i>9) fputc('a'+i/10, stderr);
					if(len > 0) {
//fputc('.', stderr);
						written += len;
						buff[write_idx].len -= len;

						marker_count += len;
						if(!global_param.flag_daemon && (marker_count > 2000000)) {
							// Display the network transfer rate
							double rate;
							ftime(&marker2);
							rate = (marker2.time-marker1.time) + 0.001*(marker2.millitm-marker1.millitm);
							if(rate > 0) {
								rate = 8e-6 * marker_count / rate;
								/* fprintf(stderr, "%g Mbps\n", rate); */
							}
							marker1 = marker2;
							marker_count = 0;
						}

						if (flag_verbose) {
							debug_log_output("sent: len =%6d, idx = %4d, idxcount = %4d", len, write_idx, idx_count);
						} else if(0 && !global_param.flag_daemon) {
							show_progress(idx_count * 100 / global_param.buffer_size, idx_count);
						}
						if (buff[write_idx].len <= 0) {
							buff[write_idx].inuse = 0;
							buff[write_idx].len = 0;
							buff[write_idx].pos = 0;
							write_idx = (write_idx + 1) % global_param.buffer_size;
							idx_count --;
						} else {
							buff[write_idx].pos += len;
						}
					} else {
//fputc('-', stderr);
						// Failed to write - end the stream
						if (len < 0) {
							if(errno == EAGAIN) {
								debug_log_output("write would block");
								break;
							}
							debug_log_output("write failed after %d bytes. err = %s (%d)", written, strerror(errno), (int)errno);
						} else {
							debug_log_output("socket closed by player");
						}
						flag_finish = 2;
						break;
					}
				} else {
					// Not ready to write, exit from the loop to do a read
//if (flag_finish == 0 && !buff[read_idx].inuse) {
//	fputc(',', stderr);
//} else {
//	fputc('o', stderr);
//}
					break;
				}
			}
			if((flag_finish==1) && !buff[write_idx].inuse) {
				flag_finish = 2;
				debug_log_output(
				   "*********************************************************\n"
				   "**                    SEND FINISHED!                   **\n"
				   "*********************************************************");
			}
		}
		// Always attempt a read if we have a buffer available
		//if (FD_ISSET(in_fd, &readfds)) {
		if(flag_finish == 0 && !buff[read_idx].inuse) {
			// target_read_size = (content_length - total_read_size) > 1024 ? 1024 : (content_length - total_read_size);
			target_read_size = global_param.stream_chunk_size - buff[read_idx].len;
/*
			if (buff[read_idx].p == NULL) {
				debug_log_output("error! idx: %d", read_idx);
			}
*/
ftime(&marker2);
			if ((joint_file_info_p!=NULL) && (joint_file_info_p->dvd_file != NULL)) {
				blocks_read = DVDReadBlocks(joint_file_info_p->dvd_file, offset, target_read_size/2048, buff[read_idx].p + buff[read_idx].len); 
				len = (off_t)blocks_read*2048;
				offset += blocks_read;
			} else if (joint_file_info_p && read_cnt >= joint_file_info_p->file[joint_file_info_p->current_file_num].size) {
				len = 0;
				read_cnt = 0;
				debug_log_output("finished file chunk %d\n", joint_file_info_p->current_file_num);
				//printf("finished file chunk %d\n", joint_file_info_p->current_file_num);
			} else {
				if (joint_file_info_p && target_read_size + read_cnt > joint_file_info_p->file[joint_file_info_p->current_file_num].size) {
					target_read_size = joint_file_info_p->file[joint_file_info_p->current_file_num].size - read_cnt;
					debug_log_output("finishing last block of %d\n", joint_file_info_p->current_file_num);
					//printf("finishing last block of %d\n", joint_file_info_p->current_file_num);
				}

				len = read(in_fd, buff[read_idx].p + buff[read_idx].len, target_read_size);
				read_cnt += len;
			}
//ftime(&marker3);
//i = (marker3.time-marker2.time)*1000 + (marker3.millitm-marker2.millitm);
//if(i>9) fputc('A'+i/10, stderr);
			if(len == 0) {
				if(    (joint_file_info_p==NULL)
					|| (joint_file_info_p->dvd_file != NULL)
					|| next_file(&in_fd, joint_file_info_p)) {
					// 読み込み終わり
					flag_finish = 1;
					if (flag_verbose) {
						debug_log_output("recv: len = %d, idx = %d finish!", len, read_idx);
					} else {
						debug_log_output(
					   "*********************************************************\n"
					   "**                    RECV FINISHED!                   **\n"
					   "*********************************************************");
					}
					if (buff[read_idx].len > 0) {
						buff[read_idx].inuse = 1;
						buff[read_idx].pos = 0;
					}
				} else {
					// 次のファイルに続く(ここでは何もしない)
				}
			} else if (len > 0) {
//fputc(':', stderr);
				if (flag_verbose) {
					debug_log_output("recv: len =%6d, idx = %4d, idxcount = %4d", len, read_idx, idx_count);
				} else if(0 && !global_param.flag_daemon) {
					show_progress(idx_count * 100 / global_param.buffer_size, idx_count);
				}
				buff[read_idx].len += len;
				total_read_size += len;

				if (global_param.flag_buffer_send_asap == TRUE
				|| buff[read_idx].len >= global_param.stream_chunk_size) {
					buff[read_idx].inuse = 1;
					buff[read_idx].pos = 0;
					idx_count ++;
					read_idx = (read_idx + 1) % global_param.buffer_size;
				}
/*
				if (content_length - total_read_size <= 0) {
					flag_finish = 1;
				}
*/
			} else {
				flag_finish = 1;
				if (flag_verbose) {
					debug_log_output("read err?: len = %d, idx = %d, err: %s", len, read_idx, strerror(errno));
				} else {
					debug_log_output(
				   "*********************************************************\n"
				   "**                    RECV FINISHED!(ret = %d)          **\n"
				   "*********************************************************", len);
				}
			}
		}
	}

	free(p);
	free(buff);	// Memory Free.
	debug_log_output("copy descriptors end.");

	// 正常終了
	return written;
}
Ejemplo n.º 20
0
// **************************************************************************
// HTTPヘッダを受信して解析する。
//
// 処理するのはGETのみ。GET以外のメソッドが来たらエラー
// 今のところ、URIとuser_agent、Range、Hostを解析。
// URIは、URIデコードもやる。
//
//	return: 0 		正常終了
//	return: 0以外 	エラー
// **************************************************************************
static int http_header_receive(int accept_socket, HTTP_RECV_INFO *http_recv_info_p)
{
	int result = 0;
	int	recv_len;
	unsigned char	line_buf[1024];	// 大きめに。
	unsigned char 	work_buf[1024];
	unsigned char 	work_buf2[1024];
	unsigned char 	split1[1024];
	unsigned char 	split2[1024];

	int		ret;
	int		i;
	int		j;

	// ================================
	// 1行づつ HTTPヘッダを受信
	// ================================
	for (i=0;;i++)
	{
		// 1行受信 実行。
		memset(line_buf, '\0', sizeof(line_buf));
		recv_len = line_receive(accept_socket, line_buf, sizeof(line_buf));

		// debug. 受信したヘッダ表示
		debug_log_output("'%s'(%d byte)\n", line_buf, recv_len );

		// 受信した内容をチェック。
		if ( i != 0 && recv_len == 0 ) // 空行検知。ヘッダ受信終了。
		{
			break;
		}
		else if ( recv_len < 0 ) // 受信失敗
		{
			return ( -1 );
		}

		// --------------------------
		// GETメッセージチェック
		// --------------------------
		if ( i == 0 ) // 1行目のみチェック
		{
			debug_log_output("URI Check start.'%s'\n", line_buf);

			// GET/POSTある?
			if (strncmp(line_buf, "GET ", 4) && strncmp(line_buf, "POST ", 5))
			{
				debug_log_output("'GET' or 'POST' not found. error.");
				return ( -1 );
			}
			strncpy(http_recv_info_p->request_method, line_buf, sizeof(http_recv_info_p->request_method));
			cut_after_character(http_recv_info_p->request_method, ' ');

			// 最初のスペースまでを削除。
			cut_before_character(line_buf, ' ');

			// 次にスペースが出てきたところの後ろまでを削除。
			cut_after_character(line_buf, ' ');

			// ===========================
			// GETオプション部解析
			// ===========================

			// REQUEST_URI用・Proxy用に値を保存
			strncpy(http_recv_info_p->request_uri, line_buf, sizeof(http_recv_info_p->request_uri));

			// '?'が存在するかチェック。
			if ( strchr(line_buf, '?') != NULL )
			{

				strncpy(work_buf, line_buf, sizeof(work_buf));

				// '?'より前をカット
				cut_before_character(work_buf, '?' );
				debug_log_output("work_buf = '%s'", work_buf );

				while ( 1 )
				{
					memset(split1, '\0', sizeof(split1));
					memset(split2, '\0', sizeof(split2));

					uri_decode(split1, sizeof(split1), work_buf, sizeof(work_buf) );
					strcpy(work_buf, split1);

					// 最初に登場する'&'で分割
					ret = sentence_split(work_buf, '&', split1, split2 );
					if ( ret == 0 ) // 分割成功
					{
						strncpy(work_buf, split2, sizeof(work_buf));
					}
					else if (strlen(work_buf) > 0) // まだwork_bufに中身ある?
					{
						strncpy( split1, work_buf, sizeof(split1));
						strncpy( work_buf, "", sizeof(work_buf));
					}
					else // 処理終了
					{
						break;
					}

					// -------------------------------------
					// GETした内容 解析開始
					// 超安直。いいのかこんな比較で。
					// -------------------------------------

					// URIデコード
					// uri_decode(work_buf2, sizeof(work_buf2), split1, sizeof(split1) );
					strcpy(work_buf2, split1);

					// "page="あるか調査。
					if (strncasecmp( work_buf2, "page=", strlen("page=") ) == 0 )
					{
						// = より前を削除
						cut_before_character(work_buf2, '=');
						if ( strlen(work_buf2) > 0 )
						{
							// 構造体に値を保存。
							http_recv_info_p->page = atoi(work_buf2);
						}

						continue;
					}

					// "menupage="あるか調査。
					if (strncasecmp( work_buf2, "menupage=", strlen("menupage=") ) == 0 )
					{
						// = より前を削除
						cut_before_character(work_buf2, '=');
						if ( strlen(work_buf2) > 0 )
						{
							// 構造体に値を保存。
							http_recv_info_p->menupage = atoi(work_buf2);
						}

						continue;
					}

					// "title=" DVD title selection
					if (strncasecmp( work_buf2, "title=", strlen("title=") ) == 0 )
					{
						// = より前を削除
						cut_before_character(work_buf2, '=');
						if ( strlen(work_buf2) > 0 )
						{
							// 構造体に値を保存。
							http_recv_info_p->title = atoi(work_buf2);
						}

						continue;
					}

					if (strncasecmp( work_buf2, "width=", strlen("width=") ) == 0 )
					{
						// = より前を削除
						cut_before_character(work_buf2, '=');
						if ( strlen(work_buf2) > 0 )
						{
							// 構造体に値を保存。
							global_param.target_jpeg_width = atoi(work_buf2);
						}

						continue;
					}

					if (strncasecmp( work_buf2, "height=", strlen("height=") ) == 0 )
					{
						// = より前を削除
						cut_before_character(work_buf2, '=');
						if ( strlen(work_buf2) > 0 )
						{
							// 構造体に値を保存。
							global_param.target_jpeg_height = atoi(work_buf2);
						}

						continue;
					}

					// "action="あるか調査。
					if (strncasecmp( work_buf2, "action=", strlen("action=") ) == 0 )
					{
						// = より前を削除
						cut_before_character(work_buf2, '=');

						// 構造体に値を保存。
						strncpy(http_recv_info_p->action, work_buf2, sizeof(http_recv_info_p->action));
						continue;
					}

					// "type=" allplay list type
					if (strncasecmp( work_buf2, "type=movie", strlen("type=movie") ) == 0 )
					{
						http_recv_info_p->default_file_type = TYPE_MOVIE;
						continue;
					}
					if (strncasecmp( work_buf2, "type=music", strlen("type=music") ) == 0 )
					{
						http_recv_info_p->default_file_type = TYPE_MUSIC;
						continue;
					}
					if (strncasecmp( work_buf2, "type=photo", strlen("type=photo") ) == 0 )
					{
						http_recv_info_p->default_file_type = TYPE_JPEG;
						continue;
					}
					if (strncasecmp( work_buf2, "type=soundtrack", strlen("type=soundtrack") ) == 0 )
					{
						http_recv_info_p->default_file_type = TYPE_MUSICLIST;
						continue;
					}
					if (strncasecmp( work_buf2, "type=slideshow", strlen("type=slideshow") ) == 0 )
					{
						http_recv_info_p->default_file_type = TYPE_PLAYLIST;
						continue;
					}
					
					// "option="あるか調査
					if (strncasecmp( work_buf2, "option=", strlen("option=") ) == 0 )
					{
						// = より前を削除
						cut_before_character(work_buf2, '=');

						// 構造体に値を保存。
						strncpy(http_recv_info_p->option, work_buf2, sizeof(http_recv_info_p->option));
						continue;
					}

					// "alias="あるか調査
					if (strncasecmp( work_buf2, "alias=", strlen("alias=") ) == 0 )
					{
						// = より前を削除
						cut_before_character(work_buf2, '=');

						// 構造体に値を保存。
						strncpy(http_recv_info_p->alias, work_buf2, sizeof(http_recv_info_p->alias));

						if (strncasecmp(http_recv_info_p->alias, "movie", strlen("movie")) == 0)
							http_recv_info_p->default_file_type = TYPE_MOVIE;
						else if (strncasecmp(http_recv_info_p->alias, "music", strlen("music")) == 0)
							http_recv_info_p->default_file_type = TYPE_MUSIC;
						else if (strncasecmp(http_recv_info_p->alias, "photo", strlen("photo")) == 0)
							http_recv_info_p->default_file_type = TYPE_JPEG;
						else
							http_recv_info_p->default_file_type = TYPE_UNKNOWN;

						continue;
					}

					if (strncasecmp( work_buf2, "lsearch=", strlen("lsearch=") ) == 0 )
					{
						cut_before_character(work_buf2, '=');

						strcpy(http_recv_info_p->lsearch, work_buf2);
						strcpy(http_recv_info_p->recv_uri, work_buf2);
						continue;
					}

					// "search=
					if (strncasecmp( work_buf2, "search", strlen("search") ) == 0 )
					{
						if (strncasecmp(work_buf2, "search_movie", strlen("search_movie")) == 0) {
							http_recv_info_p->search_type = TYPE_MOVIE;
							strcpy(http_recv_info_p->search_str, "_movie");
							http_recv_info_p->default_file_type = TYPE_MOVIE;
							// printf("search movie for ");
						} else if (strncasecmp(work_buf2, "search_music", strlen("search_music")) == 0) {
							http_recv_info_p->search_type = TYPE_MUSIC;
							strcpy(http_recv_info_p->search_str, "_music");
							http_recv_info_p->default_file_type = TYPE_MUSIC;
							// printf("search music for ");
						} else if (strncasecmp(work_buf2, "search_photo", strlen("search_photo")) == 0) {
							http_recv_info_p->search_type = TYPE_JPEG;
							strcpy(http_recv_info_p->search_str, "_photo");
							http_recv_info_p->default_file_type = TYPE_JPEG;
							// printf("search photo for ");
						} else if (strncasecmp(work_buf2, "search_all", strlen("search_all")) == 0) {
							http_recv_info_p->search_type = TYPE_UNKNOWN;
							strcpy(http_recv_info_p->search_str, "_all");
							http_recv_info_p->default_file_type = TYPE_UNKNOWN;
							// printf("search all for ");
						} else
							continue;

						cut_before_character(work_buf2, '=');

						strncpy(http_recv_info_p->search, work_buf2, sizeof(http_recv_info_p->search));
						if (http_recv_info_p->search[0] == '\0')
							// everything qualifies
							strcpy(http_recv_info_p->search, ".*");

						// printf("%s\n", http_recv_info_p->search);
						continue;
					}

					// "sort="あるか調査
					if (strncasecmp( work_buf2, "sort=", strlen("sort=") ) == 0 )
					{
						// = より前を削除
						cut_before_character(work_buf2, '=');

						// 構造体に値を保存。
						strncpy(http_recv_info_p->sort, work_buf2, sizeof(http_recv_info_p->sort));
						continue;
					}


					// "dvdopt="あるか調査
					if (strncasecmp( work_buf2, "dvdopt=", strlen("dvdopt=") ) == 0 )
					{
						// = より前を削除
						cut_before_character(work_buf2, '=');

						// 構造体に値を保存。
						strncpy(http_recv_info_p->dvdopt, work_buf2, sizeof(http_recv_info_p->dvdopt));
						continue;
					}

					// "focus="あるか調査
					if (strncasecmp( work_buf2, "focus=", strlen("focus=") ) == 0 )
					{
						// = より前を削除
						cut_before_character(work_buf2, '=');

						// 構造体に値を保存。
						strncpy(http_recv_info_p->focus, work_buf2, sizeof(http_recv_info_p->focus));
						continue;
					}




				}
			}

			debug_log_output("http_recv_info_p->page = '%d'", http_recv_info_p->page);
			debug_log_output("http_recv_info_p->title = '%d'", http_recv_info_p->title);
			debug_log_output("http_recv_info_p->action = '%s'", http_recv_info_p->action);
			debug_log_output("http_recv_info_p->option = '%s'", http_recv_info_p->option);
			debug_log_output("http_recv_info_p->dvdopt = '%s'", http_recv_info_p->dvdopt);

			// URIデコード
			cut_after_character(line_buf, '?');
			uri_decode(work_buf, sizeof(work_buf), line_buf, sizeof(line_buf) );
			strncpy(line_buf, work_buf, sizeof(line_buf));
			debug_log_output("URI(decoded):'%s'\n", line_buf);

			convert_language_code(line_buf, work_buf, sizeof(work_buf), CODE_AUTO, CODE_EUC);
			debug_log_output("URI(decoded,euc,FYI):'%s'\n", work_buf);


			// 構造体に保存
			if (http_recv_info_p->lsearch[0] == '\0')
				strncpy(http_recv_info_p->recv_uri, line_buf, sizeof(http_recv_info_p->recv_uri));

			continue;

		}

		// User-agent切り出し
		if ( strncasecmp(line_buf, HTTP_USER_AGENT, strlen(HTTP_USER_AGENT) ) == 0 )
		{
			// ':'より前を切る
			cut_before_character(line_buf, ':');
			cut_first_character(line_buf, ' ');

			// 構造体に保存
			strncpy( http_recv_info_p->user_agent, line_buf, sizeof(http_recv_info_p->user_agent));

			// Set the skin name based on user agent, if desired
			for(j=0; j<global_param.alternate_skin_count; j++) {
				debug_log_output("Checking for '%s'", global_param.alternate_skin_match[j]);
				if(strstr(line_buf, global_param.alternate_skin_match[j]) != NULL) {
					strcpy(global_param.skin_name, global_param.alternate_skin_name[j]);
					debug_log_output("User agent matches alternate skin '%s'", global_param.skin_name); 
					break;
				}
			}
			continue;
		}

		// Rangeあるかチェック
		if ( strncasecmp(line_buf, HTTP_RANGE,	strlen(HTTP_RANGE) ) == 0 )
		{
			debug_log_output("%s Detect.\n", HTTP_RANGE);
			// ':' より前を切る。
			cut_before_character(line_buf, ':');
			cut_first_character(line_buf, ' ');

			// recv_range にRangeの中身保存
			strncpy(http_recv_info_p->recv_range, line_buf, sizeof(http_recv_info_p->recv_range));

			// '=' より前を切る
			cut_before_character(line_buf, '=');


			// '-'で前後に分割。
			sentence_split(line_buf, '-', work_buf, work_buf2);

			debug_log_output("work_buf='%s'\n", work_buf);
			debug_log_output("work_buf2='%s'\n", work_buf2);

			// 値を文字列→数値変換
			http_recv_info_p->range_start_pos  = strtoull(work_buf, NULL, 10);

			if ( strlen(work_buf2) > 0 )
			{
				http_recv_info_p->range_end_pos = strtoull(work_buf2, NULL, 10);
			}


			debug_log_output("range_start_pos=%d\n", http_recv_info_p->range_start_pos);
			debug_log_output("range_end_pos=%d\n", http_recv_info_p->range_end_pos);

			continue;
		}

		// Hostあるかチェック
		if ( strncasecmp(line_buf, HTTP_HOST,	strlen(HTTP_HOST) ) == 0 )
		{
			debug_log_output("%s Detect.\n", HTTP_HOST);
			// ':' より前を切る。
			cut_before_character(line_buf, ':');
			cut_first_character(line_buf, ' ');

			strncpy(http_recv_info_p->recv_host, line_buf, sizeof(http_recv_info_p->recv_host));
			if(NULL == strchr(http_recv_info_p->recv_host, ':')) {
				debug_log_output("CLIENT BUG: Host header field was missing port number - fixing");
				snprintf(http_recv_info_p->recv_host + strlen(http_recv_info_p->recv_host), sizeof(http_recv_info_p->recv_host)-1, ":%d", global_param.server_port);
				debug_log_output("%s '%s'", HTTP_HOST, http_recv_info_p->recv_host);
			}

			continue;
		}

		if (strncasecmp(line_buf, HTTP_AUTHORIZATION, strlen(HTTP_AUTHORIZATION)) == 0) {
			debug_log_output("%s Detect.\n", HTTP_AUTHORIZATION);
			// ':' より前を切る。
			cut_before_character(line_buf, ':');
			cut_first_character(line_buf, ' ');
			if (strncmp(line_buf, "Basic ", 6)) {
				debug_log_output("received '%s', is not supported.", line_buf);
				continue;
			}

			strncpy(http_recv_info_p->passwd, line_buf + 6, sizeof(http_recv_info_p->passwd));

			continue;
		}

		// Content-Lengthあるかチェック
		if ( strncasecmp(line_buf, HTTP_CONTENT_LENGTH_STR,	strlen(HTTP_CONTENT_LENGTH_STR) ) == 0 )
		{
			debug_log_output("%s Detect.\n", HTTP_CONTENT_LENGTH_STR);
			// ':' より前を切る。
			cut_before_character(line_buf, ':');
			cut_first_character(line_buf, ' ');
			/* recv_content_length は わざと long です. */
			http_recv_info_p->recv_content_length = strtol(line_buf, NULL, 10);
			debug_log_output("Content-Length: %ld", http_recv_info_p->recv_content_length);
			continue;
		}

	}

	return result;
}
Ejemplo n.º 21
0
// **************************************************************************
// * サーバ HTTP処理部
// **************************************************************************
void 	server_http_process(int accept_socket)
{
	int					result;
	HTTP_RECV_INFO	http_recv_info;	//HTTP受信情報保存構造体
	int				i;
	int				flag_allow_user_agent_check;
	int				found;

	memset(&http_recv_info, 0, sizeof(http_recv_info));


	// ----------------------------------------
	// HTTP リクエストヘッダ受信
	// ----------------------------------------
	debug_log_output("HTTP Header receive start!\n");

	result = http_header_receive(accept_socket,  &http_recv_info);
	if ( result != 0 ) // エラーチェック
	{
		// エラーメッセージ
		debug_log_output("http_header_receive() Error. result=%d\n", result);
		// ソケットクローズ
		close(accept_socket);
		return;
	}
	debug_log_output("HTTP Header receive end!\n");

	debug_log_output("recv_uri:'%s'\n", http_recv_info.recv_uri);
	debug_log_output("user_agent:'%s'\n", http_recv_info.user_agent);

	debug_log_output("range_start_pos=%lld\n", http_recv_info.range_start_pos);
	debug_log_output("range_end_pos=%lld\n", http_recv_info.range_end_pos);

	if (http_recv_info.passwd[0]) {
		debug_log_output("http passwd:'%s'\n", http_recv_info.passwd);
	}

	// ==========================
	// = User-Agent チェック
	// ==========================

	flag_allow_user_agent_check = 0;

	if ( strlen(allow_user_agent[0].user_agent)  == 0 ) // User-Agnet指示が無し。
	{
		debug_log_output("user_agent: allow_user_agent No List. All Allow.");
		flag_allow_user_agent_check = 1; // OK
	}
	else
	{
		// User-Agent チェック実行
		for ( i=0; i<ALLOW_USER_AGENT_LIST_MAX; i++)
		{
			if ( strlen(allow_user_agent[i].user_agent)  == 0 )
			{
				break;
			}

			// 一致チェック
			debug_log_output("user_agent: Check[%d] '%s' in '%s'",i, allow_user_agent[i].user_agent, http_recv_info.user_agent);
			if ( strstr( http_recv_info.user_agent, allow_user_agent[i].user_agent ) != NULL )
			{
				debug_log_output("user_agent: '%s' OK.", allow_user_agent[i].user_agent );
				flag_allow_user_agent_check = 1; // 一致。OK
				break;
			}
		}
	}

	if (global_param.http_passwd[0] && !flag_allow_user_agent_check) {
		// パスワードが設定されて、正しければ、User-AgentチェックNGでもOK.
		char *pass, *p;

		pass = base64(global_param.http_passwd);
		if ((p = strchr(pass, '=')) != NULL) {
			*p = '\0';
		}
		if ((p = strchr(http_recv_info.passwd, '=')) != NULL) {
			*p = '\0';
		}

		if (!strcmp(pass, http_recv_info.passwd)) {
			// 一致
			flag_allow_user_agent_check = 1;
		} else {
			// 不一致
			// flag_allow_user_agent_check = 0;

			http_unauthorized_response(accept_socket, &http_recv_info);
			close(accept_socket);
			return ;
		}
	}

	// User-Agentチェック NGならば、ソケットクローズ。終了。
	if ( flag_allow_user_agent_check == 0 )
	{
		debug_log_output("allow_user_agent check. Deny. Socket close.");

		// ソケットクローズ
		close(accept_socket);
		return;
	}

	// クライアントがPCかどうか判断
	http_recv_info.flag_pc = (global_param.user_agent_pc[0]
		&& !strncmp(http_recv_info.user_agent, global_param.user_agent_pc
			, strlen(global_param.user_agent_pc))
	) ? 1 : 0;

	if(global_param.user_agent_pc[0]) {
		debug_log_output("Checking for PC user agent '%s'", global_param.user_agent_pc);
	}
	debug_log_output("flag_pc: %d", http_recv_info.flag_pc);

	// User-Agent
	// HD: 'Syabas/13-14-060414-04-IOD-234-000/04-IOD (uCOS-II v2.05;NOS;KA9Q; Res1280x720-HiColor; TV Res1920x1080; Browser Res1104x656-8bits; www.syabas.com mac_addr=00.a0.b0.65.51.31)'(186 byte)
	// SD: 'Syabas/13-14-060414-04-IOD-234-000/04-IOD (uCOS-II v2.05;NOS;KA9Q; Res624x416-HiColor; TV Res1920x1080; Browser Res624x416-8bits; www.syabas.com mac_addr=00.a0.b0.65.51.31)'

	http_recv_info.flag_hd = (strstr(http_recv_info.user_agent, "Res624x416") == NULL);

	if (!strncmp(http_recv_info.recv_uri, "/-.-", 4)) {
		// proxy
		if (http_proxy_response(accept_socket, &http_recv_info) < 0) {
			http_not_found_response(accept_socket, &http_recv_info);
		}

		// ソケットクローズ
		close(accept_socket);
		return;
	}

	if (path_sanitize(http_recv_info.recv_uri, sizeof(http_recv_info.recv_uri)) == NULL) {
		// BAD REQUEST!
		debug_log_output("BAD REQUEST!");
		http_not_found_response(accept_socket, &http_recv_info);
		close(accept_socket);
		return;
	}
	debug_log_output("sanitized recv_uri: %s", http_recv_info.recv_uri);

	// ----------------------------------------
	// 受け取ったURIの拡張子がrename対象ならばrename
	// ----------------------------------------
	extension_del_rename(http_recv_info.recv_uri, sizeof(http_recv_info.recv_uri));

	// ============================
	// ファイルチェック
	//  種類に応じて分岐
	// ============================
	result = http_file_check(&http_recv_info);
	debug_log_output("http_file_check returns %d\n", result);

	if (result != CGI_TYPE && !strcmp(http_recv_info.request_method, "POST")) {
		debug_log_output("BAD POST REQUEST.");
		http_not_found_response(accept_socket, &http_recv_info);
	}
	else if (result == -2) { // Directory without the trailing slash -> redirect
		char buffer[WIZD_FILENAME_MAX];
		sprintf(buffer, "%s/", http_recv_info.recv_uri);
		http_redirect_response(accept_socket, &http_recv_info, buffer);
	}
	else if ( result < 0 ) // File not found
	{
		http_not_found_response(accept_socket, &http_recv_info);
	}
	else if ( result == GENERAL_FILE_TYPE ) // ファイル実体ならば、実体転送。
	{
		if ( global_param.flag_allow_delete && (strcasecmp(http_recv_info.action, "delete" ) == 0) )
		{
			// ----------------------------------------
			// Delete file
			// ----------------------------------------
			char path[WIZD_FILENAME_MAX];

			debug_log_output("Delete file start!\n");
			debug_log_output("unlink(%s)", http_recv_info.send_filename);
			unlink(http_recv_info.send_filename);
			// Remove any associated bookmarks if they exist
			snprintf(path, sizeof(path), "%s.wizd.bookmark", http_recv_info.send_filename);
			unlink(path);

			// Redirect to directory
			strncpy(path, http_recv_info.recv_uri, sizeof(path));
			cut_after_last_character(path, '/');
			strcat(path, "/");
			http_redirect_response(accept_socket, &http_recv_info, path);
			debug_log_output("Delete file end!\n");
		} else
		// actionに、ImageViewerが指示されている?
		if ( strcasecmp(http_recv_info.action, "ImageView" ) == 0)
		{
			// ----------------------------------------
			// イメージファイルビューアー
			// ----------------------------------------
			debug_log_output("Image Viewer start!\n");
			http_image_viewer(accept_socket, &http_recv_info);
			debug_log_output("Image Viewer end!\n");
		}
		// actionに、SinglePlayが指示されている?
		else if ( strcasecmp(http_recv_info.action, "SinglePlay" ) == 0)
		{
			// ----------------------------------------
			// Musicファイル 単独プレイ
			// ----------------------------------------
			debug_log_output("Single Play start!\n");
			http_music_single_play(accept_socket, &http_recv_info);
			debug_log_output("Single Play end!\n");
		}
#ifdef RESIZE_JPEG
		// actionに、Resizeが指示されている?
		else if ( strcasecmp(http_recv_info.action, "Resize.jpg" ) == 0)
		{
			// ----------------------------------------
			// JPEG Resize
			// ----------------------------------------
			debug_log_output("JPEG Resize start!\n");
			if(http_send_resized_jpeg(accept_socket, &http_recv_info) == 0) {
				// Failed to resize - send the original file as-is
				// (this can happen if we have the wrong file extension)
				http_file_response(accept_socket, &http_recv_info);
			}
			debug_log_output("JPEG Resize end!\n");
		}
#endif
		else if (strcmp(http_recv_info.option, "aviinfo") == 0)
		{
			debug_log_output("got aviinfo option\n");
			http_menu(accept_socket, &http_recv_info);
		}
		else if (strcmp(http_recv_info.option, "mp3info") == 0)
		{
			http_menu(accept_socket, &http_recv_info);
		}
		else // アクションに指定無し。
		{
			// ----------------------------------------
			// ファイルの実体
			// HTTPリクエストヘッダに従ってデータを返信。
			// ----------------------------------------
			found = 0;
			if (global_param.flag_use_index && strstr(http_recv_info.recv_uri, "wizd") != 0 && strstr(http_recv_info.recv_uri, ".htm") != 0) {
				if (http_find_and_replace_html(accept_socket, &http_recv_info)) {
					found = 1;
				}
			}

			if (!found) {
				debug_log_output("HTTP response start!\n");
				http_file_response(accept_socket, &http_recv_info);
				debug_log_output("HTTP response end!\n");
			}
		}

	}
	else if ( result == SVI_TYPE )
	{
		// ----------------------------------------
		// SVIファイル(;´Д`)
		// SVIファイル処理してデータを返信
		// ----------------------------------------

		// actionに、SinglePlayが指示されている?
		if ( strcasecmp(http_recv_info.action, "SinglePlay" ) == 0)
		{
			// ----------------------------------------
			// Musicファイル 単独プレイ
			// ----------------------------------------
			debug_log_output("Single Play start!(SVI)\n");
			http_music_single_play(accept_socket, &http_recv_info);
			debug_log_output("Single Play end!(SVI)\n");
		}
		else // アクションに指定無し。
		{
			debug_log_output("HTTP joint file response start!\n");
			http_joint_file_response(accept_socket, &http_recv_info);
			debug_log_output("HTTP joint file response end!\n");
		}
	}
	else if ( result == PLW_UPL_TYPE )
	{
		// ---------------------------------------------
		// plw/uplファイル(`・ω・´)
		// リストファイルから、プレイリスト生成して返信
		// ---------------------------------------------
		debug_log_output("HTTP wizd play list create and response start!\n");
		http_listfile_to_playlist_create(accept_socket, &http_recv_info);
		debug_log_output("HTTP wizd play list create and response end!\n");
	}
	else if ( result == VOB_TYPE )
	{
		// ---------------------------------------------
		// vobファイル 連結
		// vobを連結して返信
		// ---------------------------------------------

		// actionに、SinglePlayが指示されている?
		if ( strcasecmp(http_recv_info.action, "SinglePlay" ) == 0)
		{
			// ----------------------------------------
			// Musicファイル 単独プレイ
			// ----------------------------------------
			debug_log_output("Single Play start!(VOB)\n");
			http_music_single_play(accept_socket, &http_recv_info);
			debug_log_output("Single Play end!(VOB)\n");
		}
		else // アクションに指定無し。
		{
			debug_log_output("HTTP vob file response start!\n");
			http_vob_file_response(accept_socket, &http_recv_info);
			debug_log_output("HTTP vob file response end!\n");
		}
	}
	else if ( result == CGI_TYPE )
	{
		// ---------------------------------------------
		// cgiファイル
		// cgiを実行して結果を返信
		// ---------------------------------------------
		debug_log_output("HTTP CGI response start!\n");
		http_cgi_response(accept_socket, &http_recv_info);
		debug_log_output("HTTP CGI response end!\n");
	}
	else if ( result == ISO_TYPE )
	{ // ISO file handling
		if ( (strcasecmp(http_recv_info.action, "IsoPlay" ) == 0) ||
			(strcasecmp(http_recv_info.action, "dvdplay" ) == 0) ||
			(strncmp(http_recv_info.action, "showchapters", 12 ) == 0))
		{
			debug_log_output("ISO playlist create start!\n");
			http_menu(accept_socket, &http_recv_info);
			debug_log_output("ISO playlist create end!\n");
		}
		else
		{
			// Start to stream the VOB
			debug_log_output("HTTP ISO file response start!\n");
			http_vob_file_response(accept_socket, &http_recv_info);
			debug_log_output("HTTP ISO file response end!\n");
		}
	}
	else
	{
		// ----------------------------------------
		// ディレクトリ
		// ----------------------------------------

		// actionに、OptionMenuが指示されている?
		if ( strcasecmp(http_recv_info.action, "OptionMenu" ) == 0)
		{
			debug_log_output("HTTP Option menu create.\n");
			http_option_menu(accept_socket, &http_recv_info);
			debug_log_output("HTTP Option menu end.\n");
		}
		else if ( strcasecmp(http_recv_info.action, "copy" ) == 0)
		{
			// --------------------------------------------
			// Copy the default playlist to this directory
			// --------------------------------------------
			char source[WIZD_FILENAME_MAX];
			char dest[WIZD_FILENAME_MAX];
			int fd_source, fd_dest;

			if(http_recv_info.default_file_type == TYPE_MUSICLIST) {
				snprintf(dest, sizeof(dest), "%s/%s", http_recv_info.send_filename, DEFAULT_MUSICLIST);
				snprintf(source, sizeof(source), "%s/%s/%s", global_param.skin_root, global_param.skin_name, DEFAULT_MUSICLIST);
			} else {
				snprintf(dest, sizeof(dest), "%s/%s", http_recv_info.send_filename, DEFAULT_PHOTOLIST);
				snprintf(source, sizeof(source), "%s/%s/%s", global_param.skin_root, global_param.skin_name, DEFAULT_PHOTOLIST);
			}
			duplex_character_to_unique(source, '/');
			duplex_character_to_unique(dest, '/');

			debug_log_output("Copying '%s' to '%s'", source, dest);

			// Copy the file
			fd_source = open(source, O_RDONLY);
			if(fd_source >= 0) {
				fd_dest = open(dest, O_CREAT | O_TRUNC | O_WRONLY, S_IREAD | S_IWRITE);
				if(fd_dest >= 0) {
					while( (i = read(fd_source, source, sizeof(source))) > 0 ) {
						write(fd_dest, source, i);
					}
					close(fd_dest);
				} else {
					debug_log_output("Failed to open destination file");
				}
				close(fd_source);
			} else {
				debug_log_output("Failed to open source file");
			}
			
			// Redirect to the directory
			strncpy(dest, http_recv_info.recv_uri, sizeof(dest));
			cut_after_last_character(dest, '/');
			strcat(dest, "/");
			http_redirect_response(accept_socket, &http_recv_info, dest);
			debug_log_output("Copy playlist end!\n");
		}
		else	// DIRECTORY_TYPE or {wizd,index}.htm{l}
		{
			int	found = 0;

			if (global_param.flag_use_index) {
				if (http_find_and_replace(accept_socket, &http_recv_info))
					found = 1;
			}

			if (!found) {
				debug_log_output("HTTP file menu create.\n");
				http_menu(accept_socket, &http_recv_info);
				debug_log_output("HTTP file menu end.\n");
			}
		}
	}

	// Clean shutdown
	shutdown(accept_socket, SHUT_WR);
 
	for(i=0; i<1 && (read(accept_socket, &result, sizeof(result))>0); i++);



	// ソケットクローズ
	close(accept_socket);

	return;
}
Ejemplo n.º 22
0
// **************************************************************************
// JOINTファイルを、連結して返信する。
// **************************************************************************
int http_joint_file_response(int accept_socket, HTTP_RECV_INFO *http_recv_info_p  )
{
	int	send_header_data_len;
	int	result_len;

	unsigned char	send_http_header_buf[2048];
	unsigned char	work_buf[1024];

	off_t		joint_content_length = 0;

	JOINT_FILE_INFO_T *joint_file_info_p;

	int	ret;
	int	i;


	debug_log_output("---------------------------------------------------");
	debug_log_output("http_joint_file_response() start" );

	// -----------------------
	// 作業用変数初期化
	// -----------------------
	memset(send_http_header_buf, '\0', sizeof(send_http_header_buf) );

	// -----------------------
	// ワーク領域確保
	// -----------------------
	joint_file_info_p = malloc( sizeof(JOINT_FILE_INFO_T) );
	if ( joint_file_info_p == NULL )
	{
		debug_log_output("malloc() error.");
		return ( -1 );
	}


	// --------------------------
	// SVIファイル情報をGET
	// --------------------------
	ret = analyze_svi_file(http_recv_info_p->send_filename, joint_file_info_p );
	debug_log_output("http_joint_file_response() end (ret=%d)" );
	if ( ret >= 0 )
	{
		debug_log_output("joint_file_info.file_num = %d", joint_file_info_p->file_num);
		debug_log_output("joint_file_info.total_size = %d", joint_file_info_p->total_size);
		for ( i = 0; i< joint_file_info_p->file_num; i++ )
		{
			debug_log_output("[%02d] '%s' %d\n", i, joint_file_info_p->file[i].name, joint_file_info_p->file[i].size );
		}

		// 送信するcontnet_length 計算
		if ( http_recv_info_p->range_end_pos > 0 )
		{
			joint_content_length = (http_recv_info_p->range_end_pos - http_recv_info_p->range_start_pos) + 1;
		}
		else
		{
			joint_content_length = joint_file_info_p->total_size - http_recv_info_p->range_start_pos;
		}
	}


	// -------------------------
	// HTTP_OK ヘッダ生成
	// -------------------------
	strncpy(send_http_header_buf, HTTP_OK, sizeof(send_http_header_buf));
	strncat(send_http_header_buf, HTTP_CONNECTION, sizeof(send_http_header_buf) - strlen(send_http_header_buf) );

	snprintf(work_buf, sizeof(work_buf), HTTP_SERVER_NAME, SERVER_NAME);
	strncat(send_http_header_buf, work_buf, sizeof(send_http_header_buf) - strlen(send_http_header_buf) );

	snprintf(work_buf, sizeof(work_buf), HTTP_CONTENT_LENGTH, joint_content_length);
	strncat(send_http_header_buf, work_buf, sizeof(send_http_header_buf) - strlen(send_http_header_buf) );

	snprintf(work_buf, sizeof(work_buf), HTTP_CONTENT_TYPE, http_recv_info_p->mime_type);
	strncat(send_http_header_buf, work_buf, sizeof(send_http_header_buf) - strlen(send_http_header_buf) );
	strncat(send_http_header_buf, HTTP_END, sizeof(send_http_header_buf) - strlen(send_http_header_buf) );



	send_header_data_len = strlen(send_http_header_buf);
	debug_log_output("send_header_data_len = %d\n", send_header_data_len);
	debug_log_output("--------\n");
	debug_log_output("%s", send_http_header_buf);
	debug_log_output("--------\n");


	// --------------
	// ヘッダ返信
	// --------------
	result_len = send(accept_socket, send_http_header_buf, send_header_data_len, 0);
	debug_log_output("result_len=%d, send_header_data_len=%d\n", result_len, send_header_data_len);


	// --------------
	// 実体返信
	// --------------
	http_joint_file_send(	accept_socket, 	joint_file_info_p,
											joint_content_length,
											http_recv_info_p->range_start_pos );


	free( joint_file_info_p );	// Memory Free.

	return 0;
}
Ejemplo n.º 23
0
off_t copy_FILE_to_descriptor(FILE *in_fp, int out_fd, off_t content_length)
{
	unsigned char *p;

	int		n;
	int		len;
	int		count;
	int		buflen;

	off_t	written = 0;
	off_t	remain = content_length;
	
	if(global_param.stream_chunk_size < 512) global_param.stream_chunk_size = 512;
	
	// ======================
	// 送信バッファを確保
	// ======================

	buflen = global_param.stream_chunk_size;
	p = malloc(buflen);
	if ( p == NULL )
	{
		debug_log_output("malloc() error.\n");
		return ( 0 );
	}

	debug_log_output("Sending %lld bytes", content_length);

	// If we have no size specified, send an "infinite" number of bytes, or until EOF
	if(remain == 0)
		remain = (off_t)(-1);

	// ================
	// 実体転送開始
	// ================
	while ( remain )
	{
		// Read a block from the file
		count = fread(p, 1, (remain > buflen) ? buflen : remain, in_fp); 
		if(count > 0) {
			remain -= count;
			// Write this data to the socket
			for(n=0; n < count; n += len) {
				len = write(out_fd, p+n, ((count-n) < global_param.socket_chunk_size) ? (count-n) : global_param.socket_chunk_size);
				if(len <= 0) {
					// Failed to write - end the stream
					remain = 0;
					if(len < 0) {
						debug_log_output("write failed. err = %s", strerror(errno));
					} else {
						debug_log_output("socket closed by player");
					}
					break;
				} else {
					written += len;
				}
			}
		} else {
			if(count < 0) {
				debug_log_output("read failed. err = %s", strerror(errno));
			} else {
				debug_log_output("EOF");
				// Open the next file in the sequence...
			}
			remain = 0;
		}
	}
	debug_log_output("Wrote %llu bytes", written);

	free(p);

	// 正常終了
	return written;
}
Ejemplo n.º 24
0
// **************************************************************************
// リクエストされたURIのファイルをチェック
// documet_rootと、skin置き場をセットで探す。
//
// Sets http_recv_info_p->file_type to one of the following:
//			-2: Directory without the slash
//			-1: File not found
//			 0: Normal file
//			 1: Directory
//			 2: SVI
//			 3: plw/upl
//			 4: tsv
//			 5: VOB video file
//			 6: CGI script
//			 7: ISO DVD image
// **************************************************************************
static int http_file_check( HTTP_RECV_INFO *http_recv_info_p)
{
	struct stat send_filestat;
	int result;
	int len;

	unsigned char	file_extension[16];

	debug_log_output("http_file_check() start.");

	// ---------------
	// 作業用変数初期化
	// ---------------
	memset(http_recv_info_p->send_filename, '\0', sizeof(http_recv_info_p->send_filename));
	memset(file_extension, '\0', sizeof(file_extension));

	// -------------------------
	// ファイルチェック
	// -------------------------

	// 要求パスのフルパス生成。
	strncpy(http_recv_info_p->send_filename, global_param.document_root, sizeof(http_recv_info_p->send_filename));
	strncat(http_recv_info_p->send_filename, http_recv_info_p->recv_uri, sizeof(http_recv_info_p->send_filename));

	// Check if the URI is an alias
	// printf("uri1 is %s\n", http_recv_info_p->recv_uri);
	// printf("send_filename1 %s\n", http_recv_info_p->send_filename);
	if(global_param.num_aliases && (http_recv_info_p->recv_uri[0] == '/')) {
		int i,j,len, skip_stat;
		char *p;
		
		for(i=0; i<global_param.num_aliases; i++) {
			len = strlen(global_param.alias_name[i]);
			if ((strncmp(http_recv_info_p->recv_uri + 1, global_param.alias_name[i], len) == 0)
			   && (http_recv_info_p->recv_uri[len+1] == '/') ) {
			   // see code in set_thumb_file in wizd_menu.c
				p = strrchr(http_recv_info_p->recv_uri, '.');
				if (p && isdigit(p[1]) && isdigit(p[2]) && !p[3]) {
					p[0] = 0;
					p++;
					j = atoi(p);
					skip_stat = 1;
				} else {
					j = i;
					skip_stat = 0;
				}

				debug_log_output("substituting alias path '%s' for '%s'\n",
								  global_param.alias_path[j],
								  global_param.alias_name[j]);

				// The name matches an alias - substitute the alias path
				strncpy(http_recv_info_p->send_filename, global_param.alias_path[j], sizeof(http_recv_info_p->send_filename));
				strncat(http_recv_info_p->send_filename, http_recv_info_p->recv_uri+len+1, sizeof(http_recv_info_p->send_filename)-strlen(http_recv_info_p->send_filename));

				if (!skip_stat && stat(http_recv_info_p->send_filename, &send_filestat) != 0)
					continue;

				// Set the default allplay type, if it was not specified in the http request
				if(http_recv_info_p->default_file_type == TYPE_UNKNOWN) {
					http_recv_info_p->default_file_type = global_param.alias_default_file_type[j];
					debug_log_output("Setting default file type to %d\n",http_recv_info_p->default_file_type);
				} else {
					debug_log_output("Leaving default file type set at %d\n",http_recv_info_p->default_file_type);
				}
				break;
			}
		}
	}

	// fix up shortcuts
# ifdef HAVE_W32API
	len = strlen(http_recv_info_p->recv_uri);
	if (len > 4 && strcmp(&http_recv_info_p->recv_uri[len - 4], ".lnk") == 0) {
		char retPath1[256];
		char retPath2[256];
		char *p1, *p2;

		cygwin_conv_to_full_win32_path(http_recv_info_p->send_filename, retPath1);
		if (get_target(retPath1, retPath2) == 0) {
			cygwin_conv_to_full_posix_path(retPath2, http_recv_info_p->send_filename);

			p1 = strrchr(http_recv_info_p->recv_uri, '/');
			p1++;
			p2 = strrchr(http_recv_info_p->send_filename, '/');
			p2++;
			strcpy(p1, p2);
		}
	}
# endif

	// printf("send_filename2 %s\n", http_recv_info_p->send_filename);
	// printf("uri2 is %s\n\n", http_recv_info_p->recv_uri);

	// '/' が重なってるところの重複を排除。
	duplex_character_to_unique(http_recv_info_p->send_filename, '/');
	debug_log_output("http_recv_info_p->send_filename='%s'\n", http_recv_info_p->send_filename);


	// Return "File not found" unless we get a match
	http_recv_info_p->file_type = -1;

	// ------------------------------------------------------------
	// ファイルあるかチェック。
	// ------------------------------------------------------------
	result = stat(http_recv_info_p->send_filename, &send_filestat);
	debug_log_output("stat: result=%d, st_mode=0x%04X, S_ISREG=%d, S_ISDIR=%d size=%lld\n", 
		result, send_filestat.st_mode, S_ISREG(send_filestat.st_mode), S_ISDIR(send_filestat.st_mode), send_filestat.st_size );
	http_recv_info_p->file_size = send_filestat.st_size;

	if(result < 0)
	{
		debug_log_output("stat() error\n", result);

		// ----------------------------------------------------------------------------
		// もし、実体が存在しなかったら、skin置き場に変えてもう一度チェック
		// Skin置き場は実体ファイルのみ認める。
		// ----------------------------------------------------------------------------
		debug_log_output("DocumentRoot not found. SkinDir Check.");

		debug_log_output("global_param.skin_root='%s'", global_param.skin_root);
		debug_log_output("global_param.skin_name='%s'", global_param.skin_name);


		// skin置き場にあるモノとして、フルパス生成。
		strncpy(http_recv_info_p->send_filename, global_param.skin_root, sizeof(http_recv_info_p->send_filename));
		strncat(http_recv_info_p->send_filename, global_param.skin_name, sizeof(http_recv_info_p->send_filename));
		strncat(http_recv_info_p->send_filename, http_recv_info_p->recv_uri, sizeof(http_recv_info_p->send_filename));

		// '/' が重なってるところの重複を排除。
		duplex_character_to_unique(http_recv_info_p->send_filename, '/');
		debug_log_output("SkinDir:http_recv_info_p->send_filename='%s'\n", http_recv_info_p->send_filename);


		// ------------------------------------------------------------
		// Skin置き場にファイルあるかチェック。
		// ------------------------------------------------------------
		result = stat(http_recv_info_p->send_filename, &send_filestat);
		debug_log_output("stat: result=%d, st_mode=%04X, S_ISREG=%d\n", result, send_filestat.st_mode, S_ISREG(send_filestat.st_mode));

		if( result < 0 ) {
			// Strip off the path, and try just the filename in the skin directory
			unsigned char *ptr = strrchr(http_recv_info_p->recv_uri, '/');
			if((ptr != NULL) && (ptr != http_recv_info_p->recv_uri)) {
				strncpy(http_recv_info_p->send_filename, global_param.skin_root, sizeof(http_recv_info_p->send_filename));
				strncat(http_recv_info_p->send_filename, global_param.skin_name, sizeof(http_recv_info_p->send_filename)-strlen(http_recv_info_p->send_filename));
				strncat(http_recv_info_p->send_filename, ptr, sizeof(http_recv_info_p->send_filename)-strlen(http_recv_info_p->send_filename));
				duplex_character_to_unique(http_recv_info_p->send_filename, '/');
				debug_log_output("SkinDir:http_recv_info_p->send_filename='%s'\n", http_recv_info_p->send_filename);
				result = stat(http_recv_info_p->send_filename, &send_filestat);
				debug_log_output("stat: result=%d, st_mode=%04X, S_ISREG=%d\n", result, send_filestat.st_mode, S_ISREG(send_filestat.st_mode));
			}
		}

		// ファイル実体と検知。
		if ( ( result < 0 ) || !(S_ISREG(send_filestat.st_mode)) )
		{
			// -------------------------------------
			// File Not Found.
			// やっぱり、404にしよう。
			// -------------------------------------
			http_recv_info_p->file_type = -1; // Not found
			return(http_recv_info_p->file_type);
		}
	}


	// stat()の結果で分岐。
	if ( ( result == 0 ) && ( S_ISREG(send_filestat.st_mode) == 1 ) )
	{
		 // ファイル実体と検知
		debug_log_output("'%s' is File!!", http_recv_info_p->send_filename);
		debug_log_output("send_filestat.st_size= %lld\n", send_filestat.st_size);

		// Hack to overcome Linkplayer bug - it limits bookmark offset to (2^31)-1
		// so we remember the last bookmark served so we can recover the real offset
		if((http_recv_info_p->range_start_pos == 2147483647) && global_param.bookmark_threshold) {
			// Check for the real bookmark
			FILE *fp;
			off_t offset;
			char work_buf[WIZD_FILENAME_MAX];
			snprintf(work_buf, sizeof(work_buf), "%s.wizd.bookmark", 
				http_recv_info_p->send_filename);
			debug_log_output("Double-checking bookmark: '%s'", work_buf);
			fp = fopen(work_buf, "r");
			if(fp != NULL) {
				fgets(work_buf, sizeof(work_buf), fp);
				fclose(fp);
				offset = atoll(work_buf);
				if(offset > http_recv_info_p->range_start_pos) {
					debug_log_output("Detected LinkPlayer2 bookmark bug, replacing 'Range: %lld-' with 'Range: %lld-'",
						http_recv_info_p->range_start_pos, offset);
					http_recv_info_p->range_start_pos = offset;
				}
			}
		}


		// -------------------------------------------
		// ファイルの拡張子より、Content-type を決定
		// -------------------------------------------
		filename_to_extension(http_recv_info_p->send_filename, file_extension, sizeof(file_extension));
		debug_log_output("http_recv_info_p->send_filename='%s', file_extension='%s'\n", http_recv_info_p->send_filename, file_extension);

		// 拡張子から、mime_typeを導く。
		http_recv_info_p->menu_file_type = check_file_extension_to_mime_type(file_extension, http_recv_info_p->mime_type,  sizeof(http_recv_info_p->mime_type));

		// SVIファイルと実体ファイルで分岐
		if (( strcasecmp(file_extension, "svi") == 0 ) || ( strcasecmp(file_extension, "sv3") == 0 ))
		{
			http_recv_info_p->file_type = SVI_TYPE;	// sviファイル
		}
		else if (  ( http_recv_info_p->menu_file_type == TYPE_PLAYLIST )
				|| ( http_recv_info_p->menu_file_type == TYPE_MUSICLIST ))
			/*( strcasecmp(file_extension, "plw") == 0  ) ||
				 ( strcasecmp(file_extension, "pls") == 0  ) ||
				 ( strcasecmp(file_extension, "m3u") == 0  ) ||
				 ( strcasecmp(file_extension, "upl") == 0  ) )*/
		{
			http_recv_info_p->file_type = PLW_UPL_TYPE;	// plw/upl ファイル
		}
		else if (( strcasecmp(file_extension, "vob") == 0  )
			|| ( strcasecmp(file_extension, "ts") == 0  )
			|| ( strcasecmp(file_extension, "tp") == 0  ) )
		{
			// VOB_TYPE files combine files with increasing digits at the end of the filename
			// into one large virtual file
			http_recv_info_p->file_type = VOB_TYPE;	// vobファイル
		}
		else if ( strcasecmp(file_extension, "tsv") == 0  )
		{
			http_recv_info_p->file_type = TSV_TYPE;	// tsvファイル
		}
		else if ( strcasecmp(file_extension, "cgi") == 0  )
		{
			// CGIの実行が不許可なら、Not Found.
			http_recv_info_p->file_type = (global_param.flag_execute_cgi ? CGI_TYPE : -1 );	// cgiファイル
		}
		else if ( http_recv_info_p->menu_file_type == TYPE_ISO )
		{
			http_recv_info_p->file_type = ISO_TYPE;
		}
		else
		{
			http_recv_info_p->file_type = GENERAL_FILE_TYPE;	// File実体
		}
	}
	else if ( ( result == 0 ) && ( S_ISDIR(send_filestat.st_mode) == 1 ) ) // ディレクトリ
	{
		int len;
		len = strlen(http_recv_info_p->recv_uri);
		if (len > 0 && http_recv_info_p->recv_uri[len - 1] != '/') {
			// '/' で終端していないディレクトリ要求の場合...
			http_recv_info_p->file_type = -2;
		}
		// ディレクトリと検知
		debug_log_output("'%s' is Dir!!", http_recv_info_p->send_filename);

		http_recv_info_p->file_type = DIRECTORY_TYPE ;	// ディレクトリ
	}
	return( http_recv_info_p->file_type );
}
Ejemplo n.º 25
0
int http_proxy_response(int accept_socket, HTTP_RECV_INFO *http_recv_info_p)
{
    const char *HTTP_RECV_CONTENT_TYPE = "Content-type: text/html";
    const char *HTTP_RECV_CONTENT_LENGTH = "Content-Length: ";
    const char *HTTP_RECV_LOCATION = "Location: ";
    char *p_target_host_name;
    char *p_uri_string;
    char send_http_header_buf[2048];
    char line_buf[MAX_LINE][LINE_BUF_SIZE + 5];
    char proxy_pre_string[2048];
    char base_url[2048];
    char *p_url;
    char *p;
    char *p_auth = NULL;
    int port = 80;
    int sock;
    off_t content_length = 0;
    int len = 0;
    int line = 0;
    int i;
    int content_is_html = 0;
    p_uri_string = http_recv_info_p->request_uri;
    if (!strncmp(p_uri_string, "/-.-playlist.pls?", 17)) {
        char buff[FILENAME_MAX];
        if (p_uri_string[17] == '/') {
            snprintf(buff, sizeof(buff), "http://%s%s"
            , http_recv_info_p->recv_host, p_uri_string+17);
        } else {
            strncpy(buff, p_uri_string+17, sizeof(buff));
        }
        replace_character((char*)buff, ".pls", "");
        return 0;//http_uri_to_scplaylist_create(accept_socket, (char*)buff);
    }
    if (strncmp(p_uri_string, "/-.-http://", 11)) {
        return -1;
    }
    if (!global_param.flag_allow_proxy) {
        return -1;
    }
    strncpy(base_url, p_uri_string, 2048);
    p = strrchr(base_url, '/');
    p[1] = '\0';
    p_target_host_name = p_uri_string + 11;
    p_url = strchr(p_target_host_name, '/');
    if (p_url == NULL) return -1;
    *p_url++ = '\0';
    strncpy(proxy_pre_string, p_uri_string, 2048);
    p = strchr(p_target_host_name, '@');
    if (p != NULL) {
        // there is a user name.
        p_auth = p_target_host_name;
        p_target_host_name = p + 1;
        *p = '\0';
    }
    p = strchr(p_target_host_name, ':');
    if (p != NULL) {
        port = atoi(p+1);
        *p = '\0';
    }
    debug_log_output("proxy:target_host_name: %s", p_target_host_name);
    debug_log_output("proxy:authenticate: %s", p_auth ? p_auth : "NULL");
    debug_log_output("proxy:url: %s", p_url);
    debug_log_output("proxy:prestring: %s", proxy_pre_string);
    debug_log_output("proxy:base_url: %s", base_url);
    debug_log_output("proxy:port: %d", port);
    p = send_http_header_buf;
    if( http_recv_info_p->isGet == 1 ){
        p += sprintf((char*)p, "GET /%s HTTP/1.0\r\n", p_url);
    }else if ( http_recv_info_p->isGet == 2 ){
        p += sprintf((char*)p, "HEAD /%s HTTP/1.0\r\n", p_url);
    }
    p += sprintf((char*)p, "Host: %s:%u\r\n", p_target_host_name, port);
    if (global_param.user_agent_proxy_override[0]) {
        p += sprintf((char*)p, "User-agent: %s\r\n", global_param.user_agent_proxy_override);
    } else {
        if (http_recv_info_p->user_agent[0]) {
            p += sprintf((char*)p, "User-agent: %s\r\n", http_recv_info_p->user_agent);
        } else {
            p += sprintf((char*)p, "User-agent: %s\r\n", SERVER_NAME);
        }
    }
    p += sprintf(p, "Accept: */*\r\n");
    p += sprintf(p, "Connection: close\r\n");
    if (http_recv_info_p->range_start_pos) {
        p += sprintf((char*)p, "Range: bytes=");
        p += sprintf((char*)p, "%zu-", http_recv_info_p->range_start_pos);
        if (http_recv_info_p->range_end_pos) {
            p += sprintf((char*)p, "%zu", http_recv_info_p->range_end_pos);
        }
        p += sprintf(p, "\r\n");
    }
    if (p_auth != NULL) {
        p += sprintf((char*)p, "Authorization: Basic %s\r\n", base64((unsigned char*)p_auth));
    }
    p += sprintf(p, "\r\n");
    sock = sock_connect((char*)p_target_host_name, port);
    if (sock < 0) {
        debug_log_output("error: %s", strerror(errno));
        debug_log_output("sock: %d", sock);
        return -1;
    }
    set_nonblocking_mode(sock, 0); /* blocking mode */
    set_nonblocking_mode(accept_socket, 0); /* blocking mode */
    write(sock, send_http_header_buf, strlen(send_http_header_buf));
    debug_log_output("================= send to proxy\n");
    debug_log_output("%s", send_http_header_buf);
    debug_log_output("=================\n");
    
    //TODO ここが404や400の可能性あり
    for (line = 0; line < MAX_LINE; line ++) {
        char work_buf[LINE_BUF_SIZE + 10];
        memset(line_buf[line], 0, LINE_BUF_SIZE + 5);
        len = line_receive(sock, line_buf[line], LINE_BUF_SIZE + 1);
        if (len < 0) break;
        debug_log_output("recv html: '%s' len = %d", ((len)?(char*)line_buf[line]:""), len);
        line_buf[line][len++] = '\r';
        line_buf[line][len++] = '\n';
        line_buf[line][len] = '\0';
        if (!strncasecmp(line_buf[line], HTTP_RECV_CONTENT_TYPE, strlen(HTTP_RECV_CONTENT_TYPE))) {
            int n;
            content_is_html = 1;
            n = strlen(HTTP_RECV_CONTENT_TYPE);
            line_buf[line][n++] = '\r';
            line_buf[line][n++] = '\n';
            line_buf[line][n] = '\0';
        }else if (!strncasecmp(line_buf[line], HTTP_RECV_CONTENT_LENGTH, strlen(HTTP_RECV_CONTENT_LENGTH))) {
            content_length = strtoull((char*)(line_buf[line] + strlen(HTTP_RECV_CONTENT_LENGTH)), NULL, 0);
        }else if (!strncasecmp(line_buf[line], HTTP_RECV_LOCATION, strlen(HTTP_RECV_LOCATION))) {
            strcpy(work_buf, line_buf[line]);
            sprintf((char*)line_buf[line], "Location: /-.-%s", work_buf + strlen(HTTP_RECV_LOCATION));
        }else if ( strstr( line_buf[line],"charset") ){
            if ( strstr( line_buf[line], "EUC-JP" )){
                replace_character( (char*)line_buf[line], "EUC-JP", "UTF-8");
            }else if ( strstr ( line_buf[line], "Shift_JIS" )) {
                replace_character( (char*)line_buf[line], "Shift_JIS", "UTF-8");
            }
        }
        if (len <= 2) {
            line++;
            break;
        }
    }
    if (len < 0 ) {
        debug_log_output("CLOSED-C");
        close(sock);
        return -1;
    }
    if (content_is_html) {
        char *p, *q;
        char *new_p, *r;
        char work_buf[LINE_BUF_SIZE + 10];
        char work_buf2[LINE_BUF_SIZE * 2];
        char *link_pattern = (char*)"<A HREF=";
        int flag_conv_html_code = 1;
        for (i=0; i<line; i++) {
            //長さは不定なので送らない
            if (!strncasecmp(line_buf[i], HTTP_RECV_CONTENT_LENGTH, strlen(HTTP_RECV_CONTENT_LENGTH))) continue;
            //*q = '\0';
            p = work_buf;
            q = work_buf2;
            if (flag_conv_html_code) {
                convert_language_code(line_buf[i], work_buf, LINE_BUF_SIZE, CODE_AUTO, global_param.client_language_code);
            }
            //strcpy( work_buf, line_buf[i]);
            //            write(accept_socket, line_buf[i], strlen(line_buf[i]));
            //            debug_log_output("sent html: '%s' len = %d", line_buf[i], strlen(line_buf[i]));
            write(accept_socket, work_buf, strlen(line_buf[i]));
            debug_log_output("sent html: '%s' len = %d", work_buf, strlen(work_buf));
        }
        debug_log_output("sent header");
        //write(accept_socket, "debug:--\n", strlen("debug:--\n"));
        while (1) {
            char rep_str[1024];
            memset(work_buf, 0, LINE_BUF_SIZE);
            len = line_receive(sock, work_buf, LINE_BUF_SIZE);
            if (len < 0) break;
            debug_log_output("recv html: '%s' len = %d", work_buf, len);
            work_buf[len++] = '\r';
            work_buf[len++] = '\n';
            work_buf[len] = '\0';
            if (my_strcasestr(work_buf, "Content-Type") != NULL) {
                // Content-Type があったら
                // 漢字コードの変換をやめる
                //    flag_conv_html_code = 0;
                if ( strstr( work_buf, "EUC-JP" )){
                    replace_character( (char*)work_buf, "EUC-JP", "UTF-8");
                }else if ( strstr ( work_buf, "Shift_JIS" )) {
                    replace_character( (char*)work_buf, "Shift_JIS", "UTF-8");
                }
            }
            p = work_buf;
            q = work_buf2;
            memset(q, 0, sizeof(work_buf2));
            /*
            * HTML中に <A HREF="..."> があったら、プロクシを経由するように
            * たとえば <A HREF="/-.-http://www.yahoo.co.jp/"> のように変換する
            * もし、ファイルがストリーム可能そうであれば、VOD="0" も追加する。
            *
            * 問題点:
            *   タグの途中に改行があると失敗するだろう.
            *   面倒なのでたいした置換はしていない
            *   惰性で書いたので汚い。だれか修正して。
            */
            link_pattern = (char*)"<A HREF=";
            while ((new_p = my_strcasestr(p, link_pattern)) != NULL) {
                int l = new_p - p + strlen(link_pattern);
                char *tmp;
                MIME_LIST_T *mlt = NULL;
                strncpy(q, p, l);
                q += l;
                p += l; /* i.e., p = new_p + strlen(link_pattern); */
                r = strchr(p, '>');
                if (r == NULL) continue;
                *r = '\0';
                if (*p == '"') *q++ = *p++;
                if ((tmp = strchr(p, '"')) != NULL || (tmp = strchr(p, ' ')) != NULL) {
                    mlt = mime_list;
                    while (mlt->mime_name != NULL) {
                        if (*(tmp - strlen(mlt->file_extension) - 1) == '.'
                        && !strncasecmp(tmp - strlen(mlt->file_extension), mlt->file_extension, strlen(mlt->file_extension))) {
                            break;
                        }
                        mlt++;
                    }
                }
                //if (flag_pc && mlt != NULL && mlt->stream_type == TYPE_STREAM) {
                //    q += sprintf((char*)q, "/-.-playlist.pls?http://%s", http_recv_info_p->recv_host);
                //}
                if (*p == '/') {
                    q += sprintf(q, "%s%s", proxy_pre_string, p);
                } else if (!strncmp(p, "http://", 7)) {
                    q += sprintf(q, "/-.-%s", p);
                } else {
                    q += sprintf((char*)q, "%s%s", base_url, p);
                    //q += sprintf((char*)q, "%s", p);
                }
                if (mlt != NULL && mlt->stream_type == TYPE_STREAM) {
                    q += sprintf(q, " vod=\"0\"");
                }
                *q++ = '>';
                p = r + 1;
            }
            while (*p) *q++ = *p++;
            *q = '\0';
            /*
            * HTML中に SRC="..." があったら、プロクシを経由するように変換する
            *
            * 問題点:
            *   タグの途中に改行があると失敗するだろう.
            *   変数使いまわしたので、融通が効かない。
            *   だれか修正して。
            */
            p = work_buf2;
            q = work_buf;
            memset(q, 0, sizeof(work_buf));
            link_pattern = (char*)"SRC=";
            while ((new_p = my_strcasestr(p, link_pattern)) != NULL) {
                int l = new_p - p + strlen(link_pattern);
                strncpy(q, p, l);
                q += l;
                p += l; /* i.e., p = new_p + strlen(link_pattern); */
                if (*p == '"') *q++ = *p++;
                if (*p == '/') {
                    q += sprintf(q, "%s", proxy_pre_string);
                } else if (!strncmp(p, "http://", 7)) {
                    q += sprintf(q, "/-.-");
                } else {
                    q += sprintf(q, "%s", base_url);
                    //q += sprintf(q, "%s", p);
                }
            }
            while (*p) *q++ = *p++;
            *q = '\0';
            p = work_buf;
            q = work_buf2;
            if (flag_conv_html_code) {
                convert_language_code(p, q, LINE_BUF_SIZE, CODE_AUTO, global_param.client_language_code);
                //strcpy( q,p);
                p = q;
            }
            snprintf(rep_str, sizeof(rep_str), "|http://%s/-.-http://"
            , http_recv_info_p->recv_host);
            replace_character((char*)p, "|http://", rep_str);
            write(accept_socket, p, strlen(p));
            debug_log_output("sent html: %s", p);
        }
    } else {
        for (i=0; i<line; i++) {
            write(accept_socket, line_buf[i], strlen(line_buf[i]));
        }
        if( http_recv_info_p->isGet == 1 ){
            return ( copy_descriptors(sock, accept_socket, (size_t)content_length) );
            //NULL ,
            //(char*)http_recv_info_p->recv_uri,
           // http_recv_info_p->range_start_pos));
        }
    }
    sClose(sock);
    return 0;
}
Ejemplo n.º 26
0
off_t copy_descriptors(int in_fd, int out_fd, off_t content_length, JOINT_FILE_INFO_T *joint_file_info_p)
{
	int i;

	pthread_t id;
	pthread_attr_t attr;
	thread_param_type param;

	int index = 0;
	int next_index;
	int oneback,twoback,shortcount;

	off_t	total_read_size = 0;
	int	len;

	off_t read_cnt = 0;

	int flag_verbose = 0; // Set to 1 for debugging sessions, set to 0 for release
	int flag_send_asap = global_param.flag_buffer_send_asap;

	ssize_t blocks_read = 0;
	int offset = 0;
	
	if(global_param.buffer_size < 1) global_param.buffer_size = 1;
	if(global_param.stream_chunk_size < 512) global_param.stream_chunk_size = 512;

	if (joint_file_info_p) offset = joint_file_info_p->iso_seek;
	
	if(flag_verbose && global_param.flag_debug_log_output) {
		// Redirect streaming debug log to stderr
		debug_log_initialize(NULL);
	}
	// ======================
	// 送信バッファを確保
	// ======================

	param.count = global_param.buffer_size;

	// Need at least 4 buffers for this to be reasonable
	if(param.count < 4)
		param.count = 4;

	param.length = global_param.stream_chunk_size;

	debug_log_output("Allocating %d buffers of %d bytes each\n", param.count, param.length);

	param.bytes = (int *)malloc(param.count * sizeof(int));
	param.total = (off_t *)malloc(param.count * sizeof(off_t));
	param.buffer = (char **)malloc(param.count * sizeof(char *));
	param.mutex = (pthread_mutex_t *)malloc(param.count * sizeof(pthread_mutex_t));

	if ( ( param.bytes == NULL ) || ( param.buffer == NULL ) || ( param.mutex == NULL ) )
	{
		debug_log_output("malloc() error.\n");
		return (-1 );
	}

	for(i=0; i<param.count; i++) {
		param.bytes[i] = 0;
		param.buffer[i] = (char *)malloc(param.length);
		if(param.buffer[i] == NULL) {
			debug_log_output("malloc() error.\n");
			return ( 0 );
		}
		pthread_mutex_init(&param.mutex[i], NULL);
	}

	// Launch a separate thread to send the data out
	param.fd = out_fd;
	param.flags = 0;
	param.written = 0;

	// Lock the next block in advance
	pthread_mutex_lock(&param.mutex[index]);

	pthread_attr_init(&attr);

// This doesn't seek to work well under Cygwin
//#define USE_PTHREAD_PRIORITY
#ifdef USE_PTHREAD_PRIORITY
	{
		int policy,retcode,curr,mn,mx;
		struct sched_param schp;

		memset(&schp, 0, sizeof(schp));
		// Get the current settings
		pthread_getschedparam(pthread_self(), &policy, &schp);
		curr=schp.sched_priority;
		mn=sched_get_priority_min(policy);
		mx=sched_get_priority_max(policy);
		schp.sched_priority = (curr+mx)/2;
		debug_log_output("Setting policy %d, priority %d (was=%d, min=%d, max=%d)\n", policy, schp.sched_priority, curr, mn, mx);
		retcode = pthread_attr_setschedpolicy(&attr,policy);
		if(retcode != 0) {
			debug_log_output("pthread_attr_setschedpolicy returned %d\n",retcode);
		}
		retcode = pthread_attr_setschedparam(&attr,&schp);
		if(retcode != 0) {
			debug_log_output("pthread_attr_setschedparam returned %d\n",retcode);
		}
	}
#endif
	if((i = pthread_create(&id, &attr, send_buffers, &param)) != 0) {
		debug_log_output("pthread_create returned %d\n",i);
		return ( 0 );
	}

	// Watch the two bins behind, and shorten the buffer if the write thread is catching up
	twoback = param.count - 2;
	oneback = param.count - 1;
	shortcount = param.length/4;
	if(shortcount < 4096)
		shortcount = 4096;

	while ( param.flags == 0 )
	{
		// Wait for a buffer to free up
		next_index = index+1;
		if(next_index >= param.count)
			next_index = 0;

		if(pthread_mutex_lock(&param.mutex[next_index]) == 0) {
			for(i=0 ; i < param.length; ) {
				len = param.length - i;
				if(len > global_param.file_chunk_size)
					len = global_param.file_chunk_size;
				if ((joint_file_info_p!=NULL) && (joint_file_info_p->dvd_file != NULL)) {
					blocks_read = DVDReadBlocks(joint_file_info_p->dvd_file, offset, len/2048, param.buffer[index] + i); 
					len = (off_t)blocks_read*2048;
					offset += blocks_read;
				} else if (joint_file_info_p && read_cnt >= joint_file_info_p->file[joint_file_info_p->current_file_num].size) {
					len = 0;
					read_cnt = 0;
					debug_log_output("finished file chunk %d\n", joint_file_info_p->current_file_num);
					//printf("finished file chunk %d\n", joint_file_info_p->current_file_num);
				} else {
					if (joint_file_info_p && len + read_cnt > joint_file_info_p->file[joint_file_info_p->current_file_num].size) {
						len = joint_file_info_p->file[joint_file_info_p->current_file_num].size - read_cnt;
						debug_log_output("finishing last block of %d\n", joint_file_info_p->current_file_num);
						//printf("finishing last block of %d\n", joint_file_info_p->current_file_num);
					}

					len = read(in_fd, param.buffer[index] + i, len);
					read_cnt += len;
				}
				if(len == 0) {
					// End of file
					if(    (joint_file_info_p==NULL)
						|| (joint_file_info_p->dvd_file != NULL)
						|| next_file(&in_fd, joint_file_info_p)) {
						// No more files
						if (flag_verbose) {
							debug_log_output("recv: len = %d, idx = %d finish!", len, index);
						} else {
							debug_log_output(
							   "*********************************************************\n"
							   "**                    RECV FINISHED!                   **\n"
							   "*********************************************************");
						}
						param.flags |= FLAG_READ_COMPLETE;
						break;
					} else {
						// We opened up a new file, so continue the loop
					}
				} else if (len > 0) {
					i += len;
					total_read_size += len;
					if((content_length > 0) && (total_read_size >= content_length)) {
						// Only send as much as is requested
						if(total_read_size > content_length) {
							debug_log_output("Restricting content length, read=%lld, allowed=%lld", total_read_size, content_length);
							total_read_size -= content_length;
							i -= (int)total_read_size;;
							total_read_size = content_length;
						}
						param.flags |= FLAG_READ_COMPLETE;
						break;
					}
				} else {
					// Read error
					if (flag_verbose) {
						debug_log_output("read err?: len = %d, idx = %d, err: %s", len, index, strerror(errno));
					} else {
						debug_log_output(
					   "*********************************************************\n"
					   "**                    RECV FINISHED!(ret = %d)          **\n"
					   "*********************************************************", len);
					}
					param.flags |= FLAG_READ_COMPLETE;
					break;
				}
				// Check the trailing bins to see if the write thread is catching us
				// with the exception that if we already fell behind, 
				// then we allow it to rebuffer completely for one block
				if((i >= shortcount) && (param.bytes[twoback] == 0) && (total_read_size > param.length)) {
					if(param.bytes[oneback] == 0) {
						//fputc('.',stderr); // Only one buffer full - reloading
					} else {
						//fputc(':',stderr); // Only two buffers full, cut this buffer short
						break;
					}
				}
			}
			// Flag this block as ready-to-write
			param.bytes[index] = i;
			param.total[index] = total_read_size;
			if(flag_send_asap) {
				pthread_mutex_unlock(&param.mutex[index]);
			} else if(next_index == (param.count-2)) {
				// Buffers are filled, so release the sending thread
				flag_send_asap = TRUE;
				for(i=0; i<next_index; i++)
					pthread_mutex_unlock(&param.mutex[i]);
			}

			twoback = oneback;
			oneback = index;
			index = next_index;
		}
	}

	// Count the number of bytes in the queue
	for(i=0,len=0; i<param.count; i++) {
		len += param.bytes[i];
	}
	debug_log_output("Read complete, read %lld bytes, %d bytes to transmit", total_read_size, len);

	// If we haven't released the sending thread yet, do so now
	if(!flag_send_asap) {
		for(i=0; i<index; i++)
			pthread_mutex_unlock(&param.mutex[i]);
	}

	// Release the last block, unused
	pthread_mutex_unlock(&param.mutex[index]);

	// Wait for the created thread to complete
	pthread_join(id,NULL);

	// Free up the allocated memory
	if(param.bytes != NULL)
		free(param.bytes);
	for(i=0; i<param.count; i++) {
		if(param.buffer[i] != NULL)
			free(param.buffer[i]);
		pthread_mutex_destroy(&param.mutex[i]);
	}
	debug_log_output("copy descriptors end.");

	return param.written;
}
Ejemplo n.º 27
0
// **************************************************************************
// ファイル実体の返信。
// ヘッダ生成&送信準備
// **************************************************************************
int http_file_response(int accept_socket, HTTP_RECV_INFO *http_recv_info_p)
{
	int	send_header_data_len;
	int	result_len;

	unsigned char	send_http_header_buf[2048];
	unsigned char	work_buf[1024];

	off_t	content_length;
	off_t	written;
	off_t	offset;

	struct	stat	file_stat;
	int				result;

	int mpeg2video = (strstr(http_recv_info_p->mime_type, "video/mpeg") != NULL);

	// ---------------
	// 作業用変数初期化
	// ---------------
	memset(send_http_header_buf, '\0', sizeof(send_http_header_buf));

/*
	if ( http_recv_info_p->range_start_pos == 0 )
	{
		content_length = 0;
	}
*/
	result = stat(http_recv_info_p->send_filename, &file_stat); // ファイルサイズチェック。
	if ( result != 0 )
	{
		debug_log_output("file not found.");
		return ( -1 );
	}

	// Set the starting offset based on the requested page
	offset = (file_stat.st_size/10) * http_recv_info_p->page;

	if(    global_param.bookmark_threshold
	    && (http_recv_info_p->file_size > global_param.bookmark_threshold)
	    && (http_recv_info_p->range_start_pos == 0)) {
		// Check for a bookmark
		FILE	*fp;
		int previous_page = 0;
		off_t previous_size = 0;
		off_t bookmark = 0;
		snprintf(work_buf, sizeof(work_buf), "%s.wizd.bookmark", http_recv_info_p->send_filename);
		debug_log_output("Checking for bookmark: '%s'", work_buf);
		fp = fopen(work_buf, "r");
		if(fp != NULL) {
			fgets(work_buf, sizeof(work_buf), fp);
			bookmark = atoll(work_buf);
			if(fgets(work_buf, sizeof(work_buf), fp) != NULL) {
				previous_size = atoll(work_buf);
				if(fgets(work_buf, sizeof(work_buf), fp) != NULL) {
					previous_page = atoi(work_buf);
				}
			}
			fclose(fp);
			debug_log_output("Bookmark offset: %lld/%lld (page %d)", bookmark, previous_size, previous_page);
			debug_log_output("Requested range %lld-%lld", http_recv_info_p->range_start_pos, http_recv_info_p->range_end_pos);
		}
		// Compare the current request with the stored bookmark
		// If requesting the same chapter as before, then don't adjust anything
		// If reqesting an earlier chapter, then go there directly
		if(http_recv_info_p->page < previous_page) {
			// Make sure we never advance the position on a previous-chapter command
			if((bookmark > 0) && (offset > bookmark)) {
				debug_log_output("Forcing offset from %lld to %lld to prevent advance when going to previous chapter", offset, bookmark);
				offset = bookmark;
			} else {
				debug_log_output("Going to previous chapter - no bookmark adjustment needed");
			}
		} else if(http_recv_info_p->page > previous_page) {
			// If the file size is increasing, and bookmark is equal to the previous end-of-file
			// then adjust things so it continues playing where it left off
			// This will allow for (almost) continuous playback of files of increasing size
			if((previous_size > 0) && (file_stat.st_size > previous_size) && (offset < bookmark)) {
				debug_log_output("Forcing offset from %lld to %lld to get continuous playback", offset, bookmark);
				offset = bookmark;
			} else {
				// If requesting a following chapter, then return content_length=1 until we are beyond the bookmark location
				// (Note: I tried content_length=0, but this seems to really confuse the LinkPlayer!!!)
				if((global_param.dummy_chapter_length > 0) && (offset < bookmark)) {
					content_length = global_param.dummy_chapter_length;
					debug_log_output("Returning length=%lld because offset < bookmark (%lld < %lld)",
						content_length, offset, bookmark);
					http_recv_info_p->range_start_pos = offset;
					http_recv_info_p->range_end_pos = offset + content_length - 1;
					offset=0;

					// I also tried sending a not-found, but this confuses it too!!!
					/*
					snprintf(send_http_header_buf, sizeof(send_http_header_buf),
						HTTP_NOT_FOUND
						HTTP_CONNECTION
						HTTP_CONTENT_TYPE
						HTTP_END, "video/mpeg" );
					send_header_data_len = strlen(send_http_header_buf);
					debug_log_output("send_header_data_len = %d\n", send_header_data_len);
					debug_log_output("--------\n");
					debug_log_output("%s", send_http_header_buf);
					debug_log_output("--------\n");
					result_len = send(accept_socket, send_http_header_buf, send_header_data_len, 0);
					debug_log_output("result_len=%d, send_data_len=%d\n", result_len, send_header_data_len);
					*/
					// I also tried simply closing the socket and exiting, but this confuses it too!!!
					//close(accept_socket);
					//return 0;
				} else if(offset > bookmark) {
					debug_log_output("Advancing to chapter %d, offset=%lld, bookmark=%lld", http_recv_info_p->page, offset, bookmark);
				}
			}
		} else if(previous_size > 0) {
			// When requesting the same chapter, then compute the offset using the previously saved length
			// so that fast-forward/rewind isn't affected by changing file sizes
			offset = (previous_size/10) * http_recv_info_p->page;
			debug_log_output("Forcing offset=%lld based on previous size (%lld) instead of current size (%lld)",
				offset, previous_size, file_stat.st_size);
		}
	}

	if(offset > 0) {
		debug_log_output("Offsetting start/end position by %lld", offset);
		http_recv_info_p->range_start_pos += offset;
		if(http_recv_info_p->range_end_pos > 0)
			http_recv_info_p->range_end_pos += offset;
	}
	if ( http_recv_info_p->range_end_pos > 0 )	// end位置指定有り。
	{
		content_length = (http_recv_info_p->range_end_pos - http_recv_info_p->range_start_pos) + 1;
	} 
	else 
	{
		content_length = file_stat.st_size - http_recv_info_p->range_start_pos;
	}

	// --------------
	// OK ヘッダ生成
	// --------------
	strncpy(send_http_header_buf, HTTP_OK, sizeof(send_http_header_buf));

	strncat(send_http_header_buf, HTTP_CONNECTION, sizeof(send_http_header_buf) - strlen(send_http_header_buf));

	snprintf(work_buf, sizeof(work_buf), HTTP_SERVER_NAME, SERVER_NAME);
	strncat(send_http_header_buf, work_buf, sizeof(send_http_header_buf) - strlen(send_http_header_buf));

	if (content_length) {
		snprintf(work_buf, sizeof(work_buf), HTTP_CONTENT_LENGTH, content_length);
		strncat(send_http_header_buf, work_buf, sizeof(send_http_header_buf) - strlen(send_http_header_buf) );
	}

	snprintf(work_buf, sizeof(work_buf), HTTP_CONTENT_TYPE, http_recv_info_p->mime_type);
	strncat(send_http_header_buf, work_buf, sizeof(send_http_header_buf) - strlen(send_http_header_buf) );
	strncat(send_http_header_buf, HTTP_END, sizeof(send_http_header_buf) - strlen(send_http_header_buf) );


	send_header_data_len = strlen(send_http_header_buf);
	debug_log_output("send_header_data_len = %d\n", send_header_data_len);
	debug_log_output("--------\n");
	debug_log_output("%s", send_http_header_buf);
	debug_log_output("--------\n");


	// --------------
	// ヘッダ返信
	// --------------
	result_len = send(accept_socket, send_http_header_buf, send_header_data_len, 0);
	debug_log_output("result_len=%d, send_data_len=%d\n", result_len, send_header_data_len);


	// Small files go to simple function
	if((content_length > 0) && (content_length <= SEND_BUFFER_SIZE)) {
		written = http_simple_file_send( accept_socket, http_recv_info_p->send_filename,
								content_length,
								http_recv_info_p->range_start_pos );
	} else {
		// --------------
		// 実体返信
		// --------------
		written = http_file_send(	accept_socket, 	http_recv_info_p->send_filename,
									content_length,
									http_recv_info_p->range_start_pos );
	}

	if(global_param.bookmark_threshold && (mpeg2video || !global_param.flag_bookmarks_only_for_mpeg)) {
		/* if(  (written < global_param.bookmark_threshold) // Less than 10 MB written
		  ||  (content_length && ((written+global_param.bookmark_threshold) > content_length)) //within 10 MB of the end of file
		  ||  (0 == strcmp(http_recv_info_p->mime_type, "video/mpeg")) ) { // Only create bookmarks for MPEG video files
			// Remove any existing bookmark
			snprintf(work_buf, sizeof(work_buf), "%s.wizd.bookmark", http_recv_info_p->send_filename);
			if(0 == unlink(work_buf)) {
				debug_log_output("Removed bookmark: '%s'", work_buf);
			}
		} else */
		if(written > global_param.bookmark_threshold) {
			// Save a bookmark
			snprintf(work_buf, sizeof(work_buf), "%s.wizd.bookmark", http_recv_info_p->send_filename);
			written += http_recv_info_p->range_start_pos;
			// Back up to account for network buffering in the player
			// (don't back up if the bookmark is at the end of the file)
			if(written < file_stat.st_size)
				written -= global_param.bookmark_threshold;
			if(written > 0) { // always true here!
				FILE *fp = fopen(work_buf, "w");
				if(fp != NULL) {
					// Write the bookmark location, the size (as we saw it), and the requested chapter number
					// which will be used to decide what to do when we receive the next request
					fprintf(fp, "%lld\n", written);
					fprintf(fp, "%lld\n", file_stat.st_size);
					fprintf(fp, "%d\n", http_recv_info_p->page);
					fclose(fp);
					debug_log_output("Wrote bookmark: '%s' page %d %lld of %lld", work_buf, http_recv_info_p->page, written, file_stat.st_size);
				} else {
					debug_log_output("create bookmark failed. err = %s", strerror(errno));
				}
			} else {
				// Remove any old bookmarks
				if(0 == unlink(work_buf)) {
					debug_log_output("Removed bookmark: '%s'", work_buf);
				}
			}
		}
	}

	return 0;
}
Ejemplo n.º 28
0
void *send_buffers(void *p)
{
	thread_param_type *param = (thread_param_type *)p;
	int last_index = param->count-1;
	int index=0;
	int i,len;
	int flag_verbose = 0; // Set to 1 for debugging sessions, set to 0 for release

	if((param == NULL) || (param->count <= 0) || (param->length <= 0))
		return NULL;

	// Lock the last block to prevent overrun
	pthread_mutex_lock(&param->mutex[last_index]);

	debug_log_output("Threaded send started");

	while((param->flags & (FLAG_ABORT|FLAG_WRITE_COMPLETE)) == 0) {
		if(pthread_mutex_lock(&param->mutex[index])==0) {

			if(param->bytes[index] > 0) {
				if(flag_verbose && (param->flags & FLAG_READ_COMPLETE)) {
					debug_log_output("Sending block %d with %d bytes\n", index, param->bytes[index]);
				}
				// We have a buffer with data - send it out
				for(i=0; i<param->bytes[index]; ) {
					len = param->bytes[index] - i;
					if(len > global_param.socket_chunk_size)
						len = global_param.socket_chunk_size;
					len = send(param->fd, param->buffer[index] + i, len, 0);
					// Free up the mutex after we complete a send, so file read is triggered
					// after we have fresh data going out the network
					if(last_index >= 0) {
						pthread_mutex_unlock(&param->mutex[last_index]);
						last_index=-1;
					}
					if(len <= 0) {
						// Failed to write - end the stream
						if (len < 0) {
							debug_log_output("send failed. err = %s", strerror(errno));
						} else {
							debug_log_output("socket closed by player");
						}
						param->flags |= FLAG_ABORT;
						break;
					} else {
						i += len;
						param->written += len;
					}
				}
				if(param->written != param->total[index]) {
					debug_log_output("Read/send mismatch, read=%lld, sent=%lld, buffer=%d, sent=%d",
						param->total[index], param->written, param->bytes[index], i);
				}
			} else if((param->flags & FLAG_READ_COMPLETE) == FLAG_READ_COMPLETE) {
				// No more data - so flag that we are finished sending
				param->flags |= FLAG_WRITE_COMPLETE;
			} else if(flag_verbose) {
				debug_log_output("ERROR: Got a zero-length block without a read-complete flag!!!");
			}
			// Flag this block as complete
			param->bytes[index] = 0;
			// Free up the previous block if it hasn't been freed yet
			if(last_index >= 0) {
				pthread_mutex_unlock(&param->mutex[last_index]);
				last_index=-1;
			}
			last_index=index; // Release this block only after we acquire the next

			if(++index >= param->count)
				index = 0;
		} else {
			debug_log_output("Failed to lock mutex %d, aborting!!!", index);
			param->flags |= FLAG_ABORT;
		}
	}
	// Release the last block
	pthread_mutex_unlock(&param->mutex[last_index]);

	// Count the number of bytes in the queue
	for(i=0,len=0; i<param->count; i++) {
		len += param->bytes[i];
	}
	debug_log_output("Send complete, sent %lld bytes, %d bytes left in the buffer", param->written, len);

	return NULL;
}
Ejemplo n.º 29
0
// **************************************************************************
// SVI録画情報 読み込み
// **************************************************************************
int read_svi_info(unsigned char *svi_filename, unsigned char *svi_info, int svi_info_size, unsigned int *rec_time )
{
	int		fd;

	off_t		lseek_ret;
	ssize_t		read_length;
	size_t		read_size;
	unsigned char	rec_time_work[2];

	debug_log_output("\n\nread_svi_info() start.");


	read_size = svi_info_size;
	if ( read_size > SVI_INFO_LENGTH )
	{
		read_size = SVI_INFO_LENGTH;
	}

	memset( svi_info, '\0', svi_info_size );
	*rec_time = 0;

	// --------------------------------
	// SVIファイルから情報取り出す
	// --------------------------------

	// SVIファイル開く
	fd = open(svi_filename, O_RDONLY);
	if ( fd < 0 )
	{
		debug_log_output("oepn('%s') error.", svi_filename);
		return (-1);
	}

	// SVIファイルのファイル情報の位置にSEEK
	lseek_ret = lseek(fd, SVI_INFO_OFFSET, SEEK_SET);
	if ( lseek_ret < 0 )
	{
		debug_log_output("lseek() error.");
		return ( -1 );
	}

	// SVIファイルから、ファイル情報をget
	read_length = read(fd, svi_info, read_size);
	debug_log_output("read_length=%d, read_size=%d", read_length, read_size);
	if (read_length != read_size)
	{
		debug_log_output("fread() error.");
		return (-1);
	}


	// SVIファイルのデータ位置にSEEK
	lseek_ret = lseek(fd, SVI_REC_TIME_OFFSET, SEEK_SET);
	if ( lseek_ret < 0 )
	{
		debug_log_output("lseek() error.");
		return ( -1 );
	}

	// SVIファイルから、録画時間をGET
	read_length = read(fd, rec_time_work, SVI_REC_TIME_LENGTH );
	debug_log_output("read_length=%d, SVI_REC_TIME_LENGTH=%d", read_length, SVI_FILENAME_LENGTH);
	if (read_length != SVI_REC_TIME_LENGTH)
	{
		debug_log_output("read() error.");
		return ( -1 );
	}

	debug_log_output("read_rec=%02X,%02X", rec_time_work[0], rec_time_work[1]  );

	*rec_time += (unsigned int)( rec_time_work[0] );
	*rec_time += (unsigned int)( rec_time_work[1] << 8 );

	debug_log_output("rec_time=%d", *rec_time );


	close( fd );

	debug_log_output("read_filename = '%s'", svi_info);

	return ( 0 );
}
Ejemplo n.º 30
0
// **************************************************************************
// ファイルの実体の送信実行部
// **************************************************************************
off_t http_simple_file_send(int accept_socket, unsigned char *filename, off_t content_length, off_t range_start_pos )
{
	int		fd;

	unsigned char 	*send_buf_p;

	ssize_t			file_read_len;
	int				data_send_len;
	off_t			seek_ret;

	off_t			total_read_size;
	size_t			target_read_size;

	// ======================
	// 送信バッファを確保
	// ======================

	send_buf_p = malloc(SEND_BUFFER_SIZE);
	if ( send_buf_p == NULL )
	{
		debug_log_output("malloc() error.\n");
		return ( 0 );
	}

	// ---------------------
	// ファイルオープン
	// ---------------------
	fd = open(filename, O_RDONLY);
	if ( fd < 0 )
	{	
		debug_log_output("errno = %s\n", strerror(errno));
		debug_log_output("open() error. file='%s'", filename);
		free(send_buf_p);
		return ( 0 );
	}


	// ------------------------------------------
	// range_start_posへファイルシーク
	// ------------------------------------------
	seek_ret = lseek(fd, range_start_pos, SEEK_SET);
	if ( seek_ret < 0 )	// lseek エラーチェック
	{
		debug_log_output("errno = %s\n", strerror(errno));
		debug_log_output("lseek() error.");
		free(send_buf_p);
		close(fd);
		return ( 0 );
	}


	total_read_size = 0;

	// ================
	// 実体転送開始
	// ================
	while ( (content_length==0) || (total_read_size < content_length) )
	{
		// 一応バッファクリア
		memset(send_buf_p, 0, SEND_BUFFER_SIZE);

		// 目標readサイズ計算
		if ( (content_length - total_read_size) > SEND_BUFFER_SIZE )
		{
			target_read_size = SEND_BUFFER_SIZE;
		}
		else
		{
			target_read_size = (size_t)(content_length - total_read_size);
		}


		// ファイルからデータを読み込む。
		file_read_len = read(fd, send_buf_p, target_read_size);
		if ( file_read_len <= 0 )
		{
			debug_log_output("EOF detect.\n");
			break;
		}



		// SOCKET にデータを送信
		data_send_len = send(accept_socket, send_buf_p, file_read_len, 0);
		if ( data_send_len != file_read_len ) 
		{
			debug_log_output("send() error.\n");
			close(fd);	// File Close.
			return ( total_read_size );
		}

		total_read_size += file_read_len;
	}

	free(send_buf_p);	// Memory Free.
	close(fd);	// File Close.

	// 正常終了
	return total_read_size;
}