Example #1
0
/**
 * httpserver_dispatcher:
 * @data: RequestData type pointer
 * @user_data: httpstreaming type pointer
 *
 * Process http request.
 *
 * Returns: positive value if have not completed the processing, for example live streaming.
 *      0 if have completed the processing.
 */
static GstClockTime
httpstreaming_dispatcher (gpointer data, gpointer user_data)
{
        RequestData *request_data = data;
        HTTPStreaming *httpstreaming = (HTTPStreaming *)user_data;
        gchar *buf;
        int i = 0, j, ret;
        Encoder *encoder;
        EncoderOutput *encoder_output;
        Channel *channel;
        RequestDataUserData *request_user_data;
        GstClockTime ret_clock_time;

        channel = get_channel (httpstreaming, request_data);
        switch (request_data->status) {
        case HTTP_REQUEST:
                GST_DEBUG ("new request arrived, socket is %d, uri is %s", request_data->sock, request_data->uri);
                encoder_output = get_encoder_output (httpstreaming, request_data);
                if (encoder_output == NULL) {
                        buf = g_strdup_printf (http_404, PACKAGE_NAME, PACKAGE_VERSION);
                        httpserver_write (request_data->sock, buf, strlen (buf));
                        g_free (buf);
                        return 0;
                } else if ((request_data->parameters[0] == '\0') || (request_data->parameters[0] == 'b')) {
                        /* default operator is play, ?bitrate= */
                        GST_ERROR ("Play %s.", request_data->uri);
                        request_user_data = (RequestDataUserData *)g_malloc (sizeof (RequestDataUserData));//FIXME
                        if (request_user_data == NULL) {
                                GST_ERROR ("Internal Server Error, g_malloc for request_user_data failure.");
                                buf = g_strdup_printf (http_500, PACKAGE_NAME, PACKAGE_VERSION);
                                httpserver_write (request_data->sock, buf, strlen (buf));
                                g_free (buf);
                                return 0;
                        }

                        if (*(encoder_output->head_addr) == *(encoder_output->tail_addr)) {
                                GST_DEBUG ("%s unready.", request_data->uri);
                                buf = g_strdup_printf (http_404, PACKAGE_NAME, PACKAGE_VERSION);
                                httpserver_write (request_data->sock, buf, strlen (buf));
                                g_free (buf);
                                return 0;
                        }

                        /* let send_chunk send new chunk. */
                        encoder = get_encoder (request_data->uri, httpstreaming->itvencoder->channel_array);
                        request_user_data->encoder = encoder;
                        request_user_data->chunk_size = 0;
                        request_user_data->send_count = 2;
                        request_user_data->chunk_size_str = g_strdup ("");
                        request_user_data->chunk_size_str_len = 0;
                        request_user_data->encoder_output = encoder_output;
                        request_user_data->current_rap_addr = *(encoder_output->last_rap_addr);
                        request_user_data->current_send_position = *(encoder_output->last_rap_addr) + 12;
                        request_user_data->channel_age = channel->age;
                        request_data->user_data = request_user_data;
                        request_data->bytes_send = 0;
                        buf = g_strdup_printf (http_chunked, PACKAGE_NAME, PACKAGE_VERSION);
                        httpserver_write (request_data->sock, buf, strlen (buf));
                        g_free (buf);
                        return gst_clock_get_time (httpstreaming->httpserver->system_clock) + GST_MSECOND;
                } else {
                        buf = g_strdup_printf (http_404, PACKAGE_NAME, PACKAGE_VERSION);
                        httpserver_write (request_data->sock, buf, strlen (buf));
                        g_free (buf);
                        return 0;
                }
                break;
        case HTTP_CONTINUE:
                request_user_data = request_data->user_data;
                if ((request_user_data->channel_age != channel->age) ||
                    (*(channel->output->state) != GST_STATE_PLAYING)) {
                        g_free (request_data->user_data);
                        request_data->user_data = NULL;
                        return 0;
                }
                encoder_output = request_user_data->encoder_output;
                if (request_user_data->current_send_position == *(encoder_output->tail_addr)) {
                        /* no more stream, wait 10ms */
                        GST_DEBUG ("current:%llu == tail:%llu", request_user_data->current_send_position, encoder_output->tail_addr);
						return gst_clock_get_time (httpstreaming->httpserver->system_clock) + 500 * GST_MSECOND + g_random_int_range (1, 1000000);
                }
                ret_clock_time = send_chunk (encoder_output, request_data);
                if (ret_clock_time != GST_CLOCK_TIME_NONE)
                {
                        return ret_clock_time + gst_clock_get_time (httpstreaming->httpserver->system_clock);
                }
                else
                {
                        return GST_CLOCK_TIME_NONE;
                }
        case HTTP_FINISH:
                g_free (request_data->user_data);
                request_data->user_data = NULL;
                return 0;
        default:
                GST_ERROR ("Unknown status %d", request_data->status);
                buf = g_strdup_printf (http_400, PACKAGE_NAME, PACKAGE_VERSION);
                httpserver_write (request_data->sock, buf, strlen (buf));
                g_free (buf);
                return 0;
        }
}
Example #2
0
static void thread_pool_func (gpointer data, gpointer user_data)
{
    HTTPServer *http_server = (HTTPServer *)user_data;
    RequestData **request_data_pointer = data;
    RequestData *request_data = *request_data_pointer;
    gint ret;
    GstClockTime cb_ret;

    GST_DEBUG ("EVENT %d, status %d, sock %d", request_data->events, request_data->status, request_data->sock);
    g_mutex_lock (&(request_data->events_mutex));
    if (request_data->events & (EPOLLHUP | EPOLLERR)) {
        request_data->status = HTTP_FINISH;
        request_data->events = 0;

    } else if (request_data->events & EPOLLOUT) {
        if ((request_data->status == HTTP_IDLE) || (request_data->status == HTTP_BLOCK)) {
            request_data->status = HTTP_CONTINUE;
        }
        request_data->events ^= EPOLLOUT;

    } else if (request_data->events & EPOLLIN) {
        if ((request_data->status == HTTP_IDLE) || (request_data->status == HTTP_BLOCK)) {
            /* in normal play status */
            ret = read_request (request_data);
            if (ret < 0) {
                request_data->status = HTTP_FINISH;

            } else {
                GST_DEBUG ("Unexpected request arrived, ignore.");
                request_data->status = HTTP_CONTINUE;
            }
        } 
        /* HTTP_REQUEST status */
        request_data->events ^= EPOLLIN;

    } else if ((request_data->status == HTTP_IDLE) || (request_data->status == HTTP_BLOCK)) {
        /* no event, popup from idle queue or block queue */
        request_data->status = HTTP_CONTINUE;

    } else {
        GST_WARNING ("warning!!! unprocessed event, sock %d status %d events %d", request_data->sock, request_data->status, request_data->events);
    }
    g_mutex_unlock (&(request_data->events_mutex));

    if (request_data->status == HTTP_REQUEST) {
        ret = read_request (request_data);
        if (ret < 0) {
            request_data_release (http_server, request_data_pointer);
            return;
        } 

        ret = parse_request (request_data);
        if (ret == 0) {
            /* parse complete, call back user function */
            request_data->events ^= EPOLLIN;
            invoke_user_callback (http_server, request_data_pointer);

        } else if (ret == 1) {
            /* need read more data */
            g_mutex_lock (&(http_server->block_queue_mutex));
            g_queue_push_head (http_server->block_queue, request_data_pointer);
            g_mutex_unlock (&(http_server->block_queue_mutex));
            return;

        } else if (ret == 2) {
            /* Not Implemented */
            GST_WARNING ("Not Implemented, return is %d, sock is %d", ret, request_data->sock);
            gchar *buf = g_strdup_printf (http_501, PACKAGE_NAME, PACKAGE_VERSION);
            if (httpserver_write (request_data->sock, buf, strlen (buf)) != strlen (buf)) {
                GST_ERROR ("write sock %d error.", request_data->sock);
            }
            g_free (buf);
            request_data_release (http_server, request_data_pointer);

        } else {
            /* Bad Request */
            GST_WARNING ("Bad request, return is %d, sock is %d", ret, request_data->sock);
            gchar *buf = g_strdup_printf (http_400, PACKAGE_NAME, PACKAGE_VERSION);
            if (httpserver_write (request_data->sock, buf, strlen (buf)) != strlen (buf)) {
                GST_ERROR ("write sock %d error.", request_data->sock);
            }
            g_free (buf);
            request_data_release (http_server, request_data_pointer);
        }

    } else if (request_data->status == HTTP_CONTINUE) {
        invoke_user_callback (http_server, request_data_pointer);

    } else if (request_data->status == HTTP_FINISH) { // FIXME: how about if have continue request in idle queue??
        cb_ret = http_server->user_callback (request_data, http_server->user_data);
        GST_DEBUG ("request finish %d callback return %lu, send %lu", request_data->sock, cb_ret, request_data->bytes_send);
        if (cb_ret == 0) {
            g_mutex_lock (&(http_server->idle_queue_mutex));
            g_tree_remove (http_server->idle_queue, &(request_data->wakeup_time));
            g_mutex_unlock (&(http_server->idle_queue_mutex));
            request_data_release (http_server, request_data_pointer);
        }
    }
}