Ejemplo n.º 1
0
int main(int argc, char **argv)
{
	int sockfd;
	struct sockaddr_in servaddr;
	static char s[MAXLINE];

	opsbuild(argc, argv);
	if (argc == 2 )
	  snprintf(s,MAXLINE,"action=ActionToDo&hash=3ad540e4c39f54d0d138c60d66c1d923&ActionTag=%s&ActionRows=6&\r\n",argv[1]);
	else if (argc == 3 )
	  snprintf(s,MAXLINE,"action=ActionToDo&hash=3ad540e4c39f54d0d138c60d66c1d923&ActionTag=%s&ActionRows=%s&\r\n",argv[1],argv[2]);
	else
	  snprintf(s,MAXLINE,"action=ActionToDo&hash=3ad540e4c39f54d0d138c60d66c1d923&ActionTag=%s&ActionRows=2&\r\n","none");



	char **pptr;
	//********** You can change. Puy any values here *******
	char *hname = "dev.mchirico.org";
	char *page = "/cron/fireAction";
	/*	char *poststr = "action=ActionToDo&hash=3ad540e4c39f54d0d138c60d66c1d923&\r\n";  */
	char *poststr = s; 
	fprintf(stderr,"poststr=%s\n",poststr);
	//*******************************************************

	char str[50];
	struct hostent *hptr;
	if ((hptr = gethostbyname(hname)) == NULL) {
		fprintf(stderr, " gethostbyname error for host: %s: %s",
			hname, hstrerror(h_errno));
		exit(1);
	}
	printf("hostname: %s\n", hptr->h_name);
	if (hptr->h_addrtype == AF_INET
	    && (pptr = hptr->h_addr_list) != NULL) {
		printf("address: %s\n",
		       inet_ntop(hptr->h_addrtype, *pptr, str,
				 sizeof(str)));
	} else {
		fprintf(stderr, "Error call inet_ntop \n");
	}

	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(80);
	inet_pton(AF_INET, str, &servaddr.sin_addr);

	connect(sockfd, (SA *) & servaddr, sizeof(servaddr));
	process_http(sockfd, hname, page, poststr);
	close(sockfd);
	exit(0);

}
Ejemplo n.º 2
0
static void http_client_loop(struct http_thread_env *hte)
{
	gchar *line = NULL;
	gsize nbyte = 0;
	HttpRequest *req = NULL;
	gint n;

	while ((n = getline(&line, &nbyte, hte->fp)) >= 0) {
		line[n] = '\0';
		if (n && line[n - 1] == '\n') line[--n] = '\0';
		if (n && line[n - 1] == '\r') line[--n] = '\0';

		if (n) mbb_log_lvl(MBB_LOG_HTTP, "recv: %s", line);

		if (req == NULL) {
			if ((req = http_request_new(line)) == NULL) {
				push_http_msg(hte, MBB_MSG_INVALID_HEADER, line);
				break;
			}

			if (! parse_url(req->url, &hte->json, &hte->method)) {
				push_http_error_msg(hte, "invalid url %s", req->url);
				break;
			}
		} else if (n) {
			if (http_request_add_header(req, line) == FALSE) {
				mbb_log_lvl(MBB_LOG_HTTP, "invalid header");
				push_http_msg(hte, MBB_MSG_INVALID_HEADER, line);
				break;
			}
		} else {
			if (req->method == HTTP_METHOD_POST) {
				if (process_http_body(hte, req) == FALSE)
					break;
			}

			process_http(hte, req);
			break;
		}
	}

	if (req != NULL)
		http_request_free(req);

	if (hte->root_tag != NULL) {
		xml_tag_free(hte->root_tag);
		hte->root_tag = NULL;
	}

	g_free(line);
}
Ejemplo n.º 3
0
int main (int argc, const char * argv[]) {
	http_connection connection;
	int port = 80;
	
	connection.context = 0;
	
	start_listener(port);
	start_event_queue();
	
	for(int i = 0; i < 1000; i++)
		process_http(&connection);
	
    return 0;
}
Ejemplo n.º 4
0
int main(void)
{
    int sockfd;
    struct sockaddr_in servaddr;
 
    char **pptr;
    char *hname = "gcm-http.googleapis.com";
    char *page = "/gcm/send";
    char *poststr = "{ \"notification\": {"
                           "\"title\": \"Warning\","
                           "\"text\": \"Someone is coming now!\","
                           "\"icon\": \"@mipmap/ic_launcher\" },"
                       "\"to\" : \""
                            "fDfdcUtacEI:APA91bFVPoGj0z2xWYe4O5wdLkD2bfCFAkDidv_v86g-Ngli6w0ugwPOvVcyyflV8jV9Sdz86PSFk_fEtESEIgE55lxHt4LTfrnZ1ho3754mFqn-Gj0pSBXQsqFMyFhbzTXrJ04o7urK"
                       "\"}\r\n";
 
 
 
    char str[50];
    struct hostent *hptr;
    if ((hptr = gethostbyname(hname)) == NULL) {
        fprintf(stderr, " gethostbyname error for host: %s: %s",
                hname, hstrerror(h_errno));
        exit(1);
    }
    printf("hostname: %s\n", hptr->h_name);
    if (hptr->h_addrtype == AF_INET
            && (pptr = hptr->h_addr_list) != NULL) {
        printf("address: %s\n",
                inet_ntop(hptr->h_addrtype, *pptr, str,
                    sizeof(str)));
    } else {
        fprintf(stderr, "Error call inet_ntop \n");
    }
 
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(80);
    inet_pton(AF_INET, str, &servaddr.sin_addr);
 
    printf("connection...\n");
    connect(sockfd, (SA *) & servaddr, sizeof(servaddr));
    printf("process http...\n---------------------------\n%s\n----------------------\n",poststr);
    process_http(sockfd, hname, page, poststr);
    close(sockfd);
    exit(0);
 
}
Ejemplo n.º 5
0
char* sendPost(char *hostName, int port, char *page, char *postString) {
    int sockfd;
    struct sockaddr_in servaddr;

    char **pptr;
    char *response = NULL;
    char str[50];
    struct hostent *hptr;

    //TODO: Still have to make all the checks if connect fails etc.
    if ((hptr = gethostbyname(hostName)) == NULL) {
        fprintf(stderr, " gethostbyname error for host: %s: %s", hostName,
                hstrerror(h_errno));
        return NULL;
    }

    //printf("hostname: %s\n", hptr->h_name);

    if (hptr->h_addrtype == AF_INET && (pptr = hptr->h_addr_list) != NULL) {
        //printf("address: %s\n", inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str)));
        inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str));
    } else {
        fprintf(stderr, "Error call inet_ntop \n");
    }

    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(port);
    inet_pton(AF_INET, str, &servaddr.sin_addr);

    connect(sockfd, (SA *) &servaddr, sizeof(servaddr));

    if ((response = process_http(sockfd, hostName, page, postString)) == NULL) {
        close(sockfd);
        free(response);
        return NULL; //false.
    }

    close(sockfd);

    //The response contains the server HTML answer, the receiver MUST free it or will leak.
    return response;
}
Ejemplo n.º 6
0
void tcp_stream_handle(void * data)
{
    struct skb_buf* skb=(struct skb_buf*)data;
    switch(skb->result)
    {
    case RESULT_FROM_CLIENT:
    case RESULT_FROM_SERVER:
        //debug_log("!!!!!!seq %lu len %d",skb->seq ,skb->data_len);
        process_http(skb , http_session_handle);
        break;
    case RESULT_IGNORE:
        //debug_log("~~~~seq %lu len %d",skb->seq ,skb->data_len);
        nfq_set_verdict(gqh, skb->packet_id, NF_ACCEPT, skb->pload_len, skb->pload);
        break;
    case RESULT_CACHE:
    default:
        break;
    }


}
Ejemplo n.º 7
0
unsigned int sockroutine(int s_listen, acetables *g_ape)
{
	int basemem = 512, epoll_fd;

	struct epoll_event ev, *events;

	int new_fd, nfds, sin_size = sizeof(struct sockaddr_in), i;
	
	struct timeval t_start, t_end;	
	unsigned int ticks = 0;
	struct sockaddr_in their_addr;
	
	
	connection *co = xmalloc(sizeof(*co) * basemem);

	epoll_fd = epoll_create(1); /* the param is not used */
	
	if (epoll_fd < 0) {
		printf("[ERR] Not enougth memory\n");
		exit(0);		
	}
	
	g_ape->epoll_fd = &epoll_fd;
	
	events = xmalloc(sizeof(*events) * basemem);
	
	g_ape->bufout = xmalloc(sizeof(struct _socks_bufout) * basemem);

	setnonblocking(s_listen);
	
	ev.events = EPOLLIN | EPOLLET | EPOLLPRI;
	ev.data.fd = s_listen;
	epoll_ctl(epoll_fd, EPOLL_CTL_ADD, s_listen, &ev);
	
	while (1) {
		
		/* Linux 2.6.25 provide a fd-driven timer system. It could be usefull to implement */
		gettimeofday(&t_start, NULL);
		
		nfds = epoll_wait(epoll_fd, events, basemem, (1000/TICKS_RATE)-ticks);
		
		if (nfds < 0) {
			continue;
		}
		if (nfds > 0) {
			
			for (i = 0; i < nfds; i++) {

				if (events[i].data.fd == s_listen) {
				
					while (1) {
						struct epoll_event cev;
						http_state http = {0, HTTP_NULL, 0, -1, 0, 0, 0};
					
						new_fd = accept(s_listen, 
							(struct sockaddr *)&their_addr, 
							(unsigned int *)&sin_size);
					
						if (new_fd == -1) {
							break;
						}
						
						if (new_fd + 4 == basemem) {
							/* Increase connection & events size */
							growup(&basemem, &co, &events, &g_ape->bufout);
						}

						strncpy(co[new_fd].ip_client, inet_ntoa(their_addr.sin_addr), 16);
						
						co[new_fd].buffer.data = xmalloc(sizeof(char) * (DEFAULT_BUFFER_SIZE + 1));
						co[new_fd].buffer.size = DEFAULT_BUFFER_SIZE;
						co[new_fd].buffer.length = 0;
					
						co[new_fd].http = http;
						co[new_fd].attach = NULL;
						
						co[new_fd].stream_type = STREAM_IN;
					
						g_ape->bufout[new_fd].fd = new_fd;
						g_ape->bufout[new_fd].buf = NULL;
						g_ape->bufout[new_fd].buflen = 0;
						g_ape->bufout[new_fd].allocsize = 0;
						
						setnonblocking(new_fd);

						cev.events = EPOLLIN | EPOLLET | EPOLLPRI | EPOLLOUT;
						cev.data.fd = new_fd;
					
						epoll_ctl(epoll_fd, EPOLL_CTL_ADD, new_fd, &cev);
						
					
					}
					continue;
				} else {
					int readb = 0;
					
					if (events[i].events & EPOLLOUT) {
						if (co[events[i].data.fd].stream_type == STREAM_OUT && 
						((ape_proxy *)(co[events[i].data.fd].attach))->state == PROXY_IN_PROGRESS) {
							int serror = 0, ret;
							socklen_t serror_len = sizeof(serror);
						
							ret = getsockopt(events[i].data.fd, SOL_SOCKET, SO_ERROR, &serror, &serror_len);
							
							if (ret == 0 && serror == 0) {
								((ape_proxy *)(co[events[i].data.fd].attach))->state = PROXY_CONNECTED;
								((ape_proxy *)(co[events[i].data.fd].attach))->sock.fd = events[i].data.fd;
								proxy_onevent((ape_proxy *)(co[events[i].data.fd].attach), "CONNECT", g_ape);
							} else { /* This can be happen ? epoll seems set EPOLLIN as if the host is disconnecting */
								((ape_proxy *)(co[events[i].data.fd].attach))->state = PROXY_THROTTLED;
								//epoll_ctl(epoll_fd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
								clear_buffer(&co[events[i].data.fd]);
								close(events[i].data.fd);
							}

						} else if (co[events[i].data.fd].stream_type == STREAM_IN && g_ape->bufout[events[i].data.fd].buf != NULL) {

							if (sendqueue(events[i].data.fd, g_ape) == 1) {
								if (co[events[i].data.fd].attach != NULL && ((subuser *)(co[events[i].data.fd].attach))->burn_after_writing) {
									do_died((subuser *)(co[events[i].data.fd].attach));
									((subuser *)(co[events[i].data.fd].attach))->burn_after_writing = 0;
								}
							}
						}
					}
					if (events[i].events & EPOLLIN) {
						do {
							/*
								TODO : Check if maximum data read can improve perf
								Huge data may attempt to increase third parameter
							*/
							readb = read(events[i].data.fd, 
										co[events[i].data.fd].buffer.data + co[events[i].data.fd].buffer.length, 
										co[events[i].data.fd].buffer.size - co[events[i].data.fd].buffer.length);
						
						
							if (readb == -1 && errno == EAGAIN) {
							
								/*
									Nothing to read again
								*/
							
								if (co[events[i].data.fd].stream_type == STREAM_OUT) {
									
										proxy_process_eol(&co[events[i].data.fd], g_ape);
										co[events[i].data.fd].buffer.length = 0;
								} else {
									co[events[i].data.fd].buffer.data[co[events[i].data.fd].buffer.length] = '\0';
								}
								break;
							} else {
								if (readb < 1) {

									#if 0
									TODO :
									if (events[i].events & EPOLLRDHUP) {
										/* 
										   Client hangup the connection (half-closed)
										*/
									}
									#endif
									if (co[events[i].data.fd].stream_type == STREAM_IN && co[events[i].data.fd].attach != NULL) {
									
										if (events[i].data.fd == ((subuser *)(co[events[i].data.fd].attach))->fd) {
											((subuser *)(co[events[i].data.fd].attach))->headers_sent = 0;
											((subuser *)(co[events[i].data.fd].attach))->state = ADIED;
										}
										if (((subuser *)(co[events[i].data.fd].attach))->wait_for_free == 1) {
											free(co[events[i].data.fd].attach);
											co[events[i].data.fd].attach = NULL;						
										}
									} else if (co[events[i].data.fd].stream_type == STREAM_OUT) {
									
										if (((ape_proxy *)(co[events[i].data.fd].attach))->state == PROXY_TOFREE) {
											free(co[events[i].data.fd].attach);
											co[events[i].data.fd].attach = NULL;								
										} else {
									
											((ape_proxy *)(co[events[i].data.fd].attach))->state = PROXY_THROTTLED;
											proxy_onevent((ape_proxy *)(co[events[i].data.fd].attach), "DISCONNECT", g_ape);
										}
									}
								
									clear_buffer(&co[events[i].data.fd]);
								
									if (g_ape->bufout[events[i].data.fd].buf != NULL) {
										free(g_ape->bufout[events[i].data.fd].buf);
										g_ape->bufout[events[i].data.fd].buflen = 0;
										g_ape->bufout[events[i].data.fd].buf = NULL;
										g_ape->bufout[events[i].data.fd].allocsize = 0;
									}
									
									close(events[i].data.fd);
							
									break;
								} else if (co[events[i].data.fd].http.ready != -1) {
									co[events[i].data.fd].buffer.length += readb;

									if (co[events[i].data.fd].buffer.length == co[events[i].data.fd].buffer.size) {
										co[events[i].data.fd].buffer.size *= 2;
										co[events[i].data.fd].buffer.data = xrealloc(co[events[i].data.fd].buffer.data, 
																sizeof(char) * (co[events[i].data.fd].buffer.size + 1));
									
									}
									if (co[events[i].data.fd].stream_type == STREAM_IN) {
										process_http(&co[events[i].data.fd]);
								
										if (co[events[i].data.fd].http.ready == 1) {
											co[events[i].data.fd].attach = checkrecv(co[events[i].data.fd].buffer.data, 
																events[i].data.fd, g_ape, co[events[i].data.fd].ip_client);
									
											co[events[i].data.fd].buffer.length = 0;
											co[events[i].data.fd].http.ready = -1;
			
										} else if (co[events[i].data.fd].http.error == 1) {
											shutdown(events[i].data.fd, 2);
										}
									}
								}
						
							}
					
						} while(readb >= 0);
					}
				}			
			}
		}
		
		gettimeofday(&t_end, NULL);

		ticks += (1000*(t_end.tv_sec - t_start.tv_sec))+((t_end.tv_usec - t_start.tv_usec)/1000);
		
		/* Tic tac, tic tac :-) */
		if (ticks >= 1000/TICKS_RATE) {
			ape_proxy *proxy = g_ape->proxy.list;
			int psock;
			
			ticks = 0;
			
			while (proxy != NULL) {

				if (proxy->state == PROXY_NOT_CONNECTED && ((psock = proxy_connect(proxy, g_ape)) != 0)) {
					http_state http_s = {0, HTTP_NULL, 0, -1, 0, 0, 0};
					if (psock + 4 == basemem) {
						growup(&basemem, &co, &events, &g_ape->bufout);
					}
					co[psock].ip_client[0] = '\0';
					co[psock].buffer.data = xmalloc(sizeof(char) * (DEFAULT_BUFFER_SIZE + 1));
					co[psock].buffer.size = DEFAULT_BUFFER_SIZE;
					co[psock].buffer.length = 0;
				
					co[psock].http = http_s;
					co[psock].attach = proxy;
					co[psock].stream_type = STREAM_OUT;
				}


				proxy = proxy->next;
			}
			
			process_tick(g_ape);
		}                

	}

	close(epoll_fd);
	return 0;
}
Ejemplo n.º 8
0
/* Just a lightweight http request processor */
void process_http(ape_socket *co, acetables *g_ape)
{
	ape_buffer *buffer = &co->buffer_in;
	http_state *http = co->parser.data;
	ape_parser *parser = &co->parser;
	
	char *data = buffer->data;
	int pos, read, p = 0;
	
	if (buffer->length == 0 || parser->ready == 1 || http->error == 1) {
		return;
	}

	/* 0 will be erased by the next read()'ing loop */
	data[buffer->length] = '\0';
	
	data = &data[http->pos];
	
	if (*data == '\0') {
		return;
	}
	
	/* Update the address of http->data and http->uri if buffer->data has changed (realloc) */
	if (http->buffer_addr != NULL && buffer->data != http->buffer_addr) {
		if (http->data != NULL) http->data = &buffer->data[(void *)http->data - (void *)http->buffer_addr];
		if (http->uri != NULL) http->uri = &buffer->data[(void *)http->uri - (void *)http->buffer_addr];
		http->buffer_addr = buffer->data;
	}
	
	switch(http->step) {
		case 0:
			pos = seof(data, '\n');
			if (pos == -1) {
				return;
			}
			
			switch(*(unsigned int *)data) {
#ifdef _LITTLE_ENDIAN
				case 0x20544547: /* GET + space */
#endif
#ifdef _BIG_ENDIAN
				case 0x47455420: /* GET + space */
#endif
					http->type = HTTP_GET;
					p = 4;
					break;
#ifdef _LITTLE_ENDIAN
				case 0x54534F50: /* POST */
#endif
#ifdef _BIG_ENDIAN
				case 0x504F5354: /* POST */
#endif
					http->type = HTTP_POST;
					p = 5;
					break;
				default:
					ape_log(APE_INFO, __FILE__, __LINE__, g_ape, "Invalid HTTP method in request: %s", data);
					http->error = 1;
					shutdown(co->fd, 2);
					return;
			}
			
			if (data[p] != '/') {
				http->error = 1;
				shutdown(co->fd, 2);
				return;
			} else {
				int i = p;
				while (p++) {
					switch(data[p]) {
						case ' ':
							http->pos = pos;
							http->step = 1;
							http->uri = &data[i];
							http->buffer_addr = buffer->data;
							data[p] = '\0';
							process_http(co, g_ape);
							return;
						case '?':
							if (data[p+1] != ' ' && data[p+1] != '\r' && data[p+1] != '\n') {
								http->buffer_addr = buffer->data;
								http->data = &data[p+1];
							}
							break;
						case '\r':
						case '\n':
						case '\0':
							ape_log(APE_INFO, __FILE__, __LINE__, g_ape, "Invalid line ending in request: %s", data);
							http->error = 1;
							shutdown(co->fd, 2);
							return;
					}
				}
			}
			break;
		case 1:
			pos = seof(data, '\n');
			if (pos == -1) {

				return;
			}
			if (pos == 1 || (pos == 2 && *data == '\r')) {
				if (http->type == HTTP_GET) {
					/* Ok, at this point we have a blank line. Ready for GET */
					buffer->data[http->pos] = '\0';
					urldecode(http->uri);
					parser->onready(parser, g_ape);
					parser->ready = -1;
					buffer->length = 0;
					return;
				} else if (http->type == HTTP_GET_WS) { /* WebSockets handshake needs to read 8 bytes */
					//urldecode(http->uri);
					http->contentlength = 8;
					http->buffer_addr = buffer->data;
					http->data = &buffer->data[http->pos+(pos)];
					http->step = 2;
				} else {
					/* Content-Length is mandatory in case of POST */
					if (http->contentlength == 0) {
						http->error = 1;
						shutdown(co->fd, 2);
						return;
					} else {
						http->buffer_addr = buffer->data; // save the addr
						http->data = &buffer->data[http->pos+(pos)];
						http->step = 2;
					}
				}
			} else {
				struct _http_header_line *hl;

				if ((hl = parse_header_line(data)) != NULL) {
					hl->next = http->hlines;
					http->hlines = hl;
					if (strcasecmp(hl->key.val, "host") == 0) {
						http->host = hl->value.val;
					}
				}
				if (http->type == HTTP_POST) {
					/* looking for content-length instruction */
					if (pos <= 25 && strncasecmp("content-length: ", data, 16) == 0) {
						int cl = atoi(&data[16]);

						/* Content-length can't be negative... */
						if (cl < 1 || cl > MAX_CONTENT_LENGTH) {
							http->error = 1;
							shutdown(co->fd, 2);
							return;
						}
						/* At this time we are ready to read "cl" bytes contents */
						http->contentlength = cl;

					}
				} else if (http->type == HTTP_GET) {
					if (strncasecmp("Sec-WebSocket-Key1: ", data, 20) == 0) {
						http->type = HTTP_GET_WS;
					}
				}
			}
			http->pos += pos;
			process_http(co, g_ape);
			break;
		case 2:
			read = buffer->length - http->pos; // data length
			http->pos += read;
			http->read += read;
			
			if (http->read >= http->contentlength) {

				parser->ready = 1;
				urldecode(http->uri);
				/* no more than content-length */
				buffer->data[http->pos - (http->read - http->contentlength)] = '\0';
				
				parser->onready(parser, g_ape);
				parser->ready = -1;
				buffer->length = 0;
			}
			break;
		default:
			break;
	}
}
Ejemplo n.º 9
0
void process_http(connection *co)
{
	char *data = data = co->buffer.data;
	int pos, read;
	
	if (co->buffer.length == 0 || co->http.ready == 1 || co->http.error == 1) {
		return;
	}
	
	/* 0 will be erased by the next read()'ing loop */
	data[co->buffer.length] = '\0';
	
	data = &data[co->http.pos];
	
	if (*data == '\0') {
		return;
	}
	
	switch(co->http.step) {
		case 0:
			pos = seof(data);
			if (pos == -1) {
				return;
			}
			
			if (strncasecmp(data, "POST ", 5) == 0) {
				co->http.type = HTTP_POST;
			} else if (strncasecmp(data, "GET ", 4) == 0) {
				co->http.type = HTTP_GET;
			} else {
				/* Other methods are not implemented yet */
				co->http.error = 1;
				
				return;
			}
			co->http.pos = pos;
			co->http.step = 1;
			
			process_http(co);
			break;
		case 1:
			pos = seof(data);
			if (pos == -1) {

				return;
			}
			if (pos == 1 || (pos == 2 && *data == '\r')) {
				

				if (co->http.type == HTTP_GET) {
					/* Ok, at this point we have a blank line. Ready for GET */
					co->http.ready = 1;
					co->buffer.data[co->http.pos] = '\0';

					return;
				} else {
					/* Content-Length is mandatory in case of POST */
					if (co->http.contentlength == 0) {
						co->http.error = 1;
						
						return;
					} else {
						co->http.step = 2;
					}
				}
			} else if (co->http.type == HTTP_POST) {
				/* looking for content-length instruction */
				if (pos <= 25 && strncasecmp("content-length: ", data, 16) == 0) {
					int cl = atoi(&data[16]);
					
					/* Content-length can't be negative... */
					if (cl < 1 || cl > MAX_CONTENT_LENGTH) {
						co->http.error = 1;
						return;
					}
					/* At this time we are ready to read "cl" bytes contents */
					co->http.contentlength = cl;
					
				}
			}
			co->http.pos += pos;
			process_http(co);
			break;
		case 2:
			read = strlen(data);
			co->http.pos += read;
			co->http.read += read;

			if (co->http.read >= co->http.contentlength) {
				co->http.ready = 1;
				
				/* no more than content-length */
				co->buffer.data[co->http.pos - (co->http.read - co->http.contentlength)] = '\0';
			}
			break;
		default:
			break;
	}
}