Exemple #1
0
void web_server_destroy(void)
{
	if (bWebServerState == WEB_SERVER_ENABLED) {
		membuffer_destroy(&gDocumentRootDir);
		alias_release(&gAliasDoc);

		ithread_mutex_lock(&gWebMutex);
		memset(&gAliasDoc, 0, sizeof(struct xml_alias_t));
		ithread_mutex_unlock(&gWebMutex);

		ithread_mutex_destroy(&gWebMutex);
		bWebServerState = WEB_SERVER_DISABLED;
	}
}
Exemple #2
0
int web_server_set_alias(const char *alias_name, 
	const char *alias_content, size_t alias_content_length,
	time_t last_modified)
{
	int ret_code;
	struct xml_alias_t alias;

	alias_release(&gAliasDoc);
	if (alias_name == NULL) {
		/* don't serve aliased doc anymore */
		return 0;
	}
	assert(alias_content != NULL);
	membuffer_init(&alias.doc);
	membuffer_init(&alias.name);
	alias.ct = NULL;
	do {
		/* insert leading /, if missing */
		if (*alias_name != '/')
			if (membuffer_assign_str(&alias.name, "/") != 0)
				break;	/* error; out of mem */
		ret_code = membuffer_append_str(&alias.name, alias_name);
		if (ret_code != 0)
			break;	/* error */
		if ((alias.ct = (int *)malloc(sizeof(int))) == NULL)
			break;	/* error */
		*alias.ct = 1;
		membuffer_attach(&alias.doc, (char *)alias_content,
				 alias_content_length);
		alias.last_modified = last_modified;
		/* save in module var */
		ithread_mutex_lock(&gWebMutex);
		gAliasDoc = alias;
		ithread_mutex_unlock(&gWebMutex);

		return 0;
	} while (FALSE);
	/* error handler */
	/* free temp alias */
	membuffer_destroy(&alias.name);
	membuffer_destroy(&alias.doc);
	free(alias.ct);

	return UPNP_E_OUTOF_MEMORY;
}
Exemple #3
0
/*!
 * \brief Processes the request and returns the result in the output parameters.
 *
 * \return
 * \li \c HTTP_BAD_REQUEST
 * \li \c HTTP_INTERNAL_SERVER_ERROR
 * \li \c HTTP_REQUEST_RANGE_NOT_SATISFIABLE
 * \li \c HTTP_FORBIDDEN
 * \li \c HTTP_NOT_FOUND
 * \li \c HTTP_NOT_ACCEPTABLE
 * \li \c HTTP_OK
 */
static int process_request(
	/*! [in] HTTP Request message. */
	http_message_t *req,
	/*! [out] Tpye of response. */
	enum resp_type *rtype,
	/*! [out] Headers. */
	membuffer *headers,
	/*! [out] Get filename from request document. */
	membuffer *filename,
	/*! [out] Xml alias document from the request document. */
	struct xml_alias_t *alias,
	/*! [out] Send Instruction object where the response is set up. */
	struct SendInstruction *RespInstr)
{
	int code;
	int err_code;

	char *request_doc;
	struct File_Info finfo;
	int using_alias;
	int using_virtual_dir;
	uri_type *url;
	const char *temp_str;
	int resp_major;
	int resp_minor;
	int alias_grabbed;
	size_t dummy;
	const char *extra_headers = NULL;

	print_http_headers(req);
	url = &req->uri;
	assert(req->method == HTTPMETHOD_GET ||
	       req->method == HTTPMETHOD_HEAD ||
	       req->method == HTTPMETHOD_POST ||
	       req->method == HTTPMETHOD_SIMPLEGET);
	/* init */
	memset(&finfo, 0, sizeof(finfo));
	request_doc = NULL;
	finfo.content_type = NULL;
	alias_grabbed = FALSE;
	err_code = HTTP_INTERNAL_SERVER_ERROR;	/* default error */
	using_virtual_dir = FALSE;
	using_alias = FALSE;

