New functions yaz_file_glob2, yaz_xml_include_glob
[yaz-moved-to-github.git] / test / test_comstack.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2013 Index Data
3  * See the file LICENSE for details.
4  */
5 #if HAVE_CONFIG_H
6 #include <config.h>
7 #endif
8
9 #include <stdlib.h>
10 #include <string.h>
11 #include <stdio.h>
12
13 #include <yaz/test.h>
14 #include <yaz/comstack.h>
15 #include <yaz/tcpip.h>
16
17 static void tst_http_request(void)
18 {
19     {
20         /* no content, no headers */
21         const char *http_buf =
22             /*123456789012345678 */
23             "GET / HTTP/1.1\r\n"
24             "\r\n"
25             "GET / HTTP/1.0\r\n";
26
27         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 1), 0);
28         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 2), 0);
29         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 16), 0);
30         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 17), 0);
31         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 18), 18);
32         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 19), 18);
33     }
34     {
35         /* one header, no content */
36         const char *http_buf =
37             /*123456789012345678 */
38             "GET / HTTP/1.1\r\n"
39             "Content-Type: x\r\n"
40             "\r\n"
41             "GET / HTTP/1.0\r\n";
42
43         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 1), 0);
44         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 2), 0);
45         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 34), 0);
46         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 35), 35);
47         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 36), 35);
48     }
49     {
50         /* one content-length header, length 0 */
51         const char *http_buf =
52             /*123456789012345678 */
53             "GET / HTTP/1.1\r\n"
54             "Content-Length: 0\r\n"
55             "\r\n"
56             "GET / HTTP/1.0\r\n";
57
58         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 1), 0);
59         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 2), 0);
60         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 35), 0);
61         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 37), 37);
62         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 38), 37);
63     }
64     {
65         /* one content-length header, length 5 */
66         const char *http_buf =
67             /*123456789012345678 */
68             "GET / HTTP/1.1\r\n"
69             "Content-Length: 5\r\n"
70             "\r\n"
71             "ABCDE"
72             "GET / HTTP/1.0\r\n";
73
74         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 1), 0);
75         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 2), 0);
76         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 41), 0);
77         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 42), 42);
78         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 43), 42);
79     }
80     {
81         /* LF only in GET, one content-length header, length 5 */
82         const char *http_buf =
83             /*123456789012345678 */
84             "GET / HTTP/1.1\n"
85             "Content-Length: 5\r\n"
86             "\r\n"
87             "ABCDE"
88             "GET / HTTP/1.0\r\n";
89
90         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 1), 0);
91         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 2), 0);
92         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 40), 0);
93         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 41), 41);
94         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 42), 41);
95     }
96     {
97         /* LF only in all places, one content-length header, length 5 */
98         const char *http_buf =
99             /*123456789012345678 */
100             "GET / HTTP/1.1\n"
101             "Content-Length: 5\n"
102             "\n"
103             "ABCDE"
104             "GET / HTTP/1.0\r\n";
105
106         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 1), 0);
107         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 2), 0);
108         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 38), 0);
109         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 39), 39);
110         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 40), 39);
111     }
112
113     {
114         /* one header, unknown transfer-encoding (no content) */
115         const char *http_buf =
116             /*12345678901234567890123456789 */
117             "GET / HTTP/1.1\r\n"
118             "Transfer-Encoding: chunke_\r\n"
119             "\r\n"
120             "GET / HTTP/1.0\r\n";
121
122         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 45), 0);
123         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 46), 46);
124     }
125
126     {
127         /* one header, one chunk */
128         const char *http_buf =
129             /*12345678901234567890123456789 */
130             "GET / HTTP/1.1\r\n"
131             "Transfer-Encoding: chunked\r\n"
132             "\r\n"
133             "3\r\n"
134             "123\r\n"
135             "0\r\n\r\n"
136             "GET / HTTP/1.0\r\n";
137
138         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 58), 0);
139         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 59), 59);
140     }
141
142     {
143         /* one header, two chunks */
144         const char *http_buf =
145             /*12345678901234567890123456789 */
146             "GET / HTTP/1.1\r\n"
147             "Transfer-Encoding: chunked\r\n"
148             "\r\n"
149             "3\r\n"
150             "123\r\n"
151             "2\r\n"
152             "12\n"
153             "0\r\n\r\n"
154             "GET / HTTP/1.0\r\n";
155
156         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 64), 0);
157         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 65), 65);
158     }
159 }
160
161 static void tst_http_response(void)
162 {
163     {
164         /* unlimited content, no headers */
165         const char *http_buf =
166             /*123456789012345678 */
167             "HTTP/1.1 200 OK\r\n"
168             "\r\n"
169             "HTTP/1.1 200 OK\r\n";
170
171         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 1), 0);
172         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 2), 0);
173         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 24), 0);
174     }
175     {
176         /* no content, no headers */
177         const char *http_buf =
178             /*123456789012345678 */
179             "HTTP/1.1 204 OK\r\n"
180             "\r\n"
181             "HTTP/1.1 200 OK\r\n";
182
183         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 1), 0);
184         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 2), 0);
185         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 18), 0);
186         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 19), 19);
187         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 24), 19);
188     }
189     {
190         /* response, content  */
191         const char *http_buf =
192             /*123456789012345678 */
193             "HTTP/1.1 200 OK\r\n"
194             "Content-Length: 2\r\n"
195             "\r\n"
196             "12"
197             "HTTP/1.1 200 OK\r\n";
198
199         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 1), 0);
200         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 2), 0);
201         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 39), 0);
202         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 40), 40);
203         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 41), 40);
204     }
205 }
206
207 /** \brief COMSTACK synopsis from manual, doc/comstack.xml */
208 static int comstack_example(const char *server_address_str)
209 {
210     COMSTACK stack;
211     char *buf = 0;
212     int size = 0, length_incoming;
213     void *server_address_ip;
214     int status;
215
216     char *protocol_package = "GET / HTTP/1.0\r\n\r\n";
217     int protocol_package_length = strlen(protocol_package);
218
219     stack = cs_create(tcpip_type, 1, PROTO_HTTP);
220     if (!stack) {
221         perror("cs_create");  /* use perror() here since we have no stack yet */
222         return -1;
223     }
224
225     server_address_ip = cs_straddr(stack, server_address_str);
226     if (!server_address_ip)
227     {
228         fprintf(stderr, "cs_straddr: address could not be resolved\n");
229         return -1;
230     }
231
232     status = cs_connect(stack, server_address_ip);
233     if (status != 0) {
234         fprintf(stderr, "cs_connect: %s\n", cs_strerror(stack));
235         return -1;
236     }
237
238     status = cs_put(stack, protocol_package, protocol_package_length);
239     if (status) {
240         fprintf(stderr, "cs_put: %s\n", cs_strerror(stack));
241         return -1;
242     }
243
244     /* Now get a response */
245
246     length_incoming = cs_get(stack, &buf, &size);
247     if (!length_incoming) {
248         fprintf(stderr, "Connection closed\n");
249         return -1;
250     } else if (length_incoming < 0) {
251         fprintf(stderr, "cs_get: %s\n", cs_strerror(stack));
252         return -1;
253     }
254
255     /* Print result */
256     fwrite(buf, length_incoming, 1, stdout);
257
258     /* clean up */
259     cs_close(stack);
260     if (buf)
261         free(buf);
262     return 0;
263 }
264
265
266 int main (int argc, char **argv)
267 {
268     YAZ_CHECK_INIT(argc, argv);
269     YAZ_CHECK_LOG();
270     if (argc == 2)
271        comstack_example(argv[1]);
272     tst_http_request();
273     tst_http_response();
274     YAZ_CHECK_TERM;
275 }
276
277 /*
278  * Local variables:
279  * c-basic-offset: 4
280  * c-file-style: "Stroustrup"
281  * indent-tabs-mode: nil
282  * End:
283  * vim: shiftwidth=4 tabstop=8 expandtab
284  */
285