Overview
Artifact ID: | fd4ce405db3bbd77ab59f1da2870c63a79ea8337 |
---|---|
Ticket: | 11622724e5b46818396db583ac839391f70c8d64 |
Date: | 2010-08-26 09:54:59 |
User: | anonymous |
Artifact Attached: | f938e4d31690b5b0aad8eeca5f4733c795445d6b |
Filename: | winhttp.c |
Description: | winhttp.c |
Content Appended
1 /* 2 ** Copyright (c) 2008 D. Richard Hipp 3 ** 4 ** This program is free software; you can redistribute it and/or 5 ** modify it under the terms of the Simplified BSD License (also 6 ** known as the "2-Clause License" or "FreeBSD License".) 7 8 ** This program is distributed in the hope that it will be useful, 9 ** but without any warranty; without even the implied warranty of 10 ** merchantability or fitness for a particular purpose. 11 ** 12 ** Author contact information: 13 ** drh@hwaci.com 14 ** http://www.hwaci.com/drh/ 15 ** 16 ******************************************************************************* 17 ** 18 ** This file implements a very simple (and low-performance) HTTP server 19 ** for windows. 20 */ 21 #ifdef __MINGW32__ /* This code is for win32 only */ 22 #include "config.h" 23 #include "winhttp.h" 24 #include <windows.h> 25 26 #include "my_popen.h" 27 28 29 /* 30 ** The HttpRequest structure holds information about each incoming 31 ** HTTP request. 32 */ 33 typedef struct HttpRequest HttpRequest; 34 struct HttpRequest { 35 int id; /* ID counter */ 36 SOCKET s; /* Socket on which to receive data */ 37 SOCKADDR_IN addr; /* Address from which data is coming */ 38 const char *zNotFound; /* --notfound option, or an empty string */ 39 }; 40 41 /* 42 ** Prefix for a temporary file. 43 */ 44 static char *zTempPrefix; 45 46 /* 47 ** Look at the HTTP header contained in zHdr. Find the content 48 ** length and return it. Return 0 if there is no Content-Length: 49 ** header line. 50 */ 51 static int find_content_length(const char *zHdr){ 52 while( *zHdr ){ 53 if( zHdr[0]=='\n' ){ 54 if( zHdr[1]=='\r' ) return 0; 55 if( strncasecmp(&zHdr[1], "content-length:", 15)==0 ){ 56 return atoi(&zHdr[17]); 57 } 58 } 59 zHdr++; 60 } 61 return 0; 62 } 63 64 /* 65 ** Process a single incoming HTTP request. 66 */ 67 void win32_process_one_http_request(void *pAppData){ 68 HttpRequest *p = (HttpRequest*)pAppData; 69 FILE *in = 0, *out = 0; 70 int amt, got; 71 int wanted = 0; 72 char *z; 73 char zRequestFName[100]; 74 char zReplyFName[100]; 75 char zCmd[2000]; /* Command-line to process the request */ 76 char zHdr[2000]; /* The HTTP request header */ 77 78 sprintf(zRequestFName, "%s_in%d.txt", zTempPrefix, p->id); 79 sprintf(zReplyFName, "%s_out%d.txt", zTempPrefix, p->id); 80 #if defined(FOSSIL_CHILD_DEBUG) 81 //sprintf(zCmd, "sh -c '\"%s\" http \"%s\" --httptrace | tee abc'", g.argv[0], g.zRepositoryName); 82 sprintf(zCmd, "\"%s\" http \"%s\" --httptrace ", g.argv[0], g.zRepositoryName); 83 #else 84 sprintf(zCmd, "\"%s\" http \"%s\" ", g.argv[0], g.zRepositoryName); 85 #endif 86 87 int childPid; 88 popen2(zCmd, &in, &out, &childPid); 89 90 amt = 0; 91 while( amt<sizeof(zHdr) ){ 92 got = recv(p->s, &zHdr[amt], sizeof(zHdr)-1-amt, 0); 93 if( got==SOCKET_ERROR ) goto end_request; 94 if( got==0 ){ 95 wanted = 0; 96 break; 97 } 98 amt += got; 99 zHdr[amt] = 0; 100 z = strstr(zHdr, "\r\n\r\n"); 101 if( z ){ 102 wanted = find_content_length(zHdr) + (&z[4]-zHdr) - amt; 103 break; 104 } 105 } 106 if( amt>=sizeof(zHdr) ) goto end_request; 107 //out = fopen(zRequestFName, "wb"); 108 if( out==0 ) goto end_request; 109 fwrite(zHdr, 1, amt, out); 110 while( wanted>0 ){ 111 got = recv(p->s, zHdr, sizeof(zHdr), 0); 112 if( got==SOCKET_ERROR ) goto end_request; 113 if( got ){ 114 fwrite(zHdr, 1, got, out); 115 }else{ 116 break; 117 } 118 wanted -= got; 119 } 120 fclose(out); 121 out = 0; 122 //sprintf(zCmd, "\"%s\" http \"%s\" %s %s %s%s", 123 // g.argv[0], g.zRepositoryName, zRequestFName, zReplyFName, 124 // inet_ntoa(p->addr.sin_addr), p->zNotFound 125 //); 126 //portable_system(zCmd); 127 //in = fopen(zReplyFName, "rb"); 128 if( in ){ 129 while( (got = fread(zHdr, 1, sizeof(zHdr), in))>0 ){ 130 send(p->s, zHdr, got, 0); 131 } 132 } 133 134 end_request: 135 if( out ) fclose(out); 136 if( in ) fclose(in); 137 closesocket(p->s); 138 unlink(zRequestFName); 139 unlink(zReplyFName); 140 free(p); 141 } 142 143 /* 144 ** Start a listening socket and process incoming HTTP requests on 145 ** that socket. 146 */ 147 void win32_http_server( 148 int mnPort, int mxPort, /* Range of allowed TCP port numbers */ 149 const char *zBrowser, /* Command to launch browser. (Or NULL) */ 150 const char *zStopper, /* Stop server when this file is exists (Or NULL) */ 151 const char *zNotFound /* The --notfound option, or NULL */ 152 ){ 153 WSADATA wd; 154 SOCKET s = INVALID_SOCKET; 155 SOCKADDR_IN addr; 156 int idCnt = 0; 157 int iPort = mnPort; 158 char *zNotFoundOption; 159 160 if( zStopper ) unlink(zStopper); 161 if( zNotFound ){ 162 zNotFoundOption = mprintf(" --notfound %s", zNotFound); 163 }else{ 164 zNotFoundOption = ""; 165 } 166 if( WSAStartup(MAKEWORD(1,1), &wd) ){ 167 fossil_fatal("unable to initialize winsock"); 168 } 169 while( iPort<=mxPort ){ 170 s = socket(AF_INET, SOCK_STREAM, 0); 171 if( s==INVALID_SOCKET ){ 172 fossil_fatal("unable to create a socket"); 173 } 174 addr.sin_family = AF_INET; 175 addr.sin_port = htons(iPort); 176 addr.sin_addr.s_addr = htonl(INADDR_ANY); 177 if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){ 178 closesocket(s); 179 iPort++; 180 continue; 181 } 182 if( listen(s, SOMAXCONN)==SOCKET_ERROR ){ 183 closesocket(s); 184 iPort++; 185 continue; 186 } 187 break; 188 } 189 if( iPort>mxPort ){ 190 if( mnPort==mxPort ){ 191 fossil_fatal("unable to open listening socket on ports %d", mnPort); 192 }else{ 193 fossil_fatal("unable to open listening socket on any" 194 " port in the range %d..%d", mnPort, mxPort); 195 } 196 } 197 zTempPrefix = mprintf("fossil_server_P%d_", iPort); 198 printf("Listening for HTTP requests on TCP port %d\n", iPort); 199 if( zBrowser ){ 200 zBrowser = mprintf(zBrowser, iPort); 201 printf("Launch webbrowser: %s\n", zBrowser); 202 portable_system(zBrowser); 203 } 204 printf("Type Ctrl-C to stop the HTTP server\n"); 205 for(;;){ 206 SOCKET client; 207 SOCKADDR_IN client_addr; 208 HttpRequest *p; 209 int len = sizeof(client_addr); 210 211 client = accept(s, (struct sockaddr*)&client_addr, &len); 212 if( zStopper && file_size(zStopper)>=0 ){ 213 break; 214 } 215 if( client==INVALID_SOCKET ){ 216 closesocket(s); 217 fossil_fatal("error from accept()"); 218 } 219 p = malloc( sizeof(*p) ); 220 if( p==0 ){ 221 fossil_fatal("out of memory"); 222 } 223 p->id = ++idCnt; 224 p->s = client; 225 p->addr = client_addr; 226 p->zNotFound = zNotFoundOption; 227 _beginthread(win32_process_one_http_request, 0, (void*)p); 228 } 229 closesocket(s); 230 WSACleanup(); 231 } 232 233 #endif /* __MINGW32__ -- This code is for win32 only */