From 2dc905af77ce65dc3135c82451411a97c145aa3b Mon Sep 17 00:00:00 2001 From: Victor Grishchenko Date: Tue, 9 Mar 2010 09:00:00 +0100 Subject: [PATCH] in progress --- README | 15 +++++++ httpgw.cpp | 119 ++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 111 insertions(+), 23 deletions(-) diff --git a/README b/README index 0329cc1..8939346 100644 --- a/README +++ b/README @@ -1,9 +1,24 @@ swift: the multiparty transport protocol + (aka BitTorrent at the transport layer) + Differently from TCP, the protocol does not use the ordered data stream + abstraction. Effectively, it splits a file into 1KB packets and sends + them around. The secret sauce is Merkle hash trees and binmaps. see doc/index.html for marketing stuff, ideas and rants doc/swift.txt for protocol draft spec *.cpp for the actual code swift.cpp is the main exec file; may run as e.g. + ./swift -t node300.das2.ewi.tudelft.nl:20000 -h \ d1502706c46779d361a1d562a10da0a45c4c40e5 -f \ trailer.ogg + + ...to retrieve video and save it to a file, or... + + ./swift -t mfold.libswift.org:20000 -h \ + d1502706c46779d361a1d562a10da0a45c4c40e5 -r . \ + -h 8080 + + ...and then point your browser at + + http://localhost:8080/d1502706c46779d361a1d562a10da0a45c4c40e5 diff --git a/httpgw.cpp b/httpgw.cpp index bb03be3..af99412 100644 --- a/httpgw.cpp +++ b/httpgw.cpp @@ -1,52 +1,121 @@ #include "swift.h" -#define MAX_HTTP_CLIENT 128 +#define HTTPGW_MAX_CLIENT 128 +enum { + HTTPGW_RANGE, + HTTPGW_MAX_HEADER +}; + struct http_gw_t { uint64_t offset; uint64_t tosend; int transfer; SOCKET sink; -} http_clients[MAX_HTTP_CLIENT]; + char* headers[HTTP_MAX_HEADER]; +} http_requests[HTTP_MAX_CLIENT]; + + +int http_gw_reqs_open = 0; -void HttpGwErrorCallback (SOCKET sink) { +http_gw_t* HttpGwFindRequest (SOCKET sock) { + for(int i=0; iheaders[i]) { + free(req->headers[i]); + req->headers[i] = NULL; + } + *req = http_requests[http_gw_reqs_open--]; + } + close_socket(sock); +} + + void HttpGwMayWriteCallback (SOCKET sink) { - // if have data => write - // otherwise, change mask - if (not_enough_data) - swift::Listen3rdPartySocket(http_conns[httpc].sink,NULL,NULL,ErrorCallback); - if (all_done) - swift::Listen3rdPartySocket(http_conns[httpc].sink,NewRequestCallback,NULL,ErrorCallback); + http_gw_t* req = HttpGwFindRequest(sink); + uint64_t complete = swift::SeqComplete(http_requests[reqi].transfer); + if (complete>req->offset) { // send data + char buf[1LL<<12]; + uint64_t tosend = std::min(1LL<<12,complete-req->offset); + size_t rd = read(req->transfer,buf,tosend); // hope it is cached + if (rd<0) { + HttpGwCloseConnection(sink); + return; + } + size_t wn = send(sink, buf, rd, 0); + if (wn<0) { + HttpGwCloseConnection(sink); + return; + } + req->offset += wn; + req->tosend -= wn; + } else { + if (swift::IsComplete(http_requests[reqi].transfer)) // done; wait for new request + swift::Listen3rdPartySocket + (http_conns[httpc].sink,NewRequestCallback,NULL,ErrorCallback); + else // wait for data + swift::Listen3rdPartySocket(request.sink,NULL,NULL,ErrorCallback); + } } void SwiftProgressCallback (int transfer, bin64_t bin) { for (int httpc=0; httpc one requests at a time - fgets(); + // we surely do not support pipelining => one request at a time + #define HTTPGW_MAX_REQ_SIZE 1024 + char buf[HTTPGW_MAX_REQ_SIZE+1]; + int rd = recv(http_conn,buf,HTTPGW_MAX_REQ_SIZE,0); + if (rd<=0) { // if conn is closed by the peer, rd==0 + HttpGwCloseRequest(http_conn); + return; + } + buf[rd] = 0; // HTTP request line - sscanf(); + char* reqline = strtok(buf,"\r\n"); + char method[16], url[512], version[16], crlf[5]; + if (4!=sscanf(reqline,"%16s %512s %16s%4[\n\r]",method,url,version,crlf)) { + HttpGwCloseRequest(http_conn); + return; + } // HTTP header fields - sscanf(); - // incomplete header => screw it - fprintf("400 Incomplete header\r\n"); - close(); + char* headerline; + while (headerline=strtok(NULL,"\n\r")) { + char header[128], value[256]; + if (3!=sscanf(headerline,"%120[^: \r\n]: %250[^\r\n]%4[\r\n]",header,value,crlf)) { + HttpGwCloseRequest(http_conn); + return; + } + for(int i=0; i