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

📄 httpconn.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/** * @file httpmethod.c HTTP connection method * * purple * * Purple is the legal property of its developers, whose names are too numerous * to list here.  Please refer to the COPYRIGHT file distributed with this * source distribution. * * 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 */#include "msn.h"#include "debug.h"#include "httpconn.h"typedef struct{	MsnHttpConn *httpconn;	char *body;	size_t body_len;} MsnHttpQueueData;static voidmsn_httpconn_process_queue(MsnHttpConn *httpconn){	httpconn->waiting_response = FALSE;	if (httpconn->queue != NULL)	{		MsnHttpQueueData *queue_data;		queue_data = (MsnHttpQueueData *)httpconn->queue->data;		httpconn->queue = g_list_remove(httpconn->queue, queue_data);		msn_httpconn_write(queue_data->httpconn,						   queue_data->body,						   queue_data->body_len);		g_free(queue_data->body);		g_free(queue_data);	}}static gbooleanmsn_httpconn_parse_data(MsnHttpConn *httpconn, const char *buf,						size_t size, char **ret_buf, size_t *ret_size,						gboolean *error){	const char *s, *c;	char *header, *body;	const char *body_start;	char *tmp;	size_t body_len = 0;	gboolean wasted = FALSE;	g_return_val_if_fail(httpconn != NULL, FALSE);	g_return_val_if_fail(buf      != NULL, FALSE);	g_return_val_if_fail(size      > 0,    FALSE);	g_return_val_if_fail(ret_buf  != NULL, FALSE);	g_return_val_if_fail(ret_size != NULL, FALSE);	g_return_val_if_fail(error    != NULL, FALSE);#if 0	purple_debug_info("msn", "HTTP: parsing data {%s}\n", buf);#endif	/* Healthy defaults. */	body = NULL;	*ret_buf  = NULL;	*ret_size = 0;	*error    = FALSE;	/* First, some tests to see if we have a full block of stuff. */	if (((strncmp(buf, "HTTP/1.1 200 OK\r\n", 17) != 0) &&		 (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) != 0)) &&		((strncmp(buf, "HTTP/1.0 200 OK\r\n", 17) != 0) &&		 (strncmp(buf, "HTTP/1.0 100 Continue\r\n", 23) != 0)))	{		*error = TRUE;		return FALSE;	}	if (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) == 0)	{		if ((s = strstr(buf, "\r\n\r\n")) == NULL)			return FALSE;		s += 4;		if (*s == '\0')		{			*ret_buf = g_strdup("");			*ret_size = 0;			msn_httpconn_process_queue(httpconn);			return TRUE;		}		buf = s;		size -= (s - buf);	}	if ((s = strstr(buf, "\r\n\r\n")) == NULL)		/* Need to wait for the full HTTP header to arrive */		return FALSE;	s += 4; /* Skip \r\n */	header = g_strndup(buf, s - buf);	body_start = s;	body_len = size - (body_start - buf);	if ((s = purple_strcasestr(header, "Content-Length: ")) != NULL)	{		int tmp_len;		s += strlen("Content-Length: ");		if ((c = strchr(s, '\r')) == NULL)		{			g_free(header);			return FALSE;		}		tmp = g_strndup(s, c - s);		tmp_len = atoi(tmp);		g_free(tmp);		if (body_len != tmp_len)		{			/* Need to wait for the full packet to arrive */			g_free(header);#if 0			purple_debug_warning("msn",							   "body length (%d) != content length (%d)\n",							   body_len, tmp_len);#endif			return FALSE;		}	}	body = g_malloc0(body_len + 1);	memcpy(body, body_start, body_len);#ifdef MSN_DEBUG_HTTP	purple_debug_misc("msn", "Incoming HTTP buffer (header): {%s\r\n}\n",					header);#endif	/* Now we should be able to process the data. */	if ((s = purple_strcasestr(header, "X-MSN-Messenger: ")) != NULL)	{		char *full_session_id, *gw_ip, *session_action;		char *t, *session_id;		char **elems, **cur, **tokens;		full_session_id = gw_ip = session_action = NULL;		s += strlen("X-MSN-Messenger: ");		if ((c = strchr(s, '\r')) == NULL)		{			msn_session_set_error(httpconn->session,								  MSN_ERROR_HTTP_MALFORMED, NULL);			purple_debug_error("msn", "Malformed X-MSN-Messenger field.\n{%s}",							 buf);			g_free(body);			return FALSE;		}		tmp = g_strndup(s, c - s);		elems = g_strsplit(tmp, "; ", 0);		for (cur = elems; *cur != NULL; cur++)		{			tokens = g_strsplit(*cur, "=", 2);			if (strcmp(tokens[0], "SessionID") == 0)				full_session_id = tokens[1];			else if (strcmp(tokens[0], "GW-IP") == 0)				gw_ip = tokens[1];			else if (strcmp(tokens[0], "Session") == 0)				session_action = tokens[1];			else				g_free(tokens[1]);			g_free(tokens[0]);			/* Don't free each of the tokens, only the array. */			g_free(tokens);		}		g_strfreev(elems);		g_free(tmp);		if ((session_action != NULL) && (strcmp(session_action, "close") == 0))			wasted = TRUE;		g_free(session_action);		t = strchr(full_session_id, '.');		session_id = g_strndup(full_session_id, t - full_session_id);		if (!wasted)		{			g_free(httpconn->full_session_id);			httpconn->full_session_id = full_session_id;			g_free(httpconn->session_id);			httpconn->session_id = session_id;			g_free(httpconn->host);			httpconn->host = gw_ip;		}		else		{			MsnServConn *servconn;			/* It's going to die. */			/* poor thing */			servconn = httpconn->servconn;			/* I'll be honest, I don't fully understand all this, but this			 * causes crashes, Stu. */			/* if (servconn != NULL)				servconn->wasted = TRUE; */			g_free(full_session_id);			g_free(session_id);			g_free(gw_ip);		}	}	g_free(header);	*ret_buf  = body;	*ret_size = body_len;	msn_httpconn_process_queue(httpconn);	return TRUE;}static voidread_cb(gpointer data, gint source, PurpleInputCondition cond){	MsnHttpConn *httpconn;	MsnServConn *servconn;	MsnSession *session;	char buf[MSN_BUF_LEN];	char *cur, *end, *old_rx_buf;	int len, cur_len;	char *result_msg = NULL;	size_t result_len = 0;	gboolean error = FALSE;	httpconn = data;	servconn = NULL;	session = httpconn->session;	len = read(httpconn->fd, buf, sizeof(buf) - 1);	if (len < 0 && errno == EAGAIN)		return;	else if (len <= 0)	{		purple_debug_error("msn", "HTTP: Read error\n");		msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ);		return;	}	buf[len] = '\0';	httpconn->rx_buf = g_realloc(httpconn->rx_buf, len + httpconn->rx_len + 1);	memcpy(httpconn->rx_buf + httpconn->rx_len, buf, len + 1);	httpconn->rx_len += len;	if (!msn_httpconn_parse_data(httpconn, httpconn->rx_buf, httpconn->rx_len,								 &result_msg, &result_len, &error))	{		/* Either we must wait for more input, or something went wrong */		if (error)			msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ);		return;	}	httpconn->servconn->processing = FALSE;	servconn = httpconn->servconn;	if (error)	{		purple_debug_error("msn", "HTTP: Special error\n");		msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ);		return;	}	g_free(httpconn->rx_buf);	httpconn->rx_buf = NULL;	httpconn->rx_len = 0;	if (result_len == 0)	{		/* Nothing to do here */#if 0		purple_debug_info("msn", "HTTP: nothing to do here\n");#endif		g_free(result_msg);		return;	}	g_free(servconn->rx_buf);	servconn->rx_buf = result_msg;	servconn->rx_len = result_len;	end = old_rx_buf = servconn->rx_buf;	servconn->processing = TRUE;	do	{		cur = end;		if (servconn->payload_len)		{			if (servconn->payload_len > servconn->rx_len)				/* The payload is still not complete. */				break;			cur_len = servconn->payload_len;			end += cur_len;		}		else		{			end = strstr(cur, "\r\n");			if (end == NULL)				/* The command is still not complete. */				break;			*end = '\0';			end += 2;			cur_len = end - cur;		}		servconn->rx_len -= cur_len;		if (servconn->payload_len)		{			msn_cmdproc_process_payload(servconn->cmdproc, cur, cur_len);			servconn->payload_len = 0;		}		else		{			msn_cmdproc_process_cmd_text(servconn->cmdproc, cur);		}	} while (servconn->connected && servconn->rx_len > 0);	if (servconn->connected)	{		if (servconn->rx_len > 0)			servconn->rx_buf = g_memdup(cur, servconn->rx_len);		else

⌨️ 快捷键说明

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