Beispiel #1
0
// 静态网页  文本等的处理
static void echo_www(int sock,const char* path, ssize_t size)
{
	int fd = open(path, O_RDONLY);
	if (fd < 0)
	{
		echo_errno(sock);
		return;
	}

	printf("get a new client: %d -> %s \n", sock, path);

	char status_line[_SIZE_];
	sprintf(status_line, "HTTP/1.0 200 OK\r\n\r\n");// 发送 回应行 和 空行 之间GET没有参数 参数 在url中
	send(sock, status_line, strlen(status_line), 0);

	/////////////////////////////////////////////////////
	//   sendfile 将fd拷贝到 sock  直接在内核态完成  不许要经历用户态 切换 【高效】
	if (sendfile(sock, fd, NULL, size) < 0) // 发送文件内容 回应内容 
	{
		echo_errno(sock);
		return;
	}

	close(fd);
	close(sock);	
}
Beispiel #2
0
static void echo_www(int sock, const char *path, ssize_t size)
{
	int fd = open(path, O_RDONLY);  //index.html  and .......	//fcntl
	if(fd < 0)
	{
		echo_errno(sock);
		return;
	}

	printf("get a new client %d\n  %s\n", sock, path);

	char status_line[SIZE];
	sprintf(status_line, "HTTP/1.0 200 OK\r\n\r\n");
	send(sock, status_line, strlen(status_line), 0);


	if( sendfile(sock, fd, NULL, size) < 0 )
	{
		echo_errno(sock);
		return;
	}


	close(fd);
}
Beispiel #3
0
static void echo_www(int sock,const char* path,ssize_t size)
{
	int fd = open(path,O_RDONLY);
	if(fd < 0)
	{
			echo_errno(sock,1);//
			return ;
	}
	printf("get a new client: %d -> %s\n",sock,path);

	char buf[SIZE];
	sprintf(buf,"HTTP/1.0 200 OK\r\n\r\n");
	send(sock,buf,strlen(buf),0);

	if(sendfile(sock,fd,NULL,size) < 0)//sendfile  提高效率
	{
			echo_errno(sock,1);
			return ;
	}

	close(fd);
}
Beispiel #4
0
static void * accept_request(void *arg)
{
	int sock = (int)arg;
	char buf[_SIZE_];

	char method[_SIZE_/10];
	char url[_SIZE_];
	char path[_SIZE_];

	memset(buf, '\0', sizeof(buf));
	memset(buf, '\0', sizeof(method));
	memset(buf, '\0', sizeof(url));
	memset(buf, '\0', sizeof(path));

	int cgi = 0;
	int ret = -1;
	char *query_string = NULL; // 数据参数
	int len = sizeof(buf) / sizeof(buf[0]);
#ifdef _DEBUG_
	do 
	{
		// http 请求 报文 按行存储
		ret = get_line(sock, buf, len);
		printf("%s", buf);
		fflush(stdout);
	} while (ret > 0 && strcmp(buf, "\n") != 0);
#endif 

	ret = get_line(sock, buf, len); // 获取请求行
printf("line:   %s\n", buf);	
	if (ret < 0)
	{
		echo_errno(sock);
		return (void*)1;
	}

	// GET / HTTP/1.0
	int i = 0; // method index
	int j = 0; // buf index

	// 请求行 包括   【方法(GET/POST)】【url】【HTTP/1.0(1.1)】
	// 获取方法 GET/POST
	while ((i < sizeof(method) - 1) && (j < sizeof(buf)) && (!isspace(buf[j])))
	{
		method[i] = buf[j];
		++i;
		++j;
	}
	method[i] = '\0';
	// strcasecmp 忽略大小写的比较
	if (strcasecmp(method, "GET") != 0 && strcasecmp(method, "POST") != 0)
	{
		echo_errno(sock);
		return (void*)2;
	}
	
	// 跳过空格
	while (j < sizeof(buf) && isspace(buf[j]))
	{
		j++;
	}

	i = 0;


	// 获取url url是除了域名 端口号之后的 /。。。
	while ((i < sizeof(url) - 1) && (j < sizeof(buf)) && (!isspace(buf[j])))
	{
		url[i++] = buf[j++];
	}

	url[i] = '\0';
	//GET  所传递的参数 在URL中, 从server的QUERY_STRING 中获取
	//POST 所传递的参数 在 数据包中 从server环境变量中CONTENT_LENGTH 环境变量中获取参数 数据的长度
	
	if (strcasecmp(method, "POST") == 0)
	{
		cgi = 1;
	}
	
	 if (strcasecmp(method, "GET") == 0)
	 {
		 query_string = url;
		 // 路径和数据参数 以?分隔 如 http:// baidu.com /s ?  k = v
		 while (*query_string != '\0' && *query_string != '?')
		 {
			 ++query_string;
		 }

		 if(*query_string == '?') // GET 带参数 需要进一步处理参数
		 {
			 cgi = 1;
			 *query_string++ = '\0';
		 }
	 }

	 // 没指定具体网页 加默认网页 和 根文件夹(安全考虑)
	 sprintf(path, "httpdoc%s", url);
	 if (path[strlen(path) - 1] == '/')
	 {
		strcat(path, "index.html");
	 }


	 // method , query_string, cgi, path
	 struct stat st;
	 if (stat(path, &st) < 0) // 测文件在不在
	 {
		 echo_errno(sock);
		 return (void*)3;
	 }
	 else
	 {
		 if (S_ISDIR(st.st_mode))// 测是不是 文件夹
		 {
			 strcat(path, "/index.html");
		 }
		 else if( (st.st_mode & S_IXUSR) ||\
				(st.st_mode & S_IXGRP) ||\
				(st.st_mode & S_IXOTH))
				//   查看cgi执行权限
		 {
				cgi = 1;
		 }
		 else
		 {}

		 if (cgi)
		 {
			  exec_cgi(sock, method, path,  query_string);
		 }
		 else
		 {
			clear_header(sock); // 
			echo_www(sock, path, st.st_size);
		 }
	 }
}
Beispiel #5
0
static void exec_cgi(int sock, const char *method, const char *path, const char *query_string )
{
	char buf[_SIZE_];
	int content_length = -1;// 内容长度  方便获取内容  
	int ret = -1;
	int cgi_input[2];
	int cgi_output[2];
	char method_env[_SIZE_];
	char query_string_env[_SIZE_];
	char content_length_env[_SIZE_];

	printf("[exec_cgi ]method : %s \n", method);

	if (strcasecmp(method, "GET") == 0)
	{
		clear_header(sock);
	}
	else // POST
	{
		do
		{
			ret = get_line(sock, buf, sizeof(buf));
			if (strncasecmp(buf, "Content-Length: ", 16) == 0)
			{
				content_length = atoi(&buf[16]);
				// break               不用 break  即把参数Content-Length获取  又把  空行删除
			}
		}while ((ret > 0) && strcmp(buf, "\n") != 0);

		if (content_length == -1)
		{
			echo_errno(sock);
			return;
		}
	}

	sprintf(buf, "HTTP/1.0 200 OK\r\n\r\n");
	send(sock, buf, strlen(buf), 0);


	// 创建  父子进程之间的 通信管道 cgi_input子进程的读  cgi_output子进程的写 
	if (pipe(cgi_input) < 0)
	{
		echo_errno(sock);
		return;
	}

	if (pipe(cgi_output) < 0)
	{
		echo_errno(sock);
		return;
	}

	pid_t id = fork();
	if (id < 0)
	{
		echo_errno(sock);
		return ;
	}

	if (id == 0)// child
	{
		close(cgi_input[1]);
		close(cgi_output[0]);

		// ////////////////
		// 重定向 管道到  标准输入 和 输出     这样以后 printf()直接打到管道

		dup2(cgi_input[0], 0);
		dup2(cgi_output[1], 1);

		sprintf(method_env, "REQUEST_METHOD=%s", method);
		putenv(method_env);// 注册环境变量 这样 execl 执行二进制程序时时 获取这些参数方便getenv
		
		// GET 要得 参数 在请求字段  中  环境变量注册 quer_string_env
		// post 要的参数在 内容中  所以要知道 内容什么时候截至(内容长度)所以 只要知道content_length_env 就可以了  

		if (strcasecmp(method, "GET") == 0)
		{
			sprintf(query_string_env, "QUERY_STRING=%s", query_string);
			putenv(query_string_env);
		}
		else // post
		{
			sprintf(content_length_env, "CONTENT_LENGTH=%d", content_length);
			putenv(content_length_env);
printf("%d-----------env\n", content_length);	
		}
		// 执行  二进制 程序
		execl(path,path,NULL);
		exit(1);
	}
	else // father
	{
		close(cgi_input[0]);
		close(cgi_output[1]);

		char c = '\0';
		int i = 0;
		printf("%s --fmethod\n", method);
		if (strcasecmp(method, "POST") == 0)
		{
			printf("--father here %d\n", content_length);
			for (; i < content_length; i++)
			{
				recv(sock, &c, 1, 0);
				printf("--%c ", c);
				fflush(stdout);
				write(cgi_input[1], &c, 1);// 给子进程 发过去 
			}
		}

		printf("\n");

		int ret = 0;
		while ((ret = read(cgi_output[0], &c, 1)) > 0)// 子进程退出 文件符号关闭 read读完文件结尾 返回0
		{
			send(sock, &c, 1, 0);// 父进程 负责向sock发送子进程的数据
		}

		waitpid(id, NULL, 0);
		close(sock);
	}
}
Beispiel #6
0
static void * accept_request(void* arg)
{
	int sock = (int)arg;
	printf("%d\n",sock);
	char buf[SIZE];
	int ret = 0;
#ifdef _DEBUG_
	do
	{
			ret = get_line(sock,buf,size);
			printf("%s",buf);
			fflush(stdout);
	}while(ret > 0 && strcmp(buf,'\n'));
#endif
	char method[SIZE / 10];
	char url[SIZE];

	char* query_string = NULL;
	int cgi = 0;
	char path[SIZE];
	memset(method,'\0',sizeof(method));
	memset(url,'\0',sizeof(url));

	ret = get_line(sock,buf,sizeof(buf));
	if(ret < 0)
	{
			echo_errno(sock,1);
			return (void*)1;
	}
	printf("%s\n",buf);
	//1 get method
	//GET //xx//yy HTTP/1.1
	int i = 0;
	int j =0;
	while(i< sizeof(method) - 1 && !isspace(buf[j])  && j < sizeof(buf) )
	{
			method[i]=buf[j];
			++i;
			++j;
	}

	method[i] = '\0';

	//2 check method
	if(strcasecmp(method,"GET")!=0 && strcasecmp(method,"POST") != 0)
	{
			echo_errno(sock,1);
			return (void*)2;
	}

	//3 get url first step space
	while(isspace(buf[j]))
	{
			++j;
	}

	i=0;
	while(!isspace(buf[j])&& (i < sizeof(url)-1) && j < sizeof(buf))
	{
		url[i] = buf [j];
		++i;
		++j;

	}

	if(strcasecmp(method,"POST") == 0)
	{
			cgi = 1;
	}
	printf("method: %s,url_path :%s\n ",method,url);

	if(strcasecmp(method,"GET") == 0)
	{
			query_string = url;
			
	}

	char *start = url;
	while( *start != '\0')
	{
			if( *start == '?')
			{
					cgi = 1;
					*start = '\0';
					query_string = start+1;
					break;
			}

			++start;

	}
	sprintf(path,"htdoc%s",url);
	if(path[strlen(path)-1] == '/')
	{
			strcat(path,"index.html");
	}

	//
	printf("path:%s\n",path);
	printf("cgi:%d\n",cgi);
	//method,query_string,cgi,path
	struct stat st;
	if(stat(path,&st) < 0)//default -> htdoc/index.html
	{
			printf("stat error\n");
			echo_errno(sock,1);
			return (void*)-3;
			
	}
	else
	{
			if(S_ISDIR(st.st_mode))
			{
					strcpy(path,"htdoc/index.html");
			}
			if(( st.st_mode & S_IXGRP)||\
					( st.st_mode & S_IXGRP)||\
					st.st_mode & S_IXOTH)
			{
					cgi = 1;
			}
			else
			{}

			//path cgi
			if(cgi)
			{
					printf("cgi mode\n");
					execut_cgi(sock,path,method,query_string);
			}
			else// 请求首页内容
			{
					clear_head(sock);
					echo_www(sock,path,st.st_size);
			}
	}

	close(sock);   //no face link
	return (void*) 0;
}
Beispiel #7
0
static void execut_cgi(int sock,const char* path,const char* method,const char* query_string)
{
		int content_len = -1;
		char buf[SIZE];
		memset(buf,'\0',sizeof(buf));
		int cgi_input[2];
		int cgi_output[2];
		
		printf("method: %s\n",method);


		if(strcasecmp(method,"GET") == 0)
		{
				clear_head(sock);
		}else  //POST
		{
				printf("aaaaaaaaaaaaaaaa\n");
				int ret = 0;
				do{
						ret = get_line(sock,buf,sizeof(buf));
						if(strncasecmp(buf,"Content-Length: ",16) == 0)
						{
								content_len = atoi(&buf[16]);				
						}
				}while((ret > 0) && strcmp(buf,"\n") != 0);
				printf("contlen:%d\n",content_len);
				if(content_len == -1)
				{
						echo_errno(sock,1);
						return ;
				}
		}
		if(pipe(cgi_output) < 0)
		{
			echo_errno(sock,1);
			return ;
		}
		if(pipe(cgi_input) < 0)
		{
			echo_errno(sock,1);
			return ;
		}

				
		sprintf(buf,"HTTP/1.0 200 OK\r\n\r\n");
		send(sock,buf,strlen(buf),0);
		pid_t id = fork();
		// 处理客户端请求
		if(id == 0)//child
		{
				close(cgi_input[1]);
				close(cgi_output[0]);
		
				dup2(cgi_input[0],0);
				dup2(cgi_output[1],1);
				
				sprintf(buf,"REQUEST_METHOD=%s",method);
				putenv(buf);

				if(strcasecmp(method,"GET") == 0)
				{
						sprintf(buf,"QUERY_STRING=%s",query_string);
						putenv(buf);
				}else
				{
						sprintf(buf,"CONTENT_LENGTH=%d",content_len);
						putenv(buf);
				}
				execl(path,path,NULL);
				exit(1);
		}else  //father
		{
				close(cgi_input[0]);
				close(cgi_output[1]);

				int i=0;
				char c = '\0';
				if(strcasecmp(method,"POST")==0)
				{
						printf("cccccccccccc\n");
						for(;i < content_len;++i)
						{
								recv(sock,&c,1,0);
								write(cgi_input[1],&c,1);
						}
				}
				printf("\n");

				while(read(cgi_output[0],&c,1) > 0)
				{
						send(sock,&c,1,0);
				}

				waitpid(id,NULL,0);
				close(cgi_input[1]);
				close(cgi_output[0]);

		}
}
Beispiel #8
0
void* accept_request(void* arg)
{
    pthread_detach(pthread_self());
    
    int sock = (int)arg;
    char buf[_SIZE_];
    char method[_SIZE_];
    char url[_SIZE_];
    char path[_SIZE_];

    memset(buf, '\0', sizeof(buf));
    memset(method, '\0', sizeof(method));
    memset(url, '\0', sizeof(url));
    memset(path, '\0', sizeof(path));
    
    int cgi = 0;
    int ret = -1;
    char* query_string = NULL;

#ifdef _DEBUG_
    do{
        ret = get_line(sock, buf, sizeof(buf));
        printf("%s", buf);
        fflush(stdout);
    } while((ret > 0) && (strcmp(buf, "\n") != 0));
#endif

    ret = get_line(sock, buf, sizeof(buf));
    if(ret < 0)
    {
        echo_errno(sock);
        return (void *)1;
    }

    //GET          /HTTP/1.1
    int i = 0;     // method index
    int j = 0;     // buf index

    while( (i < sizeof(method)-1) && (j < sizeof(buf)) && (!isspace(buf[j])))
    {
        method[i] = buf[j];
        i++, j++;
    }

    method[i] = '\0';
    while( isspace(buf[j]) )
    {
        j++;
    }

    if(strcasecmp(method, "GET") != 0 && strcasecmp(method, "POST") != 0)
    {
        echo_errno(sock);
        return (void*)2;
    }

    if(strcasecmp(method, "POST") == 0)
    {
        cgi = 1;
    }

    i = 0; // url index
    while( (i<sizeof(url)-1) && (j < sizeof(buf)) && (!isspace(buf[j])))
    {
        url[i] = buf[j];
        i++, j++;
    }

    if(strcasecmp(method, "GET") == 0)
    {
        query_string = url;
        while(*query_string != '\0' && *query_string != '?' )
        {
            query_string++;
        }

        if(*query_string == '?')
        {
            cgi = 1;
            *query_string = '\0';
            query_string++;
        }
    }

    // /     /aa/bb/cc
    sprintf(path, "htdoc%s", url);   // htdoc/
    if(path[strlen(path) - 1] == '/')
    {
        strcat(path, "index.html");
    }

    printf("method: %s\n", method);
    printf("path: %s\n", path);
    printf("query_string: %s\n", query_string);
    
    struct stat st;
    if(stat(path, &st) < 0)
    {
        echo_errno(sock);
        return (void*)3;
    }
    else
    {
        if(S_ISDIR(st.st_mode))
        {
            strcpy(path, "htdoc/index.html");
        }
        else if( (st.st_mode & S_IXUSR) || (st.st_mode & S_IXGRP) || (st.st_mode & S_IXOTH) )
        {
            cgi = 1;
        }
        else
        {}

        if(cgi)
        {
            exec_cgi(sock, path, method, query_string);
        }
        else
        {
            clear_header(sock);
            echo_html(sock, path, st.st_size);
        }
    }

    close(sock);
    return (void*)0;
}
Beispiel #9
0
static void* accept_request(void *arg)		//static
{
	int sock = (int)arg;
	char buf[SIZE];
	int len = sizeof(buf)/sizeof(*buf);
	char method[SIZE/10];
	char url[SIZE];
	char path[SIZE];
	int ret = -1;
	int i = 0;
	int j = 0;

	char *query_string = NULL;    //aim at val(can shu)
	int cgi = 0;
#ifdef _DEBUG_
//	do
//	{
//		ret = get_line(sock, buf, len);
//		printf("%s", buf);
//		fflush(stdout);
//	}while(ret > 0 && (strcmp(buf, "\n") != 0) );
#endif

	memset(buf, '\0', sizeof(buf));
	memset(method, '\0', sizeof(method));
	memset(url, '\0', sizeof(url));
	memset(path, '\0', sizeof(buf));

	//Request Line
	ret = get_line(sock, buf, len);
	if(ret <= 0)
	{
		echo_errno(sock);
		return (void*)1;
	}
	i = 0;	//method index
	j = 0;	//buf index
	while((i < (sizeof(method)/sizeof(*method) - 1)) && (j < sizeof(buf)/sizeof(*buf) - 1) && (!isspace(buf[j]) ) )
	{
		method[i] = buf[j];
		++i;
		++j;
	}
	method[i] = '\0';
	if((strcasecmp(method, "GET") != 0) && (strcasecmp(method, "POST")) )
	{
		//echo_errno(sock);
		return (void*)2;
	}

	//URL
	while(isspace(buf[j]))	//Remove Space
	{
		++j;
	}
	i = 0;
	while( ( i < sizeof(url)/sizeof(*url)-1 ) && (j < sizeof(buf)/sizeof(*buf)) && (!isspace(buf[j])) )
	{
		url[i] = buf[j];
		++i;
		++j;
	}
	url[i] = '\0';

	if( strcasecmp(method, "POST") == 0 )
	{
		cgi = 1;
		sprintf(path, "%s", url+1);
	}

	if( strcasecmp(method, "GET") == 0 )
	{
		query_string = url;
		while( *query_string != '\0' && *query_string != '?' )
		{
			query_string++;
		}
		if(*query_string == '?')
		{
			cgi = 1;
			*query_string = '\0';
			++query_string;
		}
	}

	if( strcasecmp(method, "GET") == 0 )
	{
		sprintf(path, "htdoc%s", url);
		if( path[strlen(path)-1] == '/' )
		{
			strcat(path, "index.html");
		}
	}


	struct stat st;
	if( stat(path, &st) < 0 )
	{
		//echo_errno();	//404	
		return (void*)3;
	}
	else	//case : DIR
	{
		if( S_ISDIR(st.st_mode) )
		{
			strcat(path, "index.html");
		}
		else if( (st.st_mode & S_IXUSR) || (st.st_mode & S_IXGRP) || (st.st_mode & S_IXOTH) )      //bin(binary file)
		{
			cgi = 1;
		}
		else
		{}   //noting to do
	}
	
	printf("!@!#%@^   %s   !@%@^%\n", buf);
	if(cgi) // u+x file
	{
		printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!cgi\n");
		exe_cgi(sock, method, path, query_string);  //cgi mode
	}
	else  //.jpg   .html ...
	{
		printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!www\n");
		clear_header(sock);  //! important!
		echo_www(sock, path, st.st_size);
	}

	close(sock);
	return 0;

	
}
Beispiel #10
0
static void exe_cgi( int sock, const char *method, const char *path, const char *query_string )
{
	char buf[SIZE];
	int content_length = -1;

	//pipe named by child side
	int cgi_input[2];
	int cgi_output[2];
	char method_env[SIZE];
	char query_string_env[SIZE];
	char content_length_env[SIZE];
	char tmpc;
	
	memset(buf, '\0', sizeof(buf));				// ! ! ! ! !  M U S T     I N I T   A R R A Y ! ! !     
	memset(method_env, '\0', sizeof(method_env));
	memset(query_string_env, '\0', sizeof(query_string));
	memset(content_length_env, '\0', sizeof(content_length_env));



	if(strcasecmp(method, "GET") == 0 )
	{
		clear_header(sock);			//"GET" send val by url ,already get
	}

	int ret = 0;
	if(strcasecmp(method, "POST") == 0 )  //different
	{
		do
		{
			memset(buf, '\0', sizeof(buf));
			ret = get_line(sock, buf, sizeof(buf));
			if( strncasecmp(buf, "Content-Length: ", 16) == 0)
			{
				content_length = atoi(&buf[16]);
			}
		}while( (ret > 0) && strcmp(buf, "\n") != 0 );

		printf("content_length = %d\n", content_length);

		if( content_length == -1 )
		{
			echo_errno(sock);  
			return;
		}
	}
/////////////  (8.11)  /////////////////////////////
	
	sprintf(buf, "HTTP/1.0 200 OK\r\n\r\n");
	send(sock, buf, strlen(buf), 0);

	if( pipe(cgi_input) < 0 )
	{
		echo_errno(sock);
		return;
	}
	if( pipe(cgi_output) < 0 )
	{
		echo_errno(sock);
		return;
	}

	pid_t id = fork();
	if(id == 0)		//child
	{
		close(cgi_input[1]);
		close(cgi_output[0]);
  
		dup2(cgi_input[0], 0);
		dup2(cgi_output[1], 1);


		sprintf(method_env, "REQUEST_METHOD=%s", method);
		putenv(method_env);
		if( strcasecmp(method, "GET") == 0 )		//GET	
		{
			sprintf(query_string_env, "QUERY_STRING=%s", query_string);
			putenv(query_string_env);
		}
		else  //POST
		{
			sprintf(content_length_env, "CONTENT_LENGTH=%d", content_length);
			putenv(content_length_env);
		}
		execl(path, path, NULL);
		//run here , execl wrong
		exit(1);
	}
	else  //father
	{
		close(cgi_input[0]);
		close(cgi_output[1]);
		
	//	dup2(cgi_input[1], 1);
	//	dup2(cgi_output[0], 0);

		char c = '\0';
		int  i =0;

		if( strcasecmp(method, "POST") == 0 )
		{
			for(; i < content_length; ++i)  
			{
				recv(sock, &c, 1, 0);
				printf("%c", c);
				write(cgi_input[1], &c, 1);
			}
		}
		
		int ret = 0;
		while( read(cgi_output[0], &c, 1) > 0)
		{
			send(sock, &c, 1, 0);
		}

		waitpid(id, NULL, 0);
	}

}