Merge pull request #2309 from mitza-oci/warnings
[ACE_TAO.git] / ACE / apps / JAWS / clients / WebSTONE / src / get.c
blobd800e5678b76951dfe9ba82c99faf3f10c42b21e
1 /**************************************************************************
3 * Copyright (C) 1995 Silicon Graphics, Inc.
5 * These coded instructions, statements, and computer programs were
6 * developed by SGI for public use. If any changes are made to this code
7 * please try to get the changes back to the author. Feel free to make
8 * modifications and changes to the code and release it.
10 **************************************************************************/
12 /* THIS IS WHERE WE GO OUT AND FETCH A URL */
14 #include <stdio.h>
15 #include <errno.h>
17 #ifndef WIN32
18 #include <sys/types.h>
19 #include <sys/errno.h>
20 #include <sys/socket.h>
21 #include <sys/param.h>
22 #include <netinet/in.h>
23 #include <netdb.h>
24 #endif /* WIN32 */
26 #include <string.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <ctype.h>
32 #ifdef WIN32
33 #include <io.h>
34 #include <windows.h>
35 #include <winsock.h>
36 #endif /* WIN32 */
38 #include "sysdep.h"
39 #include "bench.h"
41 #define ACCEPT_COMMAND "Accept: */* HTTP/1.0\r\n\r\n"
42 #define ACCEPT_COMMAND_LEN ((int)strlen(ACCEPT_COMMAND))
43 #define MAXCOMMANDLEN 256
44 #define HEADERBUFSIZ (8*1024)
46 #define UPPER(c) (((c) >= 'a' && (c) <= 'z') ? (c) + 'A' - 'a' : (c))
48 /* compare two strings with max length, ignoring case */
49 int mystrincmp(const char *str1, const char *str2, int len) {
50 register int diff;
52 while (*str1 && *str2 && len--) {
53 if (diff = UPPER(*str1) - UPPER(*str2))
54 return diff < 0 ? -1 : 1;
55 str1++;
56 str2++;
58 return 0;
61 int
62 get(char *loc, NETPORT port, char *url, rqst_timer_t *timer)
64 SOCKET sock = BADSOCKET_VALUE;
65 int writelen;
66 int bytesread;
67 int totalbytesread;
68 int headerlen;
69 int bodylength;
70 int contentlength = 0;
71 int outputfile = -1;
72 int status;
73 char getcommand[MAXCOMMANDLEN];
74 char headerbuffer[HEADERBUFSIZ+1];
75 char *offset;
76 char outputfilename[MAXPATHLEN];
77 char version[100];
78 int count;
80 /*#define ABORTIVE_CLOSE 1*/
81 #ifdef ABORTIVE_CLOSE
82 #error don't enable this option
83 struct linger {
84 int l_onoff;
85 int l_linger;
86 } linger_opt;
87 #endif /* ABORTIVE_CLOSE */
89 /* can you really get an error from gettimeofday?? */
90 if(GETTIMEOFDAY(&timer->entertime, &timer->entertimezone) != 0)
92 returnerr("Error retrieving entertime\n");
93 goto error;
95 timer->valid = 1;
97 if(GETTIMEOFDAY(&timer->beforeconnect, &timer->beforeconnectzone) != 0)
99 returnerr("Error retrieving beforeconnect\n");
100 goto error;
103 sock = connectsock(loc, port, "tcp");
104 if (BADSOCKET(sock))
106 D_PRINTF( "Call to connectsock returned %d (%s)\n", sock, neterrstr() );
107 returnerr("Couldn't connect to WWW server: %s\n", neterrstr());
108 goto error;
111 #ifdef ABORTIVE_CLOSE
112 #error don't enable this option
113 /* set up for abortive close */
114 linger_opt.l_onoff = 1;
115 linger_opt.l_linger = 0;
116 if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *) &linger_opt, sizeof(linger_opt)) < 0) {
117 fprintf(stderr, "Can't set sockopt SO_LINGER");
118 returnerr("Couldn't set SO_LINGER = 0\n");
119 goto error;
121 #endif /* ABORTIVE_CLOSE */
123 if(GETTIMEOFDAY(&timer->afterconnect, &timer->afterconnectzone) != 0)
125 NETCLOSE(sock);
126 GETTIMEOFDAY(&timer->exittime, &timer->exittimezone);
127 returnerr("Error retrieving afterconnect\n");
128 goto error;
132 * SEND THE GET AND THE ACCEPT.
134 sprintf(getcommand, "GET %s HTTP/1.0\r\n%s", url,
135 ACCEPT_COMMAND);
136 D_PRINTF( "Writing to server: %s\n", getcommand );
137 writelen = strlen(getcommand);
138 status = NETWRITE(sock, getcommand, writelen);
139 if(status != writelen)
141 returnerr("Error sending command line to server: %s\n",
142 neterrstr());
143 goto error;
146 * WE HAVE NOW SENT THE REQUEST SUCCESSFULLY.
147 * WAIT FOR THE REPLY AND FIND THE HEADER
150 if(GETTIMEOFDAY(&timer->beforeheader, &timer->beforeheaderzone) != 0)
152 returnerr("Error retrieving beforeheader\n");
153 goto error;
156 /* read the header and part of the file */
157 totalbytesread = 0;
158 headerlen = 0;
159 while (totalbytesread < HEADERBUFSIZ)
161 bytesread = NETREAD(sock, headerbuffer+totalbytesread, HEADERBUFSIZ-totalbytesread);
162 if (BADSOCKET(bytesread))
164 D_PRINTF( "Did not receive full header\n" );
165 D_PRINTF( "NETREAD returned %d\n", bytesread );
166 returnerr("Did not receive full header: %s\n",
167 neterrstr());
168 goto error;
170 totalbytesread += bytesread;
172 /* search for end of header */
173 headerbuffer[totalbytesread] = 0;
174 if (offset = strstr(headerbuffer, "\n\n")) {
175 headerlen = offset - headerbuffer + 2;
176 break;
177 } else if (offset = strstr(headerbuffer, "\n\r\n")) {
178 headerlen = offset - headerbuffer + 3;
179 break;
183 if (headerlen == 0) {
184 returnerr("Can't find the end of the header in \"%s\"\n", headerbuffer);
185 goto error;
188 /* get and check status code from the first line of the header */
189 count = sscanf(headerbuffer, "HTTP/%s %d", version, &status);
190 if (count != 2) {
191 returnerr("Bad status line in get(): %s\n", headerbuffer);
192 goto error;
194 if (status < 200 || status > 300) {
195 returnerr("Bad status (%d) in get() for url %s\n", status, url);
196 goto error;
199 /* get the content length line from the header */
200 offset = headerbuffer;
201 while (offset < headerbuffer+headerlen && *offset) {
202 if (*offset++ != '\n')
203 continue;
205 if (mystrincmp(offset, CONTENT_LENGTH_STRING, strlen( CONTENT_LENGTH_STRING)) == 0) {
206 sscanf(offset+strlen(CONTENT_LENGTH_STRING), "%d", &contentlength);
207 D_PRINTF( "Content-Length: %d\n", contentlength );
211 if(GETTIMEOFDAY(&timer->afterheader, &timer->afterheaderzone) != 0)
213 returnerr("Error retrieving afterheader\n");
214 goto error;
217 if(savefile)
219 sprintf(outputfilename,"/tmp/webstone.data.%d", (int)getpid());
220 if((outputfile = open(outputfilename,(O_WRONLY|O_CREAT),0777)) < 0)
222 D_PRINTF( "outputfile %d %d\n", outputfile, errno );
223 returnerr("Error saving file: %s\n", strerror(errno));
224 goto error;
226 lseek(outputfile,1,SEEK_END); /* this is odd... JEF */
228 /* if we have part of the file already, save that part */
229 if(totalbytesread > headerlen)
231 write(outputfile, headerbuffer+headerlen, totalbytesread-headerlen);
235 /* read the body of the file */
238 bytesread = NETREAD(sock, headerbuffer, HEADERBUFSIZ);
239 D_PRINTF( "Read %d bytes from socket %d\n", bytesread, sock );
241 if (BADSOCKET(bytesread))
243 D_PRINTF("Read returns %d, error: %s\n", bytesread,
244 neterrstr() );
245 returnerr("Error during read of page body. Read "
246 "returns %d on socket %d, error: %s\n",
247 bytesread, sock, neterrstr());
248 goto error;
251 totalbytesread += bytesread;
253 if (outputfile != -1 && bytesread)
255 write(outputfile, headerbuffer, bytesread);
257 } while (bytesread);
259 /* done reading body */
260 if ( contentlength && (totalbytesread - headerlen) != contentlength)
262 D_PRINTF( "Warning: file length (%d) doesn't match Content-length (%d)\n",
263 totalbytesread - headerlen, contentlength);
266 bodylength = totalbytesread - headerlen;
268 if(GETTIMEOFDAY(&timer->afterbody, &timer->afterbodyzone) != 0)
270 returnerr("Error retrieving afterbody\n");
271 goto error;
274 NETCLOSE(sock);
275 if (outputfile != -1)
277 close(outputfile);
280 D_PRINTF("Read %d bytes, %d of that being body\n",
281 totalbytesread, bodylength );
283 if(GETTIMEOFDAY(&timer->exittime, &timer->exittimezone) != 0)
285 D_PRINTF( "Error retrieving exit time: %s\n", strerror(errno) );
286 returnerr("Error retrieving exit time\n");
287 goto error;
289 timer->valid = 2;
290 timer->totalbytes = totalbytesread;
291 timer->bodybytes = bodylength;
293 D_PRINTF("get returning totalbytes %d body %d valid %d\n",
294 timer->totalbytes, timer->bodybytes, timer->valid );
296 D_PRINTF("get returning start %d, end %d\n",
297 timer->entertime.tv_sec, timer->exittime.tv_sec );
299 D_PRINTF("get returning connect %d, request %d, header %d, body %d\n",
300 timer->afterconnect.tv_sec, timer->beforeheader.tv_sec,
301 timer->afterheader.tv_sec, timer->afterbody.tv_sec );
303 return 0;
305 error:
306 if (!BADSOCKET(sock))
307 NETCLOSE(sock);
308 if (outputfile != -1)
309 close(outputfile);
310 GETTIMEOFDAY(&timer->exittime, &timer->exittimezone); /* needed? */
311 return -1;