3 #define HTTPGW_MAX_CLIENT 128
15 char* headers[HTTP_MAX_HEADER];
16 } http_requests[HTTP_MAX_CLIENT];
19 int http_gw_reqs_open = 0;
22 http_gw_t* HttpGwFindRequest (SOCKET sock) {
23 for(int i=0; i<http_gw_reqs_open; i++)
24 if (http_requests[i].sink==sock)
25 return http_requests[i];
30 void HttpGwCloseConnection (SOCKET sock) {
31 http_gw_t* req = HttpGwFindRequest(sock);
33 for(int i=0; i<HTTPGW_MAX_HEADER; i++)
34 if (req->headers[i]) {
35 free(req->headers[i]);
36 req->headers[i] = NULL;
38 *req = http_requests[http_gw_reqs_open--];
44 void HttpGwMayWriteCallback (SOCKET sink) {
45 http_gw_t* req = HttpGwFindRequest(sink);
46 uint64_t complete = swift::SeqComplete(http_requests[reqi].transfer);
47 if (complete>req->offset) { // send data
49 uint64_t tosend = std::min(1LL<<12,complete-req->offset);
50 size_t rd = read(req->transfer,buf,tosend); // hope it is cached
52 HttpGwCloseConnection(sink);
55 size_t wn = send(sink, buf, rd, 0);
57 HttpGwCloseConnection(sink);
63 if (swift::IsComplete(http_requests[reqi].transfer)) // done; wait for new request
64 swift::Listen3rdPartySocket
65 (http_conns[httpc].sink,NewRequestCallback,NULL,ErrorCallback);
67 swift::Listen3rdPartySocket(request.sink,NULL,NULL,ErrorCallback);
72 void SwiftProgressCallback (int transfer, bin64_t bin) {
73 for (int httpc=0; httpc<conn_count; httpc++)
74 if (http_conns[httpc].transfer==transfer) {
75 if (bin.offset()<<10==http_conns[httpc].offset)
76 swift::Listen3rdPartySocket
77 (http_conns[httpc].sink,NULL,MayWriteCallback,ErrorCallback);
82 void HttpGwNewRequestCallback (SOCKET http_conn){
83 // read headers - the thrilling part
84 // we surely do not support pipelining => one request at a time
85 #define HTTPGW_MAX_REQ_SIZE 1024
86 char buf[HTTPGW_MAX_REQ_SIZE+1];
87 int rd = recv(http_conn,buf,HTTPGW_MAX_REQ_SIZE,0);
88 if (rd<=0) { // if conn is closed by the peer, rd==0
89 HttpGwCloseRequest(http_conn);
94 char* reqline = strtok(buf,"\r\n");
95 char method[16], url[512], version[16], crlf[5];
96 if (4!=sscanf(reqline,"%16s %512s %16s%4[\n\r]",method,url,version,crlf)) {
97 HttpGwCloseRequest(http_conn);
100 // HTTP header fields
102 while (headerline=strtok(NULL,"\n\r")) {
103 char header[128], value[256];
104 if (3!=sscanf(headerline,"%120[^: \r\n]: %250[^\r\n]%4[\r\n]",header,value,crlf)) {
105 HttpGwCloseRequest(http_conn);
108 for(int i=0; i<HTTPGW_HEADER_COUNT; i++)
109 if (0==strcasecmp(HTTPGW_HEADERS[i],header) && !http_requests[reqi])
110 http_requests[reqi] = strdup(value);
112 // initiate transmission
114 // find/create transfer
115 SwiftProgressCallback;
116 // write response header
117 sprintf("200 OK\r\n");
118 sprintf("Header: value\r\n");
119 http_clients[i].offset = 0;
120 http_clients[i].tosend = 10000;
121 http_clients[i].transfer = file;
122 http_clients[i].sink = conn;
126 // be liberal in what you do, be conservative in what you accept
127 void HttpGwNewConnectionCallback (SOCKET serv) {
128 Address client_address;
130 (serv, & (client_address.addr), sizeof(struct sockaddr_in));
131 if (conn==INVALID_SOCKET) {
132 print_error("client conn fails");
135 make_socket_nonblocking(conn);
136 // submit 3rd party socket to the swift loop
137 socket_callbacks_t install
138 (conn,HttpGwNewRequestCallback,HttpGwMayWriteCallback,HttpGwErrorCallback);
139 swift::Listen3rdPartySocket(install);
143 void HttpGwError (SOCKET serv) {
144 print_error("error on http socket");
148 SOCKET InstallHTTPGateway (Address bind_to) {
150 #define gw_ensure(x) { if (!(x)) { \
151 print_error("http binding fails"); close_socket(fd); \
152 return INVALID_SOCKET; } }
153 gw_ensure ( (fd=socket(AF_INET, SOCK_STREAM, 0)) != INVALID_SOCKET );
154 gw_ensure ( 0==bind(fd, (sockaddr*)&(bind_to.addr), sizeof(struct sockaddr_in)) );
155 gw_ensure (make_socket_nonblocking(fd));
156 gw_ensure ( 0==listen(fd,8) );
157 socket_callbacks_t install(sock,HttpGwNewConnectionCallback,NULL,HttpGwError);
158 gw_ensure (swift::Listen3rdPartySocket(install));