⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 http.c

📁 linux下支持P2P的客户端程序,采用了Gnutella的方法,其中有实现Gnutella的具体源码,是一个基于p2p环境下的音乐共享软件,有助于对P2P的研究
💻 C
字号:
/*-*-linux-c-*-*//* *  gnewtellium - Newtella for Unix *  Copyright (C) 2001 Elias Athanasopoulos * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *//* HTTP header build/parse functions */#include <stdlib.h>#include <string.h>#include <gtk/gtk.h>#include "http.h"#include "memory.h"char *http_header_build(struct http_header *http){	char *http_string = NULL;	switch (http->func) {	case HTTP_RESPONSE:		/* HTTP 200 = OK */		if (http->code == 200) {			http_string = newtella_malloc(HTTP_RESPONSE_SIZE);					g_snprintf(http_string, HTTP_RESPONSE_SIZE,				   "HTTP/1.1 200 OK\r\n"				   "Server: %s\r\n"				   "Content-type: mp3\r\n"				   "Content-length: %u\r\n\r\n", 				   http->user_agent, http->content_length);		}		/* HTTP 404 = Not Found */		if (http->code == 404) {			http_string = newtella_malloc(HTTP_RESPONSE_SIZE);			g_snprintf(http_string, HTTP_RESPONSE_SIZE,				   "HTTP/1.1 404 Not Found\r\n"				   "Server: %s\r\n\r\n", http->user_agent);		}		/* HTTP 503 = Busy */		if (http->code == 503) {			http_string = newtella_malloc(HTTP_RESPONSE_SIZE);			g_snprintf(http_string, HTTP_RESPONSE_SIZE,				   "HTTP/1.1 503 Server is busy\r\n"				   "Server: %s\r\n\r\n", http->user_agent);		}		break;	case HTTP_GET:		http_string = newtella_malloc(HTTP_GET_SIZE + strlen(http->file_name));			g_snprintf(http_string, HTTP_GET_SIZE + strlen(http->file_name),			   "GET /get/%i/%s HTTP/1.0\r\n"			   "Connection: Keep-Alive\r\n"			   "Range: bytes=%u-\r\n"			   "User-Agent: %s\r\n\r\n", 			   http->file_index, http->file_name, http->range_start, 			   http->user_agent);		break;	case HTTP_GIV:		/* remember that we add 16 bytes for the guid */		http_string = newtella_malloc(HTTP_GIV_SIZE + strlen(http->file_name) + 16);	       		g_snprintf(http_string, HTTP_GIV_SIZE + strlen(http->file_name) + 16,			   "GIV %d:%s/%s\n\n", 			   http->file_index, http->guid, http->file_name);				break;	}		return http_string; }int http_header_size(char *buf){	/* Returns the size of an HTTP header.	   A 'valid' header must end in a '\r\n\r\n'.	   If we don't find the double '\r\n' we	   return 0.	*/        char *seek, *tmp = buf;        int buf_size = strlen(buf);try_again:        seek = memchr(tmp, '\r', buf_size);        if (!seek)                return 0;        if (!memcmp(seek, "\r\n\r\n", 4))                return (seek-buf)+4;        else {                tmp = seek + 1;                goto try_again;        }}int http_giv_size(char *buf){	/* Returns the size of a GIV header.	   A 'valid' header must end in a '\n\n'.	   If we don't find the double '\n' we	   return 0.	*/        char *seek, *tmp = buf;        int buf_size = strlen(buf);try_again:        seek = memchr(tmp, '\n', buf_size);        if (!seek)                return 0;        if (!memcmp(seek, "\n\n", 2))                return (seek-buf)+2;        else {                tmp = seek + 1;                goto try_again;        }}char *http_extract_var(const char *tag, char *buf){	/* This function returns the value of a specific tag (i.e. Server) 	   of an HTTP header response. It's very kludgy but it works. :-) 	   I'll try to add lots of comments because in a week I will be totaly 	   unaware of how it works.	   Consider: foo: bar\r\n	   	   bar = http_extract_var("foo", http_buffer);	*/        char *v, *n, *seek;        char *tmp;        int buf_size = http_header_size(buf);	int parsed = 0;		/* a temp buffer to copy the HTTP header, cause	   we want to manipulate its contents */        tmp = newtella_malloc(buf_size);        memcpy(tmp, buf, buf_size);          seek = tmp;	try_again:	/* find the first '\n'. there is great possibility that	   the next byte is the start of the wanted tag. if we	   don't find any '\n's the wanted tag doesn't exist, so	   we return null */		if (parsed == buf_size)		return NULL;		n = memchr(seek, '\n', buf_size);        if (!n)                return NULL;                        *n = '\0'; n++;	parsed = (n - tmp);	/* find the first ':' after an '\n' in order to isolate	   the _tag_ */		v = memchr(n, ':', buf_size-parsed);		if (!v)                return NULL;        *v = '\0'; v++; 	parsed = (v - tmp);	/* is it the tag we wanted? if yes isolate the _value_	   otherwise start again from where we stopped	   	   infinite loop is not possible because we return	   null if we don't find either an '\n' or an ':'	*/        if (!g_strncasecmp(tag, n, strlen(tag))) {		seek = memchr(v, '\r', buf_size-parsed);		*seek = '\0';        } else                goto try_again;        	/* copy the value in a new buffer, in order to return	   it, and free the temporary one. The increment is for	   the space after the ':' */	n = newtella_malloc(strlen(++v)+1);	strcpy(n, v);	newtella_free(tmp);        return n;}struct http_header *http_header_parse(char *http_string){	struct http_header *http = newtella_malloc(sizeof(struct http_header));	gchar *p;	/* Try to parse the header. It might *not* be a 	   complete or a valid header. If we return 	   the http structure with valid=1, then this means	   that we parsed it all correctly.	   Remember: \r\n\r\n (double) means end of the	   HTTP message.	*/	http->valid = 0;	if (!memcmp(http_string, "HTTP", 4))		goto parse_response;	else 		if (!memcmp(http_string, "GET ", 4))			goto parse_get;	else 		if (!memcmp(http_string, "GIV ", 4))			goto parse_giv;		 parse_response:	/* get the HTTP code */	http_string = memchr(http_string, ' ', strlen(http_string));	http_string++;	http->code = atoi(http_string);	switch (http->code) {		/* OK */	case 200:  		/* get the server */		http->user_agent = http_extract_var("Server", http_string);	     	/* get the content type */		http->content_type = http_extract_var("Content-type", http_string);		/* get the content length */		http->content_length = atol(http_extract_var("Content-length", http_string));		/* get the content range start -- Content-Range: bytes= */	       		p = http_extract_var("Content-Range", http_string);		if (p)			http->range_start = atol(p+6);		                /* not very safe */		if (http->content_length)			http->valid = 1;		   		break;		/* RESUME */	case 206:                /* get the server */		http->user_agent = http_extract_var("Server", http_string);	     	/* get the content type */		http->content_type = http_extract_var("Content-type", http_string);		/* get the content length */		http->content_length = atol(http_extract_var("Content-length" , http_string));		/* get the content range start -- Content-Range: bytes= */		http->range_start = atol(http_extract_var("Content-Range", http_string)+6);		/* not very safe */		if (http->content_length)			http->valid = 1;			break;		/* BUSY */	case 404:		http->user_agent = http_extract_var("Server", http_string);		http->valid = 1;		break;	case 503:		http->user_agent = http_extract_var("Server", http_string);		http->valid = 1;		break;	default:		http->valid = 0;		break;	}		return http;	 parse_get:	/* GET /get/file_index/file_name HTTP/1.0\r\n */	http->file_index = atoi(http_string + 9);	if (http->file_index) {    		/* get the file name */		char *seek, *range_str = NULL;		int   step = 0;		seek = strchr(http_string + 9, '/');		if (!seek)			return http;		seek++;		while (*seek++ != ' ') {			step++;					/* not found */			if (*seek == '\0')				return http;		}		http->file_name = newtella_malloc(step + 1);		memcpy(http->file_name, seek-step, step);		/* Connection: Keep-Alive */		http->connection = http_extract_var("Connection", seek);	       	/* get range */		range_str = http_extract_var("Range", seek);		if (range_str) {			/* parse the range string */			seek = strchr(range_str, '=');			if (!seek) 				return http;			http->range_start = atol(seek++);			seek = strchr(seek, '-');			http->range_end = atol(seek++);			http->valid = 1;		}		return http;	} parse_giv:	/* TODO */	return http;} 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -