示例#1
0
static void
rsp_stream(struct evhttp_request *req, char **uri, struct evkeyvalq *query)
{
  int id;
  int ret;

  ret = safe_atoi32(uri[2], &id);
  if (ret < 0)
    httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
  else
    httpd_stream_file(req, id);
}
示例#2
0
static void
rsp_send_error(struct evhttp_request *req, char *errmsg)
{
  struct evbuffer *evbuf;
  struct evkeyvalq *headers;
  mxml_node_t *reply;
  mxml_node_t *status;
  mxml_node_t *node;

  /* We'd use mxmlNewXML(), but then we can't put any attributes
   * on the root node and we need some.
   */
  reply = mxmlNewElement(MXML_NO_PARENT, RSP_XML_ROOT);

  node = mxmlNewElement(reply, "response");
  status = mxmlNewElement(node, "status");

  /* Status block */
  node = mxmlNewElement(status, "errorcode");
  mxmlNewText(node, 0, "1");

  node = mxmlNewElement(status, "errorstring");
  mxmlNewText(node, 0, errmsg);

  node = mxmlNewElement(status, "records");
  mxmlNewText(node, 0, "0");

  node = mxmlNewElement(status, "totalrecords");
  mxmlNewText(node, 0, "0");

  evbuf = mxml_to_evbuf(reply);
  mxmlDelete(reply);

  if (!evbuf)
    {
      httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");

      return;
    }

  headers = evhttp_request_get_output_headers(req);
  evhttp_add_header(headers, "Content-Type", "text/xml; charset=utf-8");
  evhttp_add_header(headers, "Connection", "close");

  httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP);

  evbuffer_free(evbuf);
}
/* Handle an incoming message (request) from the client. This is the
 * main processing function of the HTTPD.
 */
int httpd_handle_message(int conn)
{
	int err;
	int req_line_len;
	char msg_in[128];

	/* clear out the httpd_req structure */
	memset(&httpd_req, 0x00, sizeof(httpd_req));

	httpd_req.sock = conn;

	/* Read the first line of the HTTP header */
	req_line_len = htsys_getln_soc(conn, msg_in, sizeof(msg_in));
	if (req_line_len == 0)
		return HTTPD_DONE;

	if (req_line_len < 0) {
		httpd_e("Could not read from socket");
		return -WM_FAIL;
	}

	/* Parse the first line of the header */
	err = httpd_parse_hdr_main(msg_in, &httpd_req);
	if (err == -WM_E_HTTPD_NOTSUPP)
		/* Send 505 HTTP Version not supported */
		return httpd_send_error(conn, HTTP_505);
	else if (err != WM_SUCCESS) {
		/* Send 500 Internal Server Error */
		return httpd_send_error(conn, HTTP_500);
	}

	/* set a generic error that can be overridden by the wsgi handling. */
	httpd_d("Presetting error to: ");
	httpd_set_error("wsgi handler failed");

	/* Web Services Gateway Interface branch point:
	 * At this point we have the request type (httpd_req.type) and the path
	 * (httpd_req.filename) and all the headers waiting to be read from
	 * the socket.
	 *
	 * The call bellow will iterate through all the url patterns and
	 * invoke the handlers that match the request type and pattern.  If
	 * request type and url patern match, invoke the handler.
	 */
	err = httpd_wsgi(&httpd_req);

	if (err == HTTPD_DONE) {
		httpd_d("Done processing request.");
		return WM_SUCCESS;
	} else if (err == -WM_E_HTTPD_NO_HANDLER) {
		httpd_w("No handler for the given URL %s was found",
			httpd_req.filename);
		/*
		 * We have not yet read the complete data from the current
		 * request, from the socket. We are in an error state and
		 * we wish to cancel this HTTP transaction. We sent
		 * appropriate message to the client and read (flush) out
		 * all the pending data in the socket. We let the client
		 * close the socket for us, if necessary.
		 */
		httpd_purge_socket_data(&httpd_req, msg_in,
				sizeof(msg_in), conn);
		httpd_set_error("File %s not_found", httpd_req.filename);
		httpd_send_error(conn, HTTP_404);
		return WM_SUCCESS;
	} else {
		httpd_e("WSGI handler failed.");
		/* Send 500 Internal Server Error */
		return httpd_send_error(conn, HTTP_500);
	}

}
int httpd_handle_file(httpd_request_t *req_p, struct fs *fs)
{
	const char *anchor = "/";
	char tmp[HTTPD_MAX_URI_LENGTH+1];
	const char *encoding = NULL;
	char *msg_in, *ptr, *type = NULL;
	int err, msg_in_len = HTTPD_MAX_MESSAGE - 1, conn = req_p->sock;
	int ret;

	msg_in = os_mem_alloc(HTTPD_MAX_MESSAGE + 2);
	if (!msg_in) {
		httpd_e("Failed to allocate memory for file handling");
		/* Check what needs to be returned */
		return -WM_FAIL;
	}
	memset(msg_in, 0, HTTPD_MAX_MESSAGE + 2);

	SYS_FILE_DECL;

	if (!fs) {
		/* The filesystem wasn't mounted properly */
		httpd_send_hdr_from_str(conn, http_header_404,
					CONTENT_TYPE_PLAIN, encoding,
					NO_CACHE_HEADERS, UNUSED_PARAM);
		httpd_send_default_headers(conn,
				req_p->wsgi->hdr_fields);
		httpd_send_crlf(conn);
		httpd_send(conn, FILE_NOT_FOUND, sizeof(FILE_NOT_FOUND));
		ret = WM_SUCCESS;
		goto out;
	}
	struct ftfs_super *f_super = fs_to_ftfs_sb(fs);

	/* Ensure that the anchor is the first part of the filename */
	ptr = strstr(req_p->filename, anchor);
	if (ptr == NULL ||
	    ptr != req_p->filename) {
		httpd_d("No anchor in filename\r\n");
		ret = httpd_send_error(conn, HTTP_500);
		goto out;
	}

	/* Zap the anchor from the filename */
	ptr = req_p->filename + strlen(anchor);
	err = 0;
	/* anchors are only across directory boundaries */
	if (*ptr != '/')
		req_p->filename[err++] = '/';

	while (*ptr && (*ptr != '?')) {
		req_p->filename[err] = *ptr;
		ptr++;
		err++;
	}
	req_p->filename[err] = '\0';

	/* "/" implies a request for index.html */
	if (strncmp(req_p->filename, "/", 2) == 0) {
		strncpy(req_p->filename, http_index_html,
			sizeof(http_index_html));
	}

	/* Find if .gz version exists for file, if it is then serve that */
	type = strrchr(req_p->filename, ISO_period);
	if (type) {
		strncpy(tmp, req_p->filename, sizeof(tmp));
		strncat(tmp, ".gz", 3);
		httpd_d("Look for gz file if it exists: %s\r\n", tmp);
		if (htsys_file_open(fs, tmp, sys_filep) == WM_SUCCESS) {
			/* Gzipped version exists, serve that */
			httpd_d("Serve gzipped file\r\n");
			strncpy(req_p->filename, tmp, HTTPD_MAX_URI_LENGTH + 1);
			encoding = ".gz";
			htsys_close(fs, sys_filep);
		}
	}

	ret = httpd_parse_hdr_tags(req_p, conn, msg_in, msg_in_len);
	if (ret < 0) {
		httpd_d("Parsing headers failed \r\n");
		ret = httpd_send_error(conn, HTTP_500);
		goto out;
	}

	/* It is not a WSGI, check to see if the file exists */
	if (htsys_file_open(fs, req_p->filename, sys_filep) == -WM_FAIL) {
		httpd_w("file not found: %s\r\n", req_p->filename);

		ret = httpd_send_hdr_from_str(conn, http_header_404,
					      type, encoding, NO_CACHE_HEADERS,
					      UNUSED_PARAM);
		httpd_send_default_headers(conn,
				req_p->wsgi->hdr_fields);
		httpd_send_crlf(conn);
		if (ret != WM_SUCCESS)
			goto out;

		ret = htsys_file_open(fs, http_404_html, sys_filep);
		if (ret == WM_SUCCESS) {
			ret = httpd_send_file(fs, conn, sys_filep);
			goto out;
		} else
			httpd_w("No local 404 file.  Sending empty 404"
			      " response.\r\n");
	} else {
		/* Ok, the file exists, is it a script html or just html */
		g_wm_stats.wm_hd_file++;
		if (req_p->if_none_match &&
		    (f_super->fs_crc32 == req_p->etag_val)) {
			/* We do not need the file handle now */
			htsys_close(fs, sys_filep);

			/* Send Not Modified header */

			/* Send header prologue */
			ret = httpd_send(conn, http_header_304_prologue,
					 strlen(http_header_304_prologue));
			if (ret != WM_SUCCESS)
				goto out;
			httpd_send_header(conn, "Server", "Marvell-WM");
			httpd_send_header(conn, "Connection", "Close");

			/* Send ETag */
			int len;
			const char *h = httpd_get_etag_hdr(req_p->etag_val,
							   &len);
			ret = httpd_send(conn, h, len);
			if (ret != WM_SUCCESS)
				goto out;
			/* Close the header */
			ret = httpd_send_crlf(conn);
			goto out;
		} else  {
			ret = httpd_send_hdr_from_str(conn, http_header_200,
						      type, encoding,
						      SEND_CACHE_HEADERS,
						      f_super->fs_crc32);
			httpd_send_default_headers(conn,
					req_p->wsgi->hdr_fields);
			httpd_send_crlf(conn);

			if (ret != WM_SUCCESS)
				goto out;
			ptr = strchr(req_p->filename, ISO_period);
			if (ptr != NULL && strncmp(ptr, http_shtml,
						   sizeof(http_shtml)
						   - 1) == 0) {
				httpd_d("Handling script: %s", req_p->filename);
				ret = handle_script(fs, req_p, conn,
						    sys_filep, msg_in);
				htsys_close(fs, sys_filep);
				if (ret != WM_SUCCESS) {
					httpd_d("Script failed\r\n");
					goto out;
				}
			} else {
				ret = httpd_send_file(fs, conn, sys_filep);
				if (ret != WM_SUCCESS)
					goto out;
			}
		}
	}
	ret = httpd_send_last_chunk(conn);
out:
	os_mem_free(msg_in);
	return ret;
}