示例#1
0
static liHandlerResult progress_show(liVRequest *vr, gpointer param, gpointer *context) {
	mod_progress_show_param *psp = (mod_progress_show_param*) param;
	gboolean debug = _OPTION(vr, psp->p, 0).boolean;
	gchar *id;
	guint id_len;
	liCollectInfo *ci;
	mod_progress_job *job;

	if (*context)
		return LI_HANDLER_WAIT_FOR_EVENT;

	if (li_vrequest_is_handled(vr))
		return LI_HANDLER_GO_ON;

	if (!li_querystring_find(vr->request.uri.query, CONST_STR_LEN("X-Progress-Id"), &id, &id_len) || id_len == 0 || id_len > 128) {
		if (debug)
			VR_DEBUG(vr, "%s", "progress.show: X-Progress-Id not specified");
		return LI_HANDLER_GO_ON;
	}

	/* start collect job */
	job = g_slice_new(mod_progress_job);
	job->vr = vr;
	job->context = context;
	job->format = psp->format;
	job->debug = debug;

	job->p = psp->p;
	job->id = g_strndup(id, id_len);

	ci = li_collect_start(vr->wrk, progress_collect_func, job, progress_collect_cb, NULL);
	*context = ci; /* may be NULL */
	return ci ? LI_HANDLER_WAIT_FOR_EVENT : LI_HANDLER_GO_ON;
}
示例#2
0
static liHandlerResult progress_track(liVRequest *vr, gpointer param, gpointer *context) {
	gchar *id;
	guint id_len;
	liPlugin *p = (liPlugin*) param;
	gboolean debug = _OPTION(vr, p, 0).boolean;
	gint methods = _OPTION(vr, p, 1).number;
	mod_progress_data *pd = p->data;

	UNUSED(context);

	if (!(methods & (1 << vr->request.http_method))) {
		/* method not tracked */
	} else if (g_ptr_array_index(vr->plugin_ctx, p->id)) {
		/* already tracked */
		VR_WARNING(vr, "%s", "progress.track: already tracking request");
	} else if (li_querystring_find(vr->request.uri.query, CONST_STR_LEN("X-Progress-Id"), &id, &id_len) && id_len <= 128) {
		/* progress id found, start tracking of connection */
		mod_progress_node *node = g_slice_new0(mod_progress_node);
		node->timeout_queue_elem.data = node;
		node->id = g_strndup(id, id_len);
		node->worker_data = &pd->worker_data[vr->wrk->ndx];
		node->vr = vr;
		g_ptr_array_index(vr->plugin_ctx, pd->p->id) = node;
		g_hash_table_replace(node->worker_data->hash_table, node->id, node);

		if (debug)
			VR_DEBUG(vr, "progress.track: tracking progress with id \"%s\"", node->id);
	} else if (debug) {
		VR_DEBUG(vr, "%s", "progress.track: X-Progress-Id parameter not found, cannot track request");
	}

	return LI_HANDLER_GO_ON;
}
示例#3
0
/* the CollectCallback */
static void progress_collect_cb(gpointer cbdata, gpointer fdata, GPtrArray *result, gboolean complete) {
	guint i;
	GString *output;
	mod_progress_node *node = NULL;
	mod_progress_job *job = fdata;
	liVRequest *vr = job->vr;
	gboolean debug = job->debug;
	mod_progress_format format = job->format;

	UNUSED(cbdata);

	if (complete) {
		/* clear context so it doesn't get cleaned up anymore */
		*(job->context) = NULL;

		for (i = 0; i < result->len; i++) {
			node = g_ptr_array_index(result, i);
			if (node)
				break;
		}

		output = g_string_sized_new(128);

		/* send mime-type. there seems to be no standard for javascript... using the most commong */
		li_http_header_overwrite(vr->response.headers, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("application/x-javascript"));

		if (format == PROGRESS_FORMAT_LEGACY) {
			g_string_append_len(output, CONST_STR_LEN("new Object("));
		} else if (format == PROGRESS_FORMAT_JSONP) {
			gchar *val;
			guint len;

			if (li_querystring_find(vr->request.uri.query, CONST_STR_LEN("X-Progress-Callback"), &val, &len)) {
				/* X-Progress-Callback specified, need to check for xss */
				gchar *c;

				for (c = val; c != val+len; c++) {
					if ((*c >= 'a' && *c <= 'z') || (*c >= 'A' && *c <= 'Z') || (*c >= '0' && *c <= '9') || *c == '.' || *c == '_')
						continue;
					break;
				}

				/* was there a bad char? */
				if (c != val+len) {
					g_string_append_len(output, CONST_STR_LEN("progress("));
				} else {
					g_string_append_len(output,val, len);
					g_string_append_c(output, '(');
				}
			} else {
				g_string_append_len(output, CONST_STR_LEN("progress("));
			}
		}

		if (!node) {
			/* progress id not known */
			if (debug)
				VR_DEBUG(vr, "progress.show: progress id \"%s\" unknown", job->id);
			
			g_string_append_len(output, CONST_STR_LEN("{\"state\": \"unknown\"}"));
		} else {
			if (debug)
				VR_DEBUG(vr, "progress.show: progress id \"%s\" found", job->id);

			if (node->vr) {
				/* still in progress */
				g_string_append_printf(output,
					"{\"state\": \"running\", \"received\": %"G_GUINT64_FORMAT", \"sent\": %"G_GUINT64_FORMAT", \"request_size\": %"G_GUINT64_FORMAT", \"response_size\": %"G_GUINT64_FORMAT"}",
					node->bytes_in, node->bytes_out, node->request_size, node->response_size
				);
			} else if (node->status_code == 200) {
				/* done, success */
				g_string_append_printf(output,
					"{\"state\": \"done\", \"received\": %"G_GUINT64_FORMAT", \"sent\": %"G_GUINT64_FORMAT", \"request_size\": %"G_GUINT64_FORMAT", \"response_size\": %"G_GUINT64_FORMAT"}",
					node->bytes_in, node->bytes_out, node->request_size, node->response_size
				);
			} else {
				/* done, error */
				g_string_append_printf(output,
					"{\"state\": \"error\", \"status\": %d}",
					node->status_code
				);
			}
		}

		if (format == PROGRESS_FORMAT_LEGACY || format == PROGRESS_FORMAT_JSONP) {
			g_string_append_c(output, ')');
		}

		vr->response.http_status = 200;
		li_chunkqueue_append_string(vr->out, output);
		li_vrequest_handle_direct(vr);
		li_vrequest_joblist_append(vr);
	}

	/* free results */
	for (i = 0; i < result->len; i++) {
		if (g_ptr_array_index(result, i))
			g_slice_free(mod_progress_node, g_ptr_array_index(result, i));
	}

	g_free(job->id);
	g_slice_free(mod_progress_job, job);
}
示例#4
0
static liHandlerResult flv(liVRequest *vr, gpointer param, gpointer *context) {
    gchar *start;
    guint len;
    goffset pos;
    liHandlerResult res;
    gboolean cachable;
    struct stat st;
    int err;
    int fd = -1;

    UNUSED(context);
    UNUSED(param);

    if (li_vrequest_is_handled(vr))
        return LI_HANDLER_GO_ON;

    res = li_stat_cache_get(vr, vr->physical.path, &st, &err, &fd);

    if (res == LI_HANDLER_WAIT_FOR_EVENT)
        return res;

    if (res == LI_HANDLER_ERROR) {
        /* open or fstat failed */

        if (fd != -1)
            close(fd);

        if (!li_vrequest_handle_direct(vr))
            return LI_HANDLER_ERROR;

        switch (err) {
        case ENOENT:
        case ENOTDIR:
            vr->response.http_status = 404;
            return LI_HANDLER_GO_ON;
        case EACCES:
            vr->response.http_status = 403;
            return LI_HANDLER_GO_ON;
        default:
            VR_ERROR(vr, "stat() or open() for '%s' failed: %s", vr->physical.path->str, g_strerror(err));
            return LI_HANDLER_ERROR;
        }
    } else if (S_ISDIR(st.st_mode)) {
        if (fd != -1)
            close(fd);

        return LI_HANDLER_GO_ON;
    } else if (!S_ISREG(st.st_mode)) {
        if (fd != -1)
            close(fd);

        if (!li_vrequest_handle_direct(vr))
            return LI_HANDLER_ERROR;

        vr->response.http_status = 403;
    } else {
        liChunkFile *cf;

#ifdef FD_CLOEXEC
        fcntl(fd, F_SETFD, FD_CLOEXEC);
#endif

        if (!li_vrequest_handle_direct(vr)) {
            close(fd);
            return LI_HANDLER_ERROR;
        }

        if (li_querystring_find(vr->request.uri.query, CONST_STR_LEN("start"), &start, &len)) {
            guint i;
            pos = 0;

            for (i = 0; i < len; i++) {
                if (start[i] >= '0' && start[i] <= '9') {
                    pos *= 10;
                    pos += start[i] - '0';
                }
            }
        } else {
            pos = 0;
        }

        li_etag_set_header(vr, &st, &cachable);
        if (cachable) {
            vr->response.http_status = 304;
            close(fd);
            return LI_HANDLER_GO_ON;
        }


        vr->response.http_status = 200;
        li_http_header_overwrite(vr->response.headers, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("video/x-flv"));

        if (pos < 0 || pos > st.st_size)
            pos = 0;

        if (pos != 0)
            li_chunkqueue_append_mem(vr->direct_out, CONST_STR_LEN("FLV\x1\x1\0\0\0\x9\0\0\0\x9"));

        cf = li_chunkfile_new(NULL, fd, FALSE);
        li_chunkqueue_append_chunkfile(vr->direct_out, cf, pos, st.st_size - pos);
        li_chunkfile_release(cf);
    }

    return LI_HANDLER_GO_ON;
}