Beispiel #1
0
void
worker_can_read(int fd, short event, void *p) {

	struct http_client *c = p;
	int ret, nparsed;

	(void)fd;
	(void)event;

	ret = http_client_read(c);
	if(ret <= 0) {
		if((client_error_t)ret == CLIENT_DISCONNECTED) {
			return;
		} else if (c->failed_alloc || (client_error_t)ret == CLIENT_OOM) {
			slog(c->w->s, WEBDIS_DEBUG, "503", 3);
			http_send_error(c, 503, "Service Unavailable");
			return;
		}
	}

	if(c->is_websocket) {
		/* Got websocket data */
		ws_add_data(c);
	} else {
		/* run parser */
		nparsed = http_client_execute(c);

		if(c->failed_alloc) {
			slog(c->w->s, WEBDIS_DEBUG, "503", 3);
			http_send_error(c, 503, "Service Unavailable");
		} else if(c->is_websocket) {
			/* we need to use the remaining (unparsed) data as the body. */
			if(nparsed < ret) {
				http_client_add_to_body(c, c->buffer + nparsed + 1, c->sz - nparsed - 1);
				ws_handshake_reply(c);
			} else {
				c->broken = 1;
			}
			free(c->buffer);
			c->buffer = NULL;
			c->sz = 0;
		} else if(nparsed != ret) {
			slog(c->w->s, WEBDIS_DEBUG, "400", 3);
			http_send_error(c, 400, "Bad Request");
		} else if(c->request_sz > c->s->cfg->http_max_request_size) {
			slog(c->w->s, WEBDIS_DEBUG, "413", 3);
			http_send_error(c, 413, "Request Entity Too Large");
		}
	}

	if(c->broken) { /* terminate client */
		http_client_free(c);
	} else {
		/* start monitoring input again */
		worker_monitor_input(c);
	}
}
Beispiel #2
0
/**
 * Called when a client has finished reading input and can create a cmd
 */
void
worker_process_client(struct http_client *c) {

	/* check that the command can be executed */
	struct worker *w = c->w;
	cmd_response_t ret = CMD_PARAM_ERROR;
	switch(c->parser.method) {
		case HTTP_GET:
			if(c->path_sz == 16 && memcmp(c->path, "/crossdomain.xml", 16) == 0) {
				http_crossdomain(c);
				return;
			}
			slog(w->s, WEBDIS_DEBUG, c->path, c->path_sz);
			ret = cmd_run(c->w, c, 1+c->path, c->path_sz-1, NULL, 0);
			break;

		case HTTP_POST:
			slog(w->s, WEBDIS_DEBUG, c->path, c->path_sz);
			ret = cmd_run(c->w, c, c->body, c->body_sz, NULL, 0);
			break;

		case HTTP_PUT:
			slog(w->s, WEBDIS_DEBUG, c->path, c->path_sz);
			ret = cmd_run(c->w, c, 1+c->path, c->path_sz-1,
					c->body, c->body_sz);
			break;

		case HTTP_OPTIONS:
			http_send_options(c);
			return;

		default:
			slog(w->s, WEBDIS_DEBUG, "405", 3);
			http_send_error(c, 405, "Method Not Allowed");
			return;
	}

	switch(ret) {
		case CMD_ACL_FAIL:
		case CMD_PARAM_ERROR:
			slog(w->s, WEBDIS_DEBUG, "403", 3);
			http_send_error(c, 403, "Forbidden");
			break;

		case CMD_REDIS_UNAVAIL:
			slog(w->s, WEBDIS_DEBUG, "503", 3);
			http_send_error(c, 503, "Service Unavailable");
			break;
		default:
			break;
	}

}
Beispiel #3
0
static int http_parse_mime(uchar *tcp_data, ushort tcp_data_len, uchar nr)
{
	uchar 	*ptr;
	uint	data_len;
	uint	mem_len;

	/* skip boundary="boundary code" */
	if ((ptr = (uchar *)strstr((const char *)tcp_data, 
			boundary_code)) == NULL)
		return 1;
	else 
		ptr = ptr + strlen(boundary_code);

	mem_len = tcp_data_len - (ptr - tcp_data);
	
	/* find the first boundary code */
	if ((ptr = (uchar *)memstr((const char *)ptr, 
			boundary_code, mem_len)) != NULL) {
		/* the first content length */
		post_info.rcv_len = tcp_data_len - (ptr - tcp_data) + 2;
		
		/* move pointer to Content-Disposition */
		ptr = ptr + strlen(boundary_code);

		/* get upload file name */
		ptr = (uchar *)strstr((const char *)ptr, c_fname);
		ptr = (uchar *)strchr((const char *)ptr,'"');
		if (*(ptr+1) == '"') {
			printf("No file to be uploaded !!!\n");
			http_state = HTTP_START;
			http_send_error(nr, 400, "Bad Request",
					 "No upload file name to be slected !");
			return 1;
		} else {
			/* printf("Parsing file name...\n"); */
		}
								
	} else {
		/*printf("Can't find the first boundary code.\n");*/
		return 1;
	}
	
	ptr = (uchar *)strstr((const char *)ptr, c_headerend); /* "\r\n\r\n" */
	ptr = ptr + strlen(c_headerend);	/* upload file start pointer */
	
	data_len = tcp_data_len - (ptr - tcp_data );
	post_info.data_len = data_len;
	memcpy(post_info.buf, ptr, data_len);
	
	return 0;
}
Beispiel #4
0
/* routes a request to the correct handler */
static void route_perform(http_s *h) {
  /* add required Serevr header */
  http_set_header(h, HTTP_HEADER_SERVER, fiobj_dup(HTTP_VALUE_SERVER));
  /* collect path from hash map */
  fio_str_info_s tmp_i = fiobj_obj2cstr(h->path);
  fio_str_s tmp = FIO_STR_INIT_EXISTING(tmp_i.data, tmp_i.len, 0);
  fio_router_handler_fn handler =
      fio_router_find(&routes, fio_str_hash(&tmp), tmp);
  /* forward request or send error */
  if (handler) {
    handler(h);
    return;
  }
  http_send_error(h, 404);
}
Beispiel #5
0
/*------------------------------------------------------------------------
 * The received header must contain the word "GET" or "POST" to be 
 * considered a valid request.
 * With HTTP 1.1 where the connection is left open, the header I send
 * should include content length. With HTTP 1.0 you can just close the
 * connection after sending the page and the browser knows its done. 
 *
 * The HTTP protocol specification is at http://www.w3.org/Protocols/ 
 *------------------------------------------------------------------------
 */
