~ubuntu-branches/ubuntu/precise/getstream/precise

« back to all changes in this revision

Viewing changes to stream_http.c

  • Committer: Bazaar Package Importer
  • Author(s): Herve Rousseau
  • Date: 2007-05-31 17:23:59 UTC
  • Revision ID: james.westby@ubuntu.com-20070531172359-76b6p4jdyeyvno25
Tags: upstream-20070419
ImportĀ upstreamĀ versionĀ 20070419

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#include <sys/time.h>
 
3
 
 
4
#include <stdlib.h>
 
5
#include <string.h>
 
6
#include <stdio.h>
 
7
 
 
8
#include <glib/glist.h>
 
9
 
 
10
#include "stream.h"
 
11
#include "libhttp.h"
 
12
 
 
13
extern struct http_server       *hserver;
 
14
 
 
15
static void stream_remove_receiver(struct http_receiver_s *hr) {
 
16
        struct stream_s         *s=hr->stream;
 
17
        struct http_connection  *hc=hr->hc;
 
18
 
 
19
        s->http_receiver=g_list_remove(s->http_receiver, hr);
 
20
        s->receiver--;
 
21
 
 
22
        logwrite(LOG_INFO, "stream_http: dropping connection to %s for %s",
 
23
                                inet_ntoa(hc->sin.sin_addr),
 
24
                                hc->url);
 
25
 
 
26
        http_drop_connection(hc);
 
27
}
 
28
 
 
29
static int stream_cb_http(struct http_connection *hc, int cbtype, void *arg) {
 
30
 
 
31
        switch(cbtype) {
 
32
                case(HCB_QUERY): {
 
33
                        struct http_receiver_s  *hr;
 
34
                        struct stream_s         *s=arg; /* HCB_QUERY returns http_url args */
 
35
 
 
36
                        hr=calloc(1, sizeof(struct http_receiver_s));
 
37
                        hr->hc=hc;
 
38
                        hr->stream=s;
 
39
 
 
40
                        /* Put into stream output list */
 
41
                        s->http_receiver=g_list_append(s->http_receiver, hr);
 
42
                        s->receiver++;
 
43
 
 
44
                        /* Store http_receiver into http_connection structure */
 
45
                        hc->arg=hr;
 
46
 
 
47
                        /* Return head */
 
48
                        http_header_start(hc, "200 OK", "application/octet-stream");
 
49
                        http_header_nocache(hc);
 
50
                        http_header_clength(hc, -1);
 
51
                        http_header_end(hc);
 
52
 
 
53
                        logwrite(LOG_INFO, "stream_http: connection from %s for %s",
 
54
                                                inet_ntoa(hc->sin.sin_addr),
 
55
                                                hc->url);
 
56
                        break;
 
57
                }
 
58
                case(HCB_ERROR): {
 
59
                        stream_remove_receiver(hc->arg);
 
60
                        break;
 
61
                }
 
62
        }
 
63
        return 1;
 
64
}
 
65
 
 
66
#define SOUT_HTTP_CHUNK_SIZE    20000
 
67
 
 
68
int stream_init_http(struct stream_s *s) {
 
69
 
 
70
        s->buffer=calloc(1, SOUT_HTTP_CHUNK_SIZE);
 
71
        if (s->buffer == NULL)
 
72
                return 0;
 
73
 
 
74
        s->hurl=calloc(2, sizeof(struct http_url));
 
75
 
 
76
        s->hurl->url=s->url;
 
77
        s->hurl->cb=stream_cb_http;
 
78
        s->hurl->arg=(void *) s;
 
79
 
 
80
        http_register_url(hserver, s->hurl);
 
81
 
 
82
        return 0;
 
83
}
 
84
 
 
85
#define HTTP_MAX_QUEUED         (200*1024)
 
86
#define HTTP_MAX_OVERFLOW       20
 
87
 
 
88
void stream_send_http_one(gpointer data, gpointer user_data) {
 
89
        struct http_receiver_s  *hr=data;
 
90
        struct stream_s         *s=user_data;
 
91
 
 
92
        /*
 
93
         * Check how many bytes we already have queued on this
 
94
         * HTTP connection. Users might connect from low bandwidth
 
95
         * links not beeing able to transmit the full feed. We must
 
96
         * avoid consuming all memory.
 
97
         *
 
98
         * If the situation persists too long we drop the connection
 
99
         *
 
100
         */
 
101
        if (http_get_queue(hr->hc) > HTTP_MAX_QUEUED) {
 
102
                hr->overflow++;
 
103
                if (hr->overflow > HTTP_MAX_OVERFLOW)
 
104
                        stream_remove_receiver(hr);
 
105
                return;
 
106
        }
 
107
        hr->overflow=0;
 
108
 
 
109
        /*
 
110
         * We cant reuse evbuffer as they are empty after
 
111
         * passing the the buffevent layer - Thus we recreate
 
112
         * the buffer every time we send it out. This involes
 
113
         * a little more memcpy as really necessary but for now
 
114
         * its enough
 
115
         *
 
116
         */
 
117
        http_return_stream(hr->hc, s->buffer, s->buffervalid);
 
118
}
 
119
 
 
120
void stream_send_http(struct stream_s *s, uint8_t *tsp) {
 
121
        /* Copy TS packet to packet buffer */
 
122
        memcpy(&s->buffer[s->buffervalid], tsp, TS_PACKET_SIZE);
 
123
        s->buffervalid+=TS_PACKET_SIZE;
 
124
 
 
125
        /* check whether another packet would fit ? */
 
126
        if (s->buffervalid + TS_PACKET_SIZE > SOUT_HTTP_CHUNK_SIZE) {
 
127
                /*
 
128
                 * If the output buffer is full - loop on all http sesssions
 
129
                 * and send out the buffer as a http chunk
 
130
                 */
 
131
                g_list_foreach(s->http_receiver,
 
132
                                stream_send_http_one, (gpointer) s);
 
133
                s->buffervalid=0;
 
134
        }
 
135
}