summaryrefslogtreecommitdiffstats
path: root/src/http.c
blob: fcc6bcc08b1d57c04ca0a53bc4eed7564b5d931c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* Asterisk Manager Proxy
   Copyright (c) 2005 David C. Troy <dave@popvox.com>

   This program is free software, distributed under the terms of
   the GNU General Public License.

   HTTP Input Handler
*/

#include "astmanproxy.h"

int ParseHTTPInput(char *buf, struct message *m) {
    char *n, *v;

    n = buf;
    while ( (v = strstr(n, "=")) ) {
       v += 1;
       debugmsg("n: %s, v: %s", n, v);
       strncat(m->headers[m->hdrcount], n, v-n-1);
       strcat(m->headers[m->hdrcount], ": ");

       if ( (n = strstr(v, "&")) ) {
          n += 1;
       } else {
          n = (v + strlen(v) + 1);
       }
       strncat(m->headers[m->hdrcount], v, n-v-1);
       debugmsg("got hdr: %s", m->headers[m->hdrcount]);
       m->hdrcount++;
    }

    return (m->hdrcount > 0);
}

int BuildHTTPHeader(char *hdr) {


    time_t t;
    struct tm tm;
    char date[80];

    time(&t);
    localtime_r(&t, &tm);
    strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", &tm);

    sprintf(hdr,
       "HTTP/1.1 200 OK\r\n"
       "Date: %s\r\n"
       "Content-Type: text/xml\r\n"
       "Connection: close\r\n"
       "Server: %s/%s\r\n\r\n",
       date, PROXY_BANNER, PROXY_VERSION);

    return 0;
}

int _read(struct mansession *s, struct message *m) {

    /* Note: No single line may be longer than MAX_LEN/s->inbuf, as per get_input */
    /* No HTTP Input may be longer than BUFSIZE */

    char line[MAX_LEN], method[10], formdata[MAX_LEN], header[MAX_LEN];
    int res, clength = 0;

    memset(method, 0, sizeof method);
    memset(formdata, 0, sizeof formdata);
    memset(header, 0, sizeof header);

    /* for http, don't do get_input forever */
    for (;;) {

	if (s->inputcomplete && !s->outputcomplete)
		continue;
	else if (s->inputcomplete && s->outputcomplete)
		return -1;

        memset(line, 0, sizeof line);
        res = get_input(s, line);
	debugmsg("res=%d, line: %s",res, line);

	if (res > 0) {
        	debugmsg("Got http: %s", line);
                /* Do meaningful things here */
                if ( !strncmp(line,"POST",4) ) {
                    strncpy(method, line, 4);
                } else if ( !strncmp(line,"GET",3) ) {
                    /* GET /?Action=Ping&ActionID=Foo HTTP/1.1 */
                    strncpy(method, line, 3);
                    memcpy(formdata, line+6, strstr(line, " HTTP")-line-6);
                } else if ( !strncasecmp(line, "Content-Length: ", 16) ) {
                    clength = atoi(line+16);
                }

		if (*method && s->inlen==clength) {
                    if ( !strcasecmp(method, "POST") ) {
                        pthread_mutex_lock(&s->lock);
                        strncpy(formdata, s->inbuf, clength);
                        s->inlen = 0;
                        pthread_mutex_unlock(&s->lock);
                    }
                    debugmsg("method: %s", method);
                    debugmsg("clength: %d", clength);
                    debugmsg("formdata: %s", formdata);
                    debugmsg("s->inbuf: %s", s->inbuf);
                    debugmsg("s->inlen: %d", s->inlen);

                    BuildHTTPHeader(header);
                    pthread_mutex_lock(&s->lock);
		    s->inputcomplete = 1;
                    ast_carefulwrite(s->fd, header, strlen(header), s->writetimeout);
                    pthread_mutex_unlock(&s->lock);
                    debugmsg("header: %s", header);

                    /* now, let's transform and copy into a standard message block */
                    res = ParseHTTPInput(formdata, m);
                    return res;
		}
        } else if (res < 0)
		break;
    }

    return -1;
}

int _autodisconnect() {
    return 1;
}

/* We do not define a _write or _onconnect method */