ushort http_server(uchar *inbuf, ushort header_len, ushort tcp_len,
		   uchar nr, uchar resend)
{
	static uint	counter=0;
	uint	content_length;
	uint	data_len;
	uchar 	*ptr;
	uchar 	*tcp_data;

	if (http_debug == DEBUG)
		printf("\n\n%s************ tcp_len = %d ************%d\n",
			__func__,tcp_len,http_state);
	else
		if ((counter++ % 100) == 0)
			printf(".");
		    	
	/* Make sure this is a valid connection */
	if (nr == NO_CONNECTION) 
		return 0;
	
	/* Compute start of TCP data */
	
	/* Save first 20 chars and seq number just in case
	 * we need to re-generate page
	 * TODO: if post, then save switch state infomation
	 * If this is a resend, set sequence number to what it was
	 * the last time we sent this
	 */
	if (!resend) {
		tcp_data = inbuf + ETHER_IP_HLEN + header_len;
		memcpy(conxn[nr].query, tcp_data, 20);
		conxn[nr].old_sequence = conxn[nr].my_sequence;
	} else {
		tcp_data = inbuf;
		conxn[nr].my_sequence = conxn[nr].old_sequence;   
	}

	if (http_debug == DEBUG)
		printf("#1> http_state = %d......\n",http_state);

	/* Pre-porcess HTTP state change. */
	switch (http_state) {
	case HTTP_START:
		if ( (strstr((const char *)tcp_data, "GET") != NULL) && 
		     ((strstr((const char *)tcp_data, "index") != NULL) || 
		      (strstr((const char *)tcp_data, "/ ") != NULL)) )
			http_state = HTTP_GET;
		else if ( (strstr((const char *)tcp_data, "POST") != NULL) )
			http_state = HTTP_POST;
		break;

	case HTTP_GET:
		if ( (strstr((const char *)tcp_data, "POST") != NULL) )
			http_state = HTTP_POST;
		break;
		
	case HTTP_UPLOAD:  /* process the situation of network disconnection */
		if ( (strstr((const char *)tcp_data, "GET") != NULL) && 
		     ((strstr((const char *)tcp_data, "index") != NULL) || 
		      (strstr((const char *)tcp_data, "/ ") != NULL)) )
			http_state = HTTP_GET;
		break;
	}
	
	switch (http_state) {
	case HTTP_START:
		break;
		
	case HTTP_GET:
	      	/* send download page to HTTP client */
		http_send_ok(nr, web_page, 200, "OK");
		break;

	case HTTP_POST:
		if (http_parse_post(tcp_data, &content_length)) {
			http_state = HTTP_START;
			return 1;
		} else {
			post_info.upload_len = content_length;
			post_info.data_len = 0;
			post_info.buf = (uchar *)upgrade_buffer;
			http_state = HTTP_HEAD_DATA;
		}

		if (http_parse_mime(tcp_data, tcp_len - header_len, nr) == 0)
			http_state = HTTP_UPLOAD;
		break;

	case HTTP_HEAD_DATA:
		post_info.rcv_len = tcp_len - header_len;

		if (http_check_filename(tcp_data)) {
			http_send_error(nr, 400, "Bad Request",
				"No upload file name to be slected !");
			http_state = HTTP_START;
			return 1;			
		}
		
		ptr = (uchar *)strstr((const char *)tcp_data, c_headerend);
		ptr = ptr + strlen(c_headerend); /* upload file start pointer */
		
		data_len = tcp_len - header_len - (ptr - tcp_data );
		post_info.data_len = data_len;
		memcpy(post_info.buf, ptr, data_len);

		http_state = HTTP_UPLOAD;
		break;

	case HTTP_UPLOAD:
		post_info.rcv_len += tcp_len - header_len;

		if (http_debug == DEBUG) {
			printf("post_info.rcv_len=%d  post_info.upload_len=%d\n"
				,post_info.rcv_len,post_info.upload_len);
		}
		
		if (post_info.rcv_len >= post_info.upload_len) {
			/* To check the last packet if contains image data. */
			/* 6-byte include two "--" and one \r\n */
			/* 8-byte include two "--" and two \r\n */
			if ((tcp_len - header_len) > (strlen(boundary_code)+6)) 
				data_len = tcp_len - header_len - \
						strlen(boundary_code) - 8;
			else
				data_len = 0;

			if (http_check_image(post_info.buf, post_info.data_len)) {
				http_send_error(nr, 400, "Bad Request",
						 "File format is invalid !");
				http_state = HTTP_START;
				return (1);
			} else {			
				memset(text, 0x00, sizeof(text));
#ifdef CONFIG_MTD_CORTINA_CS752X_NAND
				sprintf(text,"%d", 5 + post_info.data_len/(1024*1000));
#else
				sprintf(text,"%d", 10 + post_info.data_len/(1024*100));
#endif
				replace_tag((uchar *)upgrade200_1, "TAG:NUM1", text);
	
				http_send_ok(nr, upgrade200_1, 200, "OK");	

				if (do_upgrade_image(post_info.buf, post_info.data_len)) {
					http_state = HTTP_START;
					return 0;
				} else {
					http_state = HTTP_REBOOT;
					break;
				}
			}

		} else {
			data_len = tcp_len - header_len;
			memcpy((void *)&post_info.buf[post_info.data_len], tcp_data, data_len);
			post_info.data_len += data_len;
		}
			
		break;

	case HTTP_REBOOT:
		if ( (strstr((const char *)tcp_data, "GET") != NULL) && 
		     (strstr((const char *)tcp_data, "reboot") != NULL) ) {    	
			http_state = HTTP_START;
			http_send_ok(nr, reboot200, 200, "OK");
			/* 
			 * Reserved time for tx those packets that queue 
			 * in packet buffer before system reset.
			 */
			udelay(500);
			do_reset(NULL, 0, 0, NULL);
		}
		break;

	default:
		printf("HTTP State Error ! %d\n", http_state);
		break;
	}

	if (http_debug == DEBUG)
		printf("#2> http_state = %d......\n",http_state);
	
	return 0;
}
Beispiel #6
0
/**
 * Called when a client has finished reading input and can create a cmd
 */