	http_CalcResponseVersion(req->major_version, req->minor_version,
				 &resp_major, &resp_minor);
	/* */
	/* remove dots */
	/* */
	request_doc = malloc(url->pathquery.size + 1);
	if (request_doc == NULL) {
		goto error_handler;	/* out of mem */
	}
	memcpy(request_doc, url->pathquery.buff, url->pathquery.size);
	request_doc[url->pathquery.size] = '\0';
	dummy = url->pathquery.size;
	remove_escaped_chars(request_doc, &dummy);
	code = remove_dots(request_doc, url->pathquery.size);
	if (code != 0) {
		err_code = HTTP_FORBIDDEN;
		goto error_handler;
	}
	if (*request_doc != '/') {
		/* no slash */
		err_code = HTTP_BAD_REQUEST;
		goto error_handler;
	}
	if (isFileInVirtualDir(request_doc)) {
		using_virtual_dir = TRUE;
		RespInstr->IsVirtualFile = 1;
		if (membuffer_assign_str(filename, request_doc) != 0) {
			goto error_handler;
		}
	} else {
		/* try using alias */
		if (is_valid_alias(&gAliasDoc)) {
			alias_grab(alias);
			alias_grabbed = TRUE;
			using_alias = get_alias(request_doc, alias, &finfo);
			if (using_alias == TRUE) {
				finfo.content_type =
				    ixmlCloneDOMString("text/xml");

				if (finfo.content_type == NULL) {
					goto error_handler;
				}
			}
		}
	}
	if (using_virtual_dir) {
		if (req->method != HTTPMETHOD_POST) {
			/* get file info */
			if (virtualDirCallback.
			    get_info(filename->buf, &finfo) != 0) {
				err_code = HTTP_NOT_FOUND;
				goto error_handler;
			}
			/* try index.html if req is a dir */
			if (finfo.is_directory) {
				if (filename->buf[filename->length - 1] == '/') {
					temp_str = "index.html";
				} else {
					temp_str = "/index.html";
				}
				if (membuffer_append_str(filename, temp_str) !=
				    0) {
					goto error_handler;
				}
				/* get info */
				if ((virtualDirCallback.
				     get_info(filename->buf,
					      &finfo) != UPNP_E_SUCCESS)
				    || finfo.is_directory) {
					err_code = HTTP_NOT_FOUND;
					goto error_handler;
				}
			}
			/* not readable */
			if (!finfo.is_readable) {
				err_code = HTTP_FORBIDDEN;
				goto error_handler;
			}
			/* finally, get content type */
			/* if ( get_content_type(filename->buf, &content_type) != 0 ) */
			/*{ */
			/*  goto error_handler; */
			/* } */
		}
	} else if (!using_alias) {
		if (gDocumentRootDir.length == 0) {
			goto error_handler;
		}
		/* */
		/* get file name */
		/* */

		/* filename str */
		if (membuffer_assign_str(filename, gDocumentRootDir.buf) != 0 ||
		    membuffer_append_str(filename, request_doc) != 0) {
			goto error_handler;	/* out of mem */
		}
		/* remove trailing slashes */
		while (filename->length > 0 &&
		       filename->buf[filename->length - 1] == '/') {
			membuffer_delete(filename, filename->length - 1, 1);
		}
		if (req->method != HTTPMETHOD_POST) {
			/* get info on file */
			if (get_file_info(filename->buf, &finfo) != 0) {
				err_code = HTTP_NOT_FOUND;
				goto error_handler;
			}
			/* try index.html if req is a dir */
			if (finfo.is_directory) {
				if (filename->buf[filename->length - 1] == '/') {
					temp_str = "index.html";
				} else {
					temp_str = "/index.html";
				}
				if (membuffer_append_str(filename, temp_str) !=
				    0) {
					goto error_handler;
				}
				/* get info */
				if (get_file_info(filename->buf, &finfo) != 0 ||
				    finfo.is_directory) {
					err_code = HTTP_NOT_FOUND;
					goto error_handler;
				}
			}
			/* not readable */
			if (!finfo.is_readable) {
				err_code = HTTP_FORBIDDEN;
				goto error_handler;
			}
		}
		/* finally, get content type */
		/*      if ( get_content_type(filename->buf, &content_type) != 0 ) */
		/*      { */
		/*          goto error_handler; */
		/*      } */
	}
	RespInstr->ReadSendSize = finfo.file_length;
	/* Check other header field. */
	if ((code =
	     CheckOtherHTTPHeaders(req, RespInstr,
				   finfo.file_length)) != HTTP_OK) {
		err_code = code;
		goto error_handler;
	}
	if (req->method == HTTPMETHOD_POST) {
		*rtype = RESP_POST;
		err_code = HTTP_OK;
		goto error_handler;
	}
	/*extra_headers = UpnpFileInfo_get_ExtraHeaders(finfo); */
	if (!extra_headers) {
		extra_headers = "";
	}

