added some code for handling the PUT method
This commit is contained in:
		| @ -470,15 +470,14 @@ qse_httpd_task_t* qse_httpd_entaskdir ( | ||||
| 	data.version = *qse_htre_getversion(req); | ||||
| 	data.keepalive = (req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE); | ||||
|  | ||||
|  | ||||
| 	qse_htre_discardcontent (req); /* TODO: don't discard for put??? */ | ||||
| 	switch (meth) | ||||
| 	{ | ||||
| 		case QSE_HTTP_HEAD: | ||||
| 			data.headonly = 1; | ||||
| 			break; | ||||
| 	 | ||||
| 		case QSE_HTTP_OPTIONS: | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_HTTP_GET: | ||||
| 		case QSE_HTTP_POST: | ||||
| 		case QSE_HTTP_PUT: | ||||
|  | ||||
| @ -25,50 +25,68 @@ | ||||
|  | ||||
| #define ETAG_LEN_MAX 127 | ||||
|  | ||||
| #define PUTFILE_INIT_FAILED (1 << 0) | ||||
|  | ||||
| typedef struct task_file_t task_file_t; | ||||
| struct task_file_t | ||||
| { | ||||
| 	qse_mcstr_t path; | ||||
| 	qse_mcstr_t mime; | ||||
|  | ||||
| 	qse_http_range_t   range; | ||||
| 	qse_mchar_t        if_none_match[ETAG_LEN_MAX + 1]; | ||||
| 	qse_ntime_t        if_modified_since; | ||||
| 	qse_http_version_t version; | ||||
| 	int                keepalive; | ||||
| 	int                headonly; | ||||
| 	int                method; | ||||
|  | ||||
| 	/* only for put file... */ | ||||
| 	union | ||||
| 	{ | ||||
| 		struct | ||||
| 		{ | ||||
| 			qse_mcstr_t mime; | ||||
| 		} get; | ||||
| 		struct | ||||
| 		{ | ||||
| 			int flags; | ||||
| 			qse_htre_t* req; | ||||
| 			qse_ubi_t handle; | ||||
| 		} put; | ||||
| 	} u; | ||||
| }; | ||||
|  | ||||
| typedef struct task_fseg_t task_fseg_t; | ||||
| struct task_fseg_t | ||||
| /*------------------------------------------------------------------------*/ | ||||
|  | ||||
| typedef struct task_getfseg_t task_getfseg_t; | ||||
| struct task_getfseg_t | ||||
| { | ||||
| 	qse_ubi_t handle; | ||||
| 	qse_foff_t left; | ||||
| 	qse_foff_t offset; | ||||
| }; | ||||
|  | ||||
| static int task_init_fseg ( | ||||
| static int task_init_getfseg ( | ||||
| 	qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) | ||||
| { | ||||
| 	task_fseg_t* xtn = qse_httpd_gettaskxtn (httpd, task); | ||||
| 	task_getfseg_t* xtn = qse_httpd_gettaskxtn (httpd, task); | ||||
| 	QSE_MEMCPY (xtn, task->ctx, QSE_SIZEOF(*xtn)); | ||||
| 	task->ctx = xtn; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void task_fini_fseg ( | ||||
| static void task_fini_getfseg ( | ||||
| 	qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) | ||||
| { | ||||
| 	task_fseg_t* ctx = (task_fseg_t*)task->ctx; | ||||
| 	task_getfseg_t* ctx = (task_getfseg_t*)task->ctx; | ||||
| 	httpd->opt.scb.file.close (httpd, ctx->handle); | ||||
| } | ||||
|  | ||||
| static int task_main_fseg ( | ||||
| static int task_main_getfseg ( | ||||
| 	qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) | ||||
| { | ||||
| 	qse_ssize_t n; | ||||
| 	qse_size_t count; | ||||
| 	task_fseg_t* ctx = (task_fseg_t*)task->ctx; | ||||
| 	task_getfseg_t* ctx = (task_getfseg_t*)task->ctx; | ||||
|  | ||||
| 	count = MAX_SEND_SIZE; | ||||
| 	if (count >= ctx->left) count = ctx->left; | ||||
| @ -98,13 +116,13 @@ static int task_main_fseg ( | ||||
| 	return 1; /* more work to do */ | ||||
| } | ||||
|  | ||||
| static qse_httpd_task_t* entask_file_segment ( | ||||
| static qse_httpd_task_t* entask_getfseg ( | ||||
| 	qse_httpd_t* httpd, qse_httpd_client_t* client,  | ||||
| 	qse_httpd_task_t* pred, | ||||
| 	qse_ubi_t handle, qse_foff_t offset, qse_foff_t size) | ||||
| { | ||||
| 	qse_httpd_task_t task; | ||||
| 	task_fseg_t data; | ||||
| 	task_getfseg_t data; | ||||
| 	 | ||||
| 	QSE_MEMSET (&data, 0, QSE_SIZEOF(data)); | ||||
| 	data.handle = handle; | ||||
| @ -112,9 +130,9 @@ static qse_httpd_task_t* entask_file_segment ( | ||||
| 	data.left = size; | ||||
|  | ||||
| 	QSE_MEMSET (&task, 0, QSE_SIZEOF(task)); | ||||
| 	task.init = task_init_fseg; | ||||
| 	task.main = task_main_fseg; | ||||
| 	task.fini = task_fini_fseg; | ||||
| 	task.init = task_init_getfseg; | ||||
| 	task.main = task_main_getfseg; | ||||
| 	task.fini = task_fini_getfseg; | ||||
| 	task.ctx = &data; | ||||
|  | ||||
| 	return qse_httpd_entask (httpd, client, pred, &task, QSE_SIZEOF(data)); | ||||
| @ -123,7 +141,7 @@ static qse_httpd_task_t* entask_file_segment ( | ||||
| /*------------------------------------------------------------------------*/ | ||||
|  | ||||
|  | ||||
| static int task_init_file ( | ||||
| static int task_init_getfile ( | ||||
| 	qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) | ||||
| { | ||||
| 	task_file_t* file = qse_httpd_gettaskxtn (httpd, task); | ||||
| @ -133,17 +151,17 @@ static int task_init_file ( | ||||
|  | ||||
| 	file->path.ptr = (qse_mchar_t*)(file + 1); | ||||
| 	qse_mbscpy ((qse_mchar_t*)file->path.ptr, arg->path.ptr); | ||||
| 	if (arg->mime.ptr) | ||||
| 	if (arg->u.get.mime.ptr) | ||||
| 	{ | ||||
| 		file->mime.ptr = file->path.ptr + file->path.len + 1; | ||||
| 		qse_mbscpy ((qse_mchar_t*)file->mime.ptr, arg->mime.ptr); | ||||
| 		file->u.get.mime.ptr = file->path.ptr + file->path.len + 1; | ||||
| 		qse_mbscpy ((qse_mchar_t*)file->u.get.mime.ptr, arg->u.get.mime.ptr); | ||||
| 	} | ||||
|  | ||||
| 	task->ctx = file; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static QSE_INLINE int task_main_file ( | ||||
| static QSE_INLINE int task_main_getfile ( | ||||
| 	qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) | ||||
| { | ||||
| 	task_file_t* file; | ||||
| @ -228,15 +246,15 @@ static QSE_INLINE int task_main_file ( | ||||
| 			qse_httpd_getname (httpd), | ||||
| 			qse_httpd_fmtgmtimetobb (httpd, QSE_NULL, 0), | ||||
| 			(file->keepalive? QSE_MT("keep-alive"): QSE_MT("close")), | ||||
| 			(file->mime.len > 0? QSE_MT("Content-Type: "): QSE_MT("")), | ||||
| 			(file->mime.len > 0? file->mime.ptr: QSE_MT("")), | ||||
| 			(file->mime.len > 0? QSE_MT("\r\n"): QSE_MT("")), | ||||
| 			(file->u.get.mime.len > 0? QSE_MT("Content-Type: "): QSE_MT("")), | ||||
| 			(file->u.get.mime.len > 0? file->u.get.mime.ptr: QSE_MT("")), | ||||
| 			(file->u.get.mime.len > 0? QSE_MT("\r\n"): QSE_MT("")), | ||||
| 			tmp[0], tmp[1], tmp[2], tmp[3], etag | ||||
| 		); | ||||
| 		if (x) | ||||
| 		{ | ||||
| 			if (file->headonly) goto no_file_send; | ||||
| 			x = entask_file_segment ( | ||||
| 			if (file->method == QSE_HTTP_HEAD) goto no_file_send; | ||||
| 			x = entask_getfseg ( | ||||
| 				httpd, client, x, | ||||
| 				handle,  | ||||
| 				file->range.from,  | ||||
| @ -283,17 +301,17 @@ static QSE_INLINE int task_main_file ( | ||||
| 			qse_httpd_getname (httpd), | ||||
| 			qse_httpd_fmtgmtimetobb (httpd, QSE_NULL, 0), | ||||
| 			(file->keepalive? QSE_MT("keep-alive"): QSE_MT("close")), | ||||
| 			(file->mime.len > 0? QSE_MT("Content-Type: "): QSE_MT("")), | ||||
| 			(file->mime.len > 0? file->mime.ptr: QSE_MT("")), | ||||
| 			(file->mime.len > 0? QSE_MT("\r\n"): QSE_MT("")), | ||||
| 			(file->u.get.mime.len > 0? QSE_MT("Content-Type: "): QSE_MT("")), | ||||
| 			(file->u.get.mime.len > 0? file->u.get.mime.ptr: QSE_MT("")), | ||||
| 			(file->u.get.mime.len > 0? QSE_MT("\r\n"): QSE_MT("")), | ||||
| 			b_fsize, | ||||
| 			qse_httpd_fmtgmtimetobb (httpd, &st.mtime, 1), | ||||
| 			etag | ||||
| 		); | ||||
| 		if (x)  | ||||
| 		{ | ||||
| 			if (file->headonly) goto no_file_send; | ||||
| 			x = entask_file_segment (httpd, client, x, handle, 0, st.size); | ||||
| 			if (file->method == QSE_HTTP_HEAD) goto no_file_send; | ||||
| 			x = entask_getfseg (httpd, client, x, handle, 0, st.size); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @ -306,6 +324,205 @@ no_file_send: | ||||
| 	return (x == QSE_NULL)? -1: 0; | ||||
| } | ||||
|  | ||||
| /*------------------------------------------------------------------------*/ | ||||
|  | ||||
| static int putfile_snatch_client_input ( | ||||
| 	qse_htre_t* req, const qse_mchar_t* ptr, qse_size_t len, void* ctx) | ||||
| { | ||||
| 	qse_httpd_task_t* task; | ||||
| 	task_file_t* file;  | ||||
|  | ||||
| 	task = (qse_httpd_task_t*)ctx; | ||||
| 	file = (task_file_t*)task->ctx; | ||||
|  | ||||
| 	if (ptr == QSE_NULL) | ||||
| 	{ | ||||
| 		/* | ||||
| 		 * this callback is called with ptr of QSE_NULL  | ||||
| 		 * when the request is completed or discarded.  | ||||
| 		 * and this indicates that there's nothing more to read | ||||
| 		 * from the client side. this can happen when the end of | ||||
| 		 * a request is seen or when an error occurs  | ||||
| 		 */ | ||||
| 		QSE_ASSERT (len == 0); | ||||
|  | ||||
| 		/* mark the there's nothing to read form the client side */ | ||||
| 		qse_htre_unsetconcb (file->u.put.req); | ||||
| 		file->u.put.req = QSE_NULL;  | ||||
|  | ||||
| 		/* since there is no more to read from the client side. | ||||
| 		 * the trigger is not needed any more. */ | ||||
| 		task->trigger[0].mask = 0; | ||||
| 	} | ||||
| 	else /*if (!(file->reqflags & PROXY_REQ_FWDERR))*/ | ||||
| 	{ | ||||
| 		/* TODO: write to file */ | ||||
| qse_printf (QSE_T("WRITING 4 [%.*hs]\n"), (int)len, ptr); | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int task_init_putfile ( | ||||
| 	qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) | ||||
| { | ||||
| 	task_file_t* file = qse_httpd_gettaskxtn (httpd, task); | ||||
| 	task_file_t* arg = (task_file_t*)task->ctx; | ||||
| 	int snatch_needed; | ||||
|  | ||||
| 	/* zero out the task's extension area */ | ||||
| 	QSE_MEMCPY (file, arg, QSE_SIZEOF(*file)); | ||||
| 	file->u.put.req = QSE_NULL; | ||||
| 	 | ||||
| 	/* copy in the path name to the area */ | ||||
| 	file->path.ptr = (qse_mchar_t*)(file + 1); | ||||
| 	qse_mbscpy ((qse_mchar_t*)file->path.ptr, arg->path.ptr); | ||||
|  | ||||
| 	snatch_needed = 0; | ||||
|  | ||||
| #if 0 | ||||
| 	httpd->errnum = QSE_HTTPD_ENOERR; | ||||
| 	if (httpd->opt.scb.file.stat (httpd, file->path.ptr, &st) <= -1) | ||||
| 	{ | ||||
| 		int http_errnum = 500; | ||||
|  | ||||
| 		switch (httpd->errnum) | ||||
| 		{ | ||||
| 			case QSE_HTTPD_ENOENT: | ||||
| 				/* nothing to do */ | ||||
| 				break; | ||||
|  | ||||
| 			case QSE_HTTPD_EACCES: | ||||
| 				http_errnum = 403; | ||||
| 			default: | ||||
| 				 | ||||
| 				goto no_file_write; | ||||
| 		} | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	if (httpd->opt.scb.file.wopen (httpd, file->path.ptr, &file->u.put.handle) <= -1) goto oops; | ||||
|  | ||||
| 	if (arg->u.put.req->state & QSE_HTRE_DISCARDED) | ||||
| 	{ | ||||
| 		/* no content to add */ | ||||
| /* TODO: return what??? */ | ||||
| qse_printf (QSE_T("ALL DISCARDED...\n")); | ||||
| 	} | ||||
| 	else if (arg->u.put.req->state & QSE_HTRE_COMPLETED) | ||||
| 	{ | ||||
| #if 0 | ||||
| 		len = qse_htre_getcontentlen(arg->u.put.req); | ||||
| 		if (len > 0) | ||||
| 		{ | ||||
| 			ptr = qse_htre_getcontentptr(arg->u.put.req); | ||||
| 			/* TODO: write this to a file */ | ||||
| 		} | ||||
| #endif | ||||
| qse_printf (QSE_T("WRITING 1 [%.*hs]\n"), (int)qse_htre_getcontentlen(arg->u.put.req), qse_htre_getcontentptr(arg->u.put.req)); | ||||
| 	} | ||||
| 	else if (arg->u.put.req->attr.flags & QSE_HTRE_ATTR_LENGTH) | ||||
| 	{ | ||||
| 		/* Content-Length is included and the content | ||||
| 		 * has been received partially so far */ | ||||
|  | ||||
| #if 0 | ||||
| 		len = qse_htre_getcontentlen(arg->u.put.req); | ||||
| 		if (len > 0) | ||||
| 		{ | ||||
| 			ptr = qse_htre_getcontentptr(arg->u.put.req); | ||||
| 			/* TODO: write to a file */ | ||||
| 		} | ||||
|  | ||||
| #endif | ||||
| qse_printf (QSE_T("WRITING 2 [%.*hs]\n"), (int)qse_htre_getcontentlen(arg->u.put.req), qse_htre_getcontentptr(arg->u.put.req)); | ||||
| 		snatch_needed = 1; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		/* if this request is not chunked nor not length based, | ||||
| 		 * the state should be QSE_HTRE_COMPLETED. so only a | ||||
| 		 * chunked request should reach here */ | ||||
| 		QSE_ASSERT (arg->u.put.req->attr.flags & QSE_HTRE_ATTR_CHUNKED); | ||||
|  | ||||
| qse_printf (QSE_T("WRITING 3 [%.*hs]\n"), (int)qse_htre_getcontentlen(arg->u.put.req), qse_htre_getcontentptr(arg->u.put.req)); | ||||
| #if 0 | ||||
| 		len = qse_htre_getcontentlen(arg->u.put.req); | ||||
| 		if (len > 0) | ||||
| 		{ | ||||
| 			ptr = qse_htre_getcontentptr(arg->u.put.req); | ||||
| 		} | ||||
| #endif | ||||
|  | ||||
| 		snatch_needed = 1; | ||||
| 	} | ||||
|  | ||||
| 	if (snatch_needed) | ||||
| 	{ | ||||
| 		/* set up a callback to be called when the request content | ||||
| 		 * is fed to the htrd reader. qse_htre_addcontent() that  | ||||
| 		 * htrd calls invokes this callback. */ | ||||
| 		file->u.put.req = arg->u.put.req; | ||||
| 		qse_htre_setconcb (file->u.put.req, putfile_snatch_client_input, task); | ||||
| 	} | ||||
|  | ||||
| 	/* no triggers yet since the main loop doesn't allow me to set  | ||||
| 	 * triggers in the task initializer. however the main task handler | ||||
| 	 * will be invoked so long as the client handle is writable by | ||||
| 	 * the main loop. */ | ||||
|  | ||||
| 	task->ctx = file; /* switch the task context to the extension area */ | ||||
| 	return 0; | ||||
|  | ||||
| oops: | ||||
| 	/* since a new task can't be added in the initializer, | ||||
| 	 * i mark that initialization failed and let task_main_putfile() | ||||
| 	 * add an error task */ | ||||
| 	file->u.put.flags |= PUTFILE_INIT_FAILED; | ||||
| 	task->ctx = file; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void task_fini_putfile ( | ||||
| 	qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) | ||||
| { | ||||
| 	task_file_t* file = (task_file_t*)task->ctx; | ||||
|  | ||||
| qse_printf (QSE_T("put fini....\n")); | ||||
| 	if (!(file->u.put.flags & PUTFILE_INIT_FAILED)) | ||||
| 		httpd->opt.scb.file.close (httpd, file->u.put.handle); | ||||
| } | ||||
|  | ||||
| static int task_main_putfile ( | ||||
| 	qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) | ||||
| { | ||||
| 	task_file_t* file = (task_file_t*)task->ctx; | ||||
| qse_printf (QSE_T("put main....\n")); | ||||
|  | ||||
| 	if (file->u.put.req) | ||||
| 	{ | ||||
| qse_printf (QSE_T("put xxxxx....\n")); | ||||
| 		/* still snatching the content body */ | ||||
| 		task->trigger[0].mask = QSE_HTTPD_TASK_TRIGGER_READ; | ||||
| 		task->trigger[0].handle = client->handle; | ||||
| 		return 1; | ||||
| 	} | ||||
|  | ||||
| qse_printf (QSE_T("put what....\n")); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /*------------------------------------------------------------------------*/ | ||||
|  | ||||
| static QSE_INLINE int task_main_delfile ( | ||||
| 	qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) | ||||
| { | ||||
| 	/* TODO: implement this */ | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| /*------------------------------------------------------------------------*/ | ||||
|  | ||||
| qse_httpd_task_t* qse_httpd_entaskfile ( | ||||
| 	qse_httpd_t* httpd, | ||||
| 	qse_httpd_client_t* client,  | ||||
| @ -317,35 +534,50 @@ qse_httpd_task_t* qse_httpd_entaskfile ( | ||||
| 	qse_httpd_task_t task; | ||||
| 	task_file_t data; | ||||
| 	const qse_htre_hdrval_t* tmp; | ||||
| 	int meth; | ||||
|  | ||||
| 	meth = qse_htre_getqmethodtype(req);; | ||||
| 	qse_size_t xtnsize; | ||||
|  | ||||
| 	QSE_MEMSET (&data, 0, QSE_SIZEOF(data)); | ||||
| 	data.path.ptr = path; | ||||
| 	data.path.len = qse_mbslen(path); | ||||
| 	if (mime) | ||||
| 	{ | ||||
| 		data.mime.ptr = mime; | ||||
| 		data.mime.len = qse_mbslen(mime); | ||||
| 	} | ||||
| 	data.version = *qse_htre_getversion(req); | ||||
| 	data.keepalive = (req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE); | ||||
| 	data.method = qse_htre_getqmethodtype(req); | ||||
|  | ||||
| 	switch (meth) | ||||
| 	xtnsize = QSE_SIZEOF(task_file_t) + data.path.len + 1; | ||||
|  | ||||
| 	QSE_MEMSET (&task, 0, QSE_SIZEOF(task)); | ||||
|  | ||||
| 	switch (data.method) | ||||
| 	{ | ||||
| 		case QSE_HTTP_HEAD: | ||||
| 			data.headonly = 1; | ||||
| 			break; | ||||
| 	 | ||||
| 		case QSE_HTTP_OPTIONS: | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_HTTP_GET: | ||||
| 		case QSE_HTTP_POST: | ||||
| 		case QSE_HTTP_PUT: | ||||
| 			qse_htre_discardcontent (req); | ||||
|  | ||||
| 			if (mime) | ||||
| 			{ | ||||
| 				data.u.get.mime.ptr = mime; | ||||
| 				data.u.get.mime.len = qse_mbslen(mime); | ||||
| 				xtnsize += data.u.get.mime.len + 1; | ||||
| 			} | ||||
|  | ||||
| 			task.init = task_init_getfile; | ||||
| 			task.main = task_main_getfile; | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_HTTP_PUT: | ||||
| 			data.u.put.req = req; | ||||
| 			task.init = task_init_putfile; | ||||
| 			task.main = task_main_putfile; | ||||
| 			task.fini = task_fini_putfile; | ||||
| 			break; | ||||
|  | ||||
| #if 0 | ||||
| 		case QSE_HTTP_DELETE: | ||||
| 			task.main = task_main_delfile; | ||||
| 			break; | ||||
| #endif | ||||
|  | ||||
| 		default: | ||||
| 			/* Method not allowed */ | ||||
| 			return qse_httpd_entaskerr (httpd, client, pred, 405, req); | ||||
| @ -395,12 +627,7 @@ qse_httpd_task_t* qse_httpd_entaskfile ( | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	QSE_MEMSET (&task, 0, QSE_SIZEOF(task)); | ||||
| 	task.init = task_init_file; | ||||
| 	task.main = task_main_file; | ||||
| 	task.ctx = &data; | ||||
|  | ||||
| 	return qse_httpd_entask (httpd, client, pred, &task,  | ||||
| 		QSE_SIZEOF(task_file_t) + data.path.len + 1 + data.mime.len + 1); | ||||
| 	return qse_httpd_entask (httpd, client, pred, &task, xtnsize); | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -350,9 +350,11 @@ static int proxy_htrd_peek_peer_output (qse_htrd_t* htrd, qse_htre_t* res) | ||||
| { | ||||
| 	proxy_peer_htrd_xtn_t* xtn; | ||||
| 	task_proxy_t* proxy; | ||||
| 	qse_httpd_t* httpd; | ||||
|  | ||||
| 	xtn = (proxy_peer_htrd_xtn_t*) qse_htrd_getxtn (htrd); | ||||
| 	proxy = xtn->proxy; | ||||
| 	httpd = proxy->httpd; | ||||
|  | ||||
| 	QSE_ASSERT (!(res->state & QSE_HTRE_DISCARDED)); | ||||
|  | ||||
| @ -361,7 +363,7 @@ static int proxy_htrd_peek_peer_output (qse_htrd_t* htrd, qse_htre_t* res) | ||||
| 		/* this peek handler is being called again.  | ||||
| 		 * this can happen if qse_htrd_feed() is fed with | ||||
| 		 * multiple responses in task_main_proxy_2 (). */ | ||||
| 		proxy->httpd->errnum = QSE_HTTPD_EINVAL; | ||||
| 		httpd->errnum = QSE_HTTPD_EINVAL; | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| @ -380,7 +382,7 @@ static int proxy_htrd_peek_peer_output (qse_htrd_t* htrd, qse_htre_t* res) | ||||
| 		    qse_mbs_cat (proxy->res, qse_htre_getsmesg(res)) == (qse_size_t)-1 || | ||||
| 		    qse_mbs_cat (proxy->res, QSE_MT("\r\n\r\n")) == (qse_size_t)-1)  | ||||
| 		{ | ||||
| 			proxy->httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 			httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 			return -1;  | ||||
| 		} | ||||
|  | ||||
| @ -397,10 +399,6 @@ static int proxy_htrd_peek_peer_output (qse_htrd_t* htrd, qse_htre_t* res) | ||||
| 		proxy->resflags &= ~PROXY_RES_AWAIT_RESHDR; | ||||
| 		proxy->resflags |= PROXY_RES_RECEIVED_RESHDR; | ||||
|  | ||||
| #if 0 | ||||
| qse_printf (QSE_T("NORMAL REPLY 222222222222222222222 NORMAL REPLY\n")); | ||||
| #endif | ||||
|  | ||||
| 		keepalive = proxy->keepalive; | ||||
| 		if (res->attr.flags & QSE_HTRE_ATTR_LENGTH) | ||||
| 		{ | ||||
| @ -448,7 +446,7 @@ qse_printf (QSE_T("NORMAL REPLY 222222222222222222222 NORMAL REPLY\n")); | ||||
| 				/* mark that the connection to client should be closed */ | ||||
| 				proxy->resflags |= PROXY_RES_CLIENT_DISCON;  | ||||
| 				/* and push the actual disconnection task */ | ||||
| 				if (qse_httpd_entaskdisconnect (proxy->httpd, xtn->client, xtn->task) == QSE_NULL) return -1; | ||||
| 				if (qse_httpd_entaskdisconnect (httpd, xtn->client, xtn->task) == QSE_NULL) return -1; | ||||
|  | ||||
| 				if (res->attr.flags & QSE_HTRE_ATTR_CHUNKED) | ||||
| 					proxy->resflags |= PROXY_RES_PEER_CHUNK; | ||||
| @ -471,7 +469,7 @@ qse_printf (QSE_T("NORMAL REPLY 222222222222222222222 NORMAL REPLY\n")); | ||||
| 			    qse_mbs_cat (proxy->res, QSE_MT(".")) == (qse_size_t)-1 || | ||||
| 			    qse_mbs_cat (proxy->res, minor) == (qse_size_t)-1) | ||||
| 			{ | ||||
| 				proxy->httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 				httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 				return -1; | ||||
| 			} | ||||
| 		} | ||||
| @ -479,7 +477,7 @@ qse_printf (QSE_T("NORMAL REPLY 222222222222222222222 NORMAL REPLY\n")); | ||||
| 		{ | ||||
| 			if (qse_mbs_cat (proxy->res, qse_htre_getverstr(res)) == (qse_size_t)-1)  | ||||
| 			{ | ||||
| 				proxy->httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 				httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 				return -1; | ||||
| 			} | ||||
| 		} | ||||
| @ -490,19 +488,19 @@ qse_printf (QSE_T("NORMAL REPLY 222222222222222222222 NORMAL REPLY\n")); | ||||
| 		    qse_mbs_cat (proxy->res, qse_htre_getsmesg(res)) == (qse_size_t)-1 || | ||||
| 		    qse_mbs_cat (proxy->res, QSE_MT("\r\n")) == (qse_size_t)-1)  | ||||
| 		{ | ||||
| 			proxy->httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 			httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 			return -1;  | ||||
| 		} | ||||
| 		/* end initial line */ | ||||
|  | ||||
| 		if (!(proxy->httpd->opt.trait & QSE_HTTPD_PROXYNOVIA) && qse_htre_getscodeval(res) != 100) | ||||
| 		if (!(httpd->opt.trait & QSE_HTTPD_PROXYNOVIA) && qse_htre_getscodeval(res) != 100) | ||||
| 		{ | ||||
| 			/* add the Via: header into the response if it is not 100. */ | ||||
| 			if (qse_mbs_cat (proxy->res, QSE_MT("Via: ")) == (qse_size_t)-1 || | ||||
| 			    qse_mbs_cat (proxy->res, qse_httpd_getname (proxy->httpd)) == (qse_size_t)-1 || | ||||
| 			    qse_mbs_cat (proxy->res, qse_httpd_getname (httpd)) == (qse_size_t)-1 || | ||||
| 			    qse_mbs_cat (proxy->res, QSE_MT("\r\n")) == (qse_size_t)-1)  | ||||
| 			{ | ||||
| 				proxy->httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 				httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 				return -1;  | ||||
| 			} | ||||
| 		} | ||||
| @ -523,7 +521,7 @@ qse_printf (QSE_T("NORMAL REPLY 222222222222222222222 NORMAL REPLY\n")); | ||||
| 			    qse_mbs_cat (proxy->res, buf) == (qse_size_t)-1 || | ||||
| 			    qse_mbs_cat (proxy->res, QSE_MT("\r\n")) == (qse_size_t)-1) | ||||
| 			{ | ||||
| 				proxy->httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 				httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 				return -1; | ||||
| 			} | ||||
| 		} | ||||
| @ -531,14 +529,14 @@ qse_printf (QSE_T("NORMAL REPLY 222222222222222222222 NORMAL REPLY\n")); | ||||
| 		{ | ||||
| 			if (qse_mbs_cat (proxy->res, QSE_MT("Transfer-Encoding: chunked\r\n")) == (qse_size_t)-1)  | ||||
| 			{ | ||||
| 				proxy->httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 				httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 				return -1; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (qse_mbs_cat (proxy->res, (keepalive? QSE_MT("Connection: keep-alive\r\n"): QSE_MT("Connection: close\r\n"))) == (qse_size_t)-1)  | ||||
| 		{ | ||||
| 			proxy->httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 			httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| @ -551,10 +549,10 @@ qse_printf (QSE_T("NORMAL REPLY 222222222222222222222 NORMAL REPLY\n")); | ||||
| 		if ((proxy->resflags & PROXY_RES_PEER_LENGTH) &&  | ||||
| 		    proxy->peer_output_received > proxy->peer_output_length) | ||||
| 		{ | ||||
| 			if (proxy->httpd->opt.trait & QSE_HTTPD_LOGACT)  | ||||
| 			if (httpd->opt.trait & QSE_HTTPD_LOGACT)  | ||||
| 				log_proxy_error (proxy, "proxy redundant output - "); | ||||
|  | ||||
| 			proxy->httpd->errnum = QSE_HTTPD_EINVAL; /* TODO: change it to a better error code */ | ||||
| 			httpd->errnum = QSE_HTTPD_EINVAL; /* TODO: change it to a better error code */ | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| @ -577,7 +575,7 @@ qse_printf (QSE_T("NORMAL REPLY 222222222222222222222 NORMAL REPLY\n")); | ||||
| 				    qse_mbs_ncat (proxy->res, qse_htre_getcontentptr(res), qse_htre_getcontentlen(res)) == (qse_size_t)-1 || | ||||
| 				    qse_mbs_cat (proxy->res, QSE_MT("\r\n")) == (qse_size_t)-1)  | ||||
| 				{ | ||||
| 					proxy->httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 					httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 					return -1; | ||||
| 				} | ||||
| 			} | ||||
| @ -585,7 +583,7 @@ qse_printf (QSE_T("NORMAL REPLY 222222222222222222222 NORMAL REPLY\n")); | ||||
| 			{ | ||||
| 				if (qse_mbs_ncat (proxy->res, qse_htre_getcontentptr(res), qse_htre_getcontentlen(res)) == (qse_size_t)-1)  | ||||
| 				{ | ||||
| 					proxy->httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 					httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 					return -1; | ||||
| 				} | ||||
| 			} | ||||
| @ -596,9 +594,6 @@ qse_printf (QSE_T("NORMAL REPLY 222222222222222222222 NORMAL REPLY\n")); | ||||
| 			/* arrange to store further contents received to proxy->res */ | ||||
| 			qse_htre_setconcb (res, proxy_snatch_peer_output, xtn->task); | ||||
| 		} | ||||
| #if 0 | ||||
| qse_printf (QSE_T("NORMAL REPLY 222222222222222222222 NORMAL REPLY OK\n")); | ||||
| #endif | ||||
| 	} | ||||
|  | ||||
| 	proxy->res_pending = QSE_MBS_LEN(proxy->res) - proxy->res_consumed; | ||||
| @ -909,7 +904,7 @@ oops: | ||||
| 	proxy->init_failed = 1; | ||||
| 	task->ctx = proxy; | ||||
|  | ||||
| 	proxy->httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 	httpd->errnum = QSE_HTTPD_ENOMEM; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -960,7 +955,7 @@ qse_printf (QSE_T("task_main_proxy_5 trigger[0].mask=%d trigger[1].mask=%d trigg | ||||
| 			if (n <= -1) | ||||
| 			{ | ||||
| 				/* can't return internal server error any more... */ | ||||
| 				if (proxy->httpd->opt.trait & QSE_HTTPD_LOGACT)  | ||||
| 				if (httpd->opt.trait & QSE_HTTPD_LOGACT)  | ||||
| 					log_proxy_error (proxy, "proxy send-to-client error - "); | ||||
| 				return -1; | ||||
| 			} | ||||
| @ -1043,7 +1038,7 @@ qse_printf (QSE_T("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigg | ||||
| 				if (proxy->peer_output_received > proxy->peer_output_length) | ||||
| 				{ | ||||
| 					/* proxy returning too much data... something is wrong in PROXY */ | ||||
| 					if (proxy->httpd->opt.trait & QSE_HTTPD_LOGACT)  | ||||
| 					if (httpd->opt.trait & QSE_HTTPD_LOGACT)  | ||||
| 						log_proxy_error (proxy, "proxy redundant output - "); | ||||
| 					return -1; | ||||
| 				} | ||||
| @ -1065,7 +1060,7 @@ qse_printf (QSE_T("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigg | ||||
| 		if (n <= -1) | ||||
| 		{ | ||||
| 			/* can't return internal server error any more... */ | ||||
| 			if (proxy->httpd->opt.trait & QSE_HTTPD_LOGACT) | ||||
| 			if (httpd->opt.trait & QSE_HTTPD_LOGACT) | ||||
| 				log_proxy_error (proxy, "proxy send-to-client error - "); | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| @ -1906,7 +1906,11 @@ if (qse_htre_getcontentlen(req) > 0) | ||||
|  | ||||
| 			/* if the resource is indicating to return an error, | ||||
| 			 * discard the contents since i won't return them */ | ||||
| 			if (rsrc.type == QSE_HTTPD_RSRC_ERR) qse_httpd_discardcontent (httpd, req);  | ||||
| 			if (rsrc.type == QSE_HTTPD_RSRC_ERR)  | ||||
| 			{  | ||||
| qse_printf (QSE_T("DISCARD 3\n")); | ||||
| 				qse_httpd_discardcontent (httpd, req);  | ||||
| 			} | ||||
| 		} | ||||
| 		if (task == QSE_NULL) goto oops; | ||||
| 	} | ||||
| @ -2414,7 +2418,7 @@ static int make_resource ( | ||||
| 	struct rsrc_tmp_t tmp; | ||||
|  | ||||
| 	qse_httpd_stat_t st; | ||||
| 	int n, stx, meth; | ||||
| 	int n, stx, method; | ||||
|  | ||||
| 	QSE_MEMSET (&tmp, 0, QSE_SIZEOF(tmp)); | ||||
| 	tmp.qpath = qse_htre_getqpath(req); | ||||
| @ -2439,16 +2443,24 @@ static int make_resource ( | ||||
| 	} | ||||
|  | ||||
| 	/* handle the request locally */ | ||||
|  | ||||
| #if 0 | ||||
| 	meth = qse_htre_getqmethodtype(req); | ||||
| 	if (meth != QSE_HTTP_GET && meth != QSE_HTTP_POST && meth != QSE_HTTP_PUT && method != QSE_HTTP_) | ||||
| 	method = qse_htre_getqmethodtype(req); | ||||
| 	switch (method) | ||||
| 	{ | ||||
| /* TODO: handle more method types */ | ||||
| 		/* method not allowed */ | ||||
| 		target->type = QSE_HTTPD_RSRC_ERR; | ||||
| 		target->u.err.code = 405; | ||||
| 		return 0; | ||||
| 		case QSE_HTTP_HEAD: | ||||
| 		case QSE_HTTP_GET: | ||||
| 		case QSE_HTTP_POST: | ||||
| 		case QSE_HTTP_PUT: | ||||
| 		case QSE_HTTP_DELETE: | ||||
| 		case QSE_HTTP_OPTIONS: | ||||
| 			/* let these methods be handled locally */ | ||||
| 			break; | ||||
|  | ||||
| 		default: | ||||
| 			/* method not allowed */ | ||||
| 			target->type = QSE_HTTPD_RSRC_ERR; | ||||
| 			target->u.err.code = 405; | ||||
| 			return 0; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
|  | ||||
| @ -263,6 +263,7 @@ qse_httpd_task_t* qse_httpd_entaskerr ( | ||||
| 	qse_httpd_t* httpd, qse_httpd_client_t* client,  | ||||
| 	qse_httpd_task_t* pred, int code, qse_htre_t* req) | ||||
| { | ||||
| 	qse_htre_discardcontent (req); | ||||
| 	return entask_status ( | ||||
| 		httpd, client, pred, code, QSE_NULL,  | ||||
| 		qse_htre_getversion(req), (req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE)); | ||||
| @ -411,17 +412,14 @@ qse_httpd_task_t* qse_httpd_entaskrsrc ( | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_HTTPD_RSRC_DIR: | ||||
| 			qse_httpd_discardcontent (httpd, req); | ||||
| 			task = qse_httpd_entaskdir (httpd, client, pred, rsrc->u.dir.path, req); | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_HTTPD_RSRC_ERR: | ||||
| 			qse_httpd_discardcontent (httpd, req); | ||||
| 			task = qse_httpd_entaskerr (httpd, client, pred, rsrc->u.err.code, req); | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_HTTPD_RSRC_FILE: | ||||
| 			qse_httpd_discardcontent (httpd, req); | ||||
| 			task = qse_httpd_entaskfile (httpd, client, pred, rsrc->u.file.path, rsrc->u.file.mime, req); | ||||
| 			break; | ||||
| 	 | ||||
|  | ||||
		Reference in New Issue
	
	Block a user