void
worker_process_client(struct http_client *c) {

	/* check that the command can be executed */
	struct worker *w = c->w;
	cmd_response_t ret = CMD_PARAM_ERROR;
	
	char *client_ip; /* well set this equal to the IP string address returned by inet_ntoa */
	client_ip = inet_ntoa(*(struct in_addr *)&c->addr); /* cast x as a struct in_addr */
	
	char msg[128] = {};
	sprintf(msg,"%s %s",client_ip,c->path);
	
	switch(c->parser.method) {
		case HTTP_GET:
			if(c->path_sz == 16 && memcmp(c->path, "/crossdomain.xml", 16) == 0) {
				http_crossdomain(c);
				return;
			}
			ret = cmd_run(c->w, c, 1+c->path, c->path_sz-1, NULL, 0);
			sprintf(msg,"%s GET %d",msg,(int)ret);
			slog(w->s, WEBDIS_DEBUG, msg, strlen(msg));
			break;

		case HTTP_POST:
			ret = cmd_run(c->w, c, c->body, c->body_sz, NULL, 0);
			sprintf(msg,"%s POST %d",msg,(int)ret);
			slog(w->s, WEBDIS_DEBUG, msg, strlen(msg));
			break;

		case HTTP_PUT:
			ret = cmd_run(c->w, c, 1+c->path, c->path_sz-1,
					c->body, c->body_sz);
			sprintf(msg,"%s PUT %d",msg,(int)ret);
			slog(w->s, WEBDIS_DEBUG, msg, strlen(msg));			
			break;

		case HTTP_OPTIONS:
			http_send_options(c);

		default:
			slog(w->s, WEBDIS_DEBUG, "405", 3);
			http_send_error(c, 405, "Method Not Allowed");
			return;
	}

	switch(ret) {
		case CMD_ACL_FAIL:
		case CMD_PARAM_ERROR:
			slog(w->s, WEBDIS_DEBUG, "403", 3);
			http_send_error(c, 403, "Forbidden");
			break;

		case CMD_REDIS_UNAVAIL:
			slog(w->s, WEBDIS_DEBUG, "503", 3);
			http_send_error(c, 503, "Service Unavailable");
			break;
		default:
			break;
	}

}