	/* Check if chunked encoding should be used. */
	if (using_virtual_dir && finfo.file_length == UPNP_USING_CHUNKED) {
		/* Chunked encoding is only supported by HTTP 1.1 clients */
		if (resp_major == 1 && resp_minor == 1) {
			RespInstr->IsChunkActive = 1;
		} else {
			/* The virtual callback indicates that we should use
			 * chunked encoding however the client doesn't support
			 * it. Return with an internal server error. */
			err_code = HTTP_NOT_ACCEPTABLE;
			goto error_handler;
		}
	}

	if (RespInstr->IsRangeActive && RespInstr->IsChunkActive) {
		/* Content-Range: bytes 222-3333/4000  HTTP_PARTIAL_CONTENT */
		/* Transfer-Encoding: chunked */
		if (http_MakeMessage(headers, resp_major, resp_minor,
		    "R" "T" "GKLD" "s" "tcS" "Xc" "sCc",
		    HTTP_PARTIAL_CONTENT,	/* status code */
		    finfo.content_type,	/* content type */
		    RespInstr,	/* range info */
		    RespInstr,	/* language info */
		    "LAST-MODIFIED: ",
		    &finfo.last_modified,
		    X_USER_AGENT, extra_headers) != 0) {
			goto error_handler;
		}
	} else if (RespInstr->IsRangeActive && !RespInstr->IsChunkActive) {
		/* Content-Range: bytes 222-3333/4000  HTTP_PARTIAL_CONTENT */
		if (http_MakeMessage(headers, resp_major, resp_minor,
		    "R" "N" "T" "GLD" "s" "tcS" "Xc" "sCc",
		    HTTP_PARTIAL_CONTENT,	/* status code */
		    RespInstr->ReadSendSize,	/* content length */
		    finfo.content_type,	/* content type */
		    RespInstr,	/* range info */
		    RespInstr,	/* language info */
		    "LAST-MODIFIED: ",
		    &finfo.last_modified,
		    X_USER_AGENT, extra_headers) != 0) {
			goto error_handler;
		}
	} else if (!RespInstr->IsRangeActive && RespInstr->IsChunkActive) {
		/* Transfer-Encoding: chunked */
		if (http_MakeMessage(headers, resp_major, resp_minor,
		    "RK" "TLD" "s" "tcS" "Xc" "sCc",
		    HTTP_OK,	/* status code */
		    finfo.content_type,	/* content type */
		    RespInstr,	/* language info */
		    "LAST-MODIFIED: ",
		    &finfo.last_modified,
		    X_USER_AGENT, extra_headers) != 0) {
			goto error_handler;
		}
	} else {
		/* !RespInstr->IsRangeActive && !RespInstr->IsChunkActive */
		if (RespInstr->ReadSendSize >= 0) {
			if (http_MakeMessage(headers, resp_major, resp_minor,
			    "R" "N" "TLD" "s" "tcS" "Xc" "sCc",
			    HTTP_OK,	/* status code */
			    RespInstr->ReadSendSize,	/* content length */
			    finfo.content_type,	/* content type */
			    RespInstr,	/* language info */
			    "LAST-MODIFIED: ",
			    &finfo.last_modified,
			    X_USER_AGENT,
			    extra_headers) != 0) {
				goto error_handler;
			}
		} else {
			if (http_MakeMessage(headers, resp_major, resp_minor,
			    "R" "TLD" "s" "tcS" "Xc" "sCc",
			    HTTP_OK,	/* status code */
			    finfo.content_type,	/* content type */
			    RespInstr,	/* language info */
			    "LAST-MODIFIED: ",
			    &finfo.last_modified,
			    X_USER_AGENT,
			    extra_headers) != 0) {
				goto error_handler;
			}
		}
	}
	if (req->method == HTTPMETHOD_HEAD) {
		*rtype = RESP_HEADERS;
	} else if (using_alias) {
		/* GET xml */
		*rtype = RESP_XMLDOC;
	} else if (using_virtual_dir) {
		*rtype = RESP_WEBDOC;
	} else {
		/* GET filename */
		*rtype = RESP_FILEDOC;
	}
	/* simple get http 0.9 as specified in http 1.0 */
	/* don't send headers */
	if (req->method == HTTPMETHOD_SIMPLEGET) {
		membuffer_destroy(headers);
	}
	err_code = HTTP_OK;

