5 #define HTTPGW_MAX_CLIENT 128
11 char * HTTPGW_HEADERS[HTTPGW_MAX_HEADER] = {
21 char* headers[HTTPGW_MAX_HEADER];
22 } http_requests[HTTPGW_MAX_CLIENT];
25 int http_gw_reqs_open = 0;
27 void HttpGwNewRequestCallback (SOCKET http_conn);
28 void HttpGwNewRequestCallback (SOCKET http_conn);
30 http_gw_t* HttpGwFindRequest (SOCKET sock) {
31 for(int i=0; i<http_gw_reqs_open; i++)
32 if (http_requests[i].sink==sock)
33 return http_requests+i;
38 void HttpGwCloseConnection (SOCKET sock) {
39 http_gw_t* req = HttpGwFindRequest(sock);
41 for(int i=0; i<HTTPGW_MAX_HEADER; i++)
42 if (req->headers[i]) {
43 free(req->headers[i]);
44 req->headers[i] = NULL;
46 *req = http_requests[http_gw_reqs_open--];
48 swift::close_socket(sock);
52 void HttpGwMayWriteCallback (SOCKET sink) {
53 http_gw_t* req = HttpGwFindRequest(sink);
54 uint64_t complete = swift::SeqComplete(req->transfer);
55 if (complete>req->offset) { // send data
57 uint64_t tosend = std::min((uint64_t)1<<12,complete-req->offset);
58 size_t rd = read(req->transfer,buf,tosend); // hope it is cached
60 HttpGwCloseConnection(sink);
63 size_t wn = send(sink, buf, rd, 0);
65 HttpGwCloseConnection(sink);
71 if (swift::IsComplete(req->transfer)) { // done; wait for new request
72 socket_callbacks_t wait_new_req(req->sink,HttpGwNewRequestCallback,NULL,HttpGwCloseConnection);
73 swift::Listen3rdPartySocket (wait_new_req);
74 } else { // wait for data
75 socket_callbacks_t wait_swift_data(req->sink,NULL,NULL,HttpGwCloseConnection);
76 swift::Listen3rdPartySocket(wait_swift_data);
82 void HttpGwSwiftProgressCallback (int transfer, bin64_t bin) {
83 for (int httpc=0; httpc<http_gw_reqs_open; httpc++)
84 if (http_requests[httpc].transfer==transfer)
85 if ( (bin.offset()<<10) == http_requests[httpc].offset ) {
86 socket_callbacks_t maywrite_callbacks
87 (http_requests[httpc].sink,NULL,HttpGwMayWriteCallback,HttpGwCloseConnection);
88 Listen3rdPartySocket (maywrite_callbacks);
93 void HttpGwFirstProgressCallback (int transfer, bin64_t bin) {
95 printf("Content-Length: value\r\n");
96 swift::RemoveProgressCallback(transfer,&HttpGwFirstProgressCallback);
97 swift::AddProgressCallback(transfer,&HttpGwSwiftProgressCallback);
98 HttpGwSwiftProgressCallback(transfer,bin);
102 void HttpGwNewRequestCallback (SOCKET http_conn){
103 http_gw_t* req = http_requests + http_gw_reqs_open++;
104 req->sink = http_conn;
105 // read headers - the thrilling part
106 // we surely do not support pipelining => one request at a time
107 #define HTTPGW_MAX_REQ_SIZE 1024
108 char buf[HTTPGW_MAX_REQ_SIZE+1];
109 int rd = recv(http_conn,buf,HTTPGW_MAX_REQ_SIZE,0);
110 if (rd<=0) { // if conn is closed by the peer, rd==0
111 HttpGwCloseConnection(http_conn);
116 char* reqline = strtok(buf,"\r\n");
117 char method[16], url[512], version[16], crlf[5];
118 if (4!=sscanf(reqline,"%16s %512s %16s%4[\n\r]",method,url,version,crlf)) {
119 HttpGwCloseConnection(http_conn);
122 // HTTP header fields
124 while (headerline=strtok(NULL,"\n\r")) {
125 char header[128], value[256];
126 if (3!=sscanf(headerline,"%120[^: \r\n]: %250[^\r\n]%4[\r\n]",header,value,crlf)) {
127 HttpGwCloseConnection(http_conn);
130 for(int i=0; i<HTTPGW_MAX_HEADER; i++)
131 if (0==strcasecmp(HTTPGW_HEADERS[i],header) && !req->headers[i])
132 req->headers[i] = strdup(value);
135 char * hashch=strtok(url,"/"), hash[41];
136 while (hashch && (1!=sscanf(hashch,"%40[0123456789abcdefABCDEF]",hash) || strlen(hash)!=40))
137 hashch = strtok(NULL,"/");
138 if (strlen(hash)!=40) {
139 HttpGwCloseConnection(http_conn);
142 // initiate transmission
143 int file = swift::Open(hash,hash);
144 // find/create transfer
145 swift::AddProgressCallback(file,&HttpGwFirstProgressCallback);
146 // write response header
149 req->transfer = file;
150 socket_callbacks_t install (http_conn,NULL,NULL,HttpGwCloseConnection);
151 swift::Listen3rdPartySocket(install);
155 // be liberal in what you do, be conservative in what you accept
156 void HttpGwNewConnectionCallback (SOCKET serv) {
157 Address client_address;
160 (serv, (sockaddr*) & (client_address.addr), &len);
161 if (conn==INVALID_SOCKET) {
162 print_error("client conn fails");
165 make_socket_nonblocking(conn);
166 // submit 3rd party socket to the swift loop
167 socket_callbacks_t install
168 (conn,HttpGwNewRequestCallback,NULL,HttpGwCloseConnection);
169 swift::Listen3rdPartySocket(install);
173 void HttpGwError (SOCKET s) {
174 print_error("everything fucked up");
178 SOCKET InstallHTTPGateway (Address bind_to) {
180 #define gw_ensure(x) { if (!(x)) { \
181 print_error("http binding fails"); close_socket(fd); \
182 return INVALID_SOCKET; } }
183 gw_ensure ( (fd=socket(AF_INET, SOCK_STREAM, 0)) != INVALID_SOCKET );
184 gw_ensure ( 0==bind(fd, (sockaddr*)&(bind_to.addr), sizeof(struct sockaddr_in)) );
185 gw_ensure (make_socket_nonblocking(fd));
186 gw_ensure ( 0==listen(fd,8) );
187 socket_callbacks_t install(fd,HttpGwNewConnectionCallback,NULL,HttpGwError);
188 gw_ensure (swift::Listen3rdPartySocket(install));