 error_handler:
	free(request_doc);
	ixmlFreeDOMString(finfo.content_type);
	if (err_code != HTTP_OK && alias_grabbed) {
		alias_release(alias);
	}

	return err_code;
}
Exemple #4
0
void web_server_callback(http_parser_t *parser, INOUT http_message_t *req,
	SOCKINFO *info)
{
	int ret;
	int timeout = 0;
	enum resp_type rtype = 0;
	membuffer headers;
	membuffer filename;
	struct xml_alias_t xmldoc;
	struct SendInstruction RespInstr;

	/*Initialize instruction header. */
	RespInstr.IsVirtualFile = 0;
	RespInstr.IsChunkActive = 0;
	RespInstr.IsRangeActive = 0;
	RespInstr.IsTrailers = 0;
	memset(RespInstr.AcceptLanguageHeader, 0,
	       sizeof(RespInstr.AcceptLanguageHeader));
	/* init */
	membuffer_init(&headers);
	membuffer_init(&filename);

	/*Process request should create the different kind of header depending on the */
	/*the type of request. */
	ret = process_request(req, &rtype, &headers, &filename, &xmldoc,
		&RespInstr);
	if (ret != HTTP_OK) {
		/* send error code */
		http_SendStatusResponse(info, ret, req->major_version,
			req->minor_version);
	} else {
		/* send response */
		switch (rtype) {
		case RESP_FILEDOC:
			http_SendMessage(info, &timeout, "Ibf",
					 &RespInstr,
					 headers.buf, headers.length,
					 filename.buf);
			break;
		case RESP_XMLDOC:
			http_SendMessage(info, &timeout, "Ibb",
				&RespInstr,
				headers.buf, headers.length,
				xmldoc.doc.buf, xmldoc.doc.length);
			alias_release(&xmldoc);
			break;
		case RESP_WEBDOC:
			/*http_SendVirtualDirDoc(info, &timeout, "Ibf",
				&RespInstr,
				headers.buf, headers.length,
				filename.buf);*/
			http_SendMessage(info, &timeout, "Ibf",
				&RespInstr,
				headers.buf, headers.length,
				filename.buf);
			break;
		case RESP_HEADERS:
			/* headers only */
			http_SendMessage(info, &timeout, "b",
				headers.buf, headers.length);
			break;
		case RESP_POST:
			/* headers only */
			ret = http_RecvPostMessage(parser, info, filename.buf,
				&RespInstr);
			/* Send response. */
			http_MakeMessage(&headers, 1, 1,
				"RTLSXcCc",
				ret, "text/html", &RespInstr, X_USER_AGENT);
			http_SendMessage(info, &timeout, "b",
				headers.buf, headers.length);
			break;
		default:
			UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
				"webserver: Invalid response type received.\n");
			assert(0);
		}
	}
	UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
		   "webserver: request processed...\n");
	membuffer_destroy(&headers);
	membuffer_destroy(&filename);
}
Exemple #5
0
void web_server_callback(http_parser_t *parser, INOUT http_message_t *req,
	SOCKINFO *info)
{
	int ret;
	int timeout = 5;
	enum resp_type rtype = 0;
	membuffer headers;
	membuffer filename;
	struct xml_alias_t xmldoc;
#if 0
	struct SendInstruction *pRespInstr;
	struct SendInstruction RespInstr;

	/*Initialize instruction header. */
	RespInstr.IsVirtualFile = 0;
	RespInstr.IsChunkActive = 0;
	RespInstr.IsRangeActive = 0;
	RespInstr.IsTrailers = 0;
	memset(RespInstr.AcceptLanguageHeader, 0,
	       sizeof(RespInstr.AcceptLanguageHeader));

	pRespInstr = &RespInstr;
#else
	struct SendInstruction *pRespInstr = osal_zmalloc( sizeof(struct SendInstruction) );
#endif
	/* init */
	membuffer_init(&headers);
	membuffer_init(&filename);

	/*Process request should create the different kind of header depending on the */
	/*the type of request. */
	ret = process_request(req, &rtype, &headers, &filename, &xmldoc,
		pRespInstr);
	if (ret != HTTP_OK) {
		/* send error code */
		http_SendStatusResponse(info, ret, req->major_version,
			req->minor_version);
	} else {
		/* send response */
		switch (rtype) {
		case RESP_FILEDOC:
			// The timeout need consider as transfer rate is high but consumption is slow and recevie buffer
			// is small in recevier. It will cause receiver pauses to receive data a while. If timeout is short,
			// the socket will be closed by timeout!!
			// HTTP file playback may get a timeout issue when media (bitrate 15Mbits) sent fast (26Mbits or above)
			// to Android device.
			timeout = 20;	// The value 20 is by experiment,as video is 15Mbits,
							// tcp has 26Mbits in transfer to NEXUS 7 video player!
			http_SendMessage(info, &timeout, "Ibf",
					 pRespInstr,
					 headers.buf, headers.length,
					 filename.buf);
			UpnpPrintf(UPNP_WARN, HTTP, __FILE__, __LINE__,"%d FILEDOC %s\r\n", __LINE__, filename.buf);
			break;
		case RESP_XMLDOC:
			http_SendMessage(info, &timeout, "Ibb",
				pRespInstr,
				headers.buf, headers.length,
				xmldoc.doc.buf, xmldoc.doc.length);
			alias_release(&xmldoc);
			UpnpPrintf(UPNP_WARN, HTTP, __FILE__, __LINE__,"%d XMLDOC %s\r\n", __LINE__, xmldoc.doc.buf);
			break;
		case RESP_WEBDOC:
			/*http_SendVirtualDirDoc(info, &timeout, "Ibf",
				pRespInstr,
				headers.buf, headers.length,
				filename.buf);*/
			http_SendMessage(info, &timeout, "Ibf",
				pRespInstr,
				headers.buf, headers.length,
				filename.buf);
			UpnpPrintf(UPNP_WARN, HTTP, __FILE__, __LINE__,"%d WEBDOC %s\r\n", __LINE__, filename.buf);
			break;
		case RESP_HEADERS:
			/* headers only */
			http_SendMessage(info, &timeout, "b",
				headers.buf, headers.length);
			UpnpPrintf(UPNP_WARN, HTTP, __FILE__, __LINE__,"%d HEADERS %s\r\n", __LINE__, headers.buf);
			break;
		case RESP_POST:
			/* headers only */
			ret = http_RecvPostMessage(parser, info, filename.buf,
				pRespInstr);
			if (ret != HTTP_OK){
				req->status_code = HTTP_BAD_REQUEST;
			}
			/* Send response. */
			http_MakeMessage(&headers, 1, 1,
				"RTLSXcCc",
				ret, "text/html", pRespInstr, X_USER_AGENT, "WebServer by Alpha Imaging Technology Corp.");
			http_SendMessage(info, &timeout, "b",
				headers.buf, headers.length);
			UpnpPrintf(UPNP_WARN, HTTP, __FILE__, __LINE__,"%d POST %s\r\n", __LINE__, headers.buf);
			break;
		default:
			UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
				"webserver: Invalid response type received.\n");
			assert(0);
			break;
		}
	}
	UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
		   "webserver: request processed...\n");
	membuffer_destroy(&headers);
	membuffer_destroy(&filename);
	osal_free(pRespInstr)
}