chd over http support (EXPERIMENTAL AND SLOW)

This commit is contained in:
Stefanos Kornilios Mitsis Poiitidis 2014-05-21 20:07:59 +03:00
parent ebeef1ddaf
commit c6f62c66bd
2 changed files with 233 additions and 15 deletions

View File

@ -302,22 +302,239 @@ static const codec_interface codec_interfaces[] =
},
};
#pragma comment (lib, "wsock32.lib")
#include <string>
#include <sstream>
int core_fread(FILE* f, void* buff, size_t len)
{
return fread(buff,1,len,f);
size_t HTTP_GET(string host, int port,string path, size_t offs, size_t len, void* pdata){
string request;
string response;
int resp_leng;
struct sockaddr_in serveraddr;
int sock;
std::stringstream request2;
if (len) {
request2 << "GET " << path << " HTTP/1.1"<<endl;
request2 << "User-Agent: reicastdc" << endl;
//request2 << "" << endl;
request2 << "Host: " << host << endl;
request2 << "Accept: */*" << endl;
request2 << "Range: bytes=" << offs << "-" << (offs + len-1) << endl;
request2 << endl;
}
else {
request2 << "HEAD " << path << " HTTP/1.1"<<endl;
request2 << "User-Agent: reicastdc" << endl;
//request2 << "" << endl;
request2 << "Host: " << host << endl;
request2 << endl;
}
request = request2.str();
//init winsock
static bool init = false;
if (!init) {
static WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0)
die("WSAStartup fail");
init = true;
}
//open socket
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
return -1;
//connect
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = *(int*)gethostbyname( host.c_str() )->h_addr_list[0];
serveraddr.sin_port = htons((unsigned short) port);
if (connect(sock, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) < 0)
return -1;
BOOL v = FALSE;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const char*)&v, sizeof(v));
//send request
if (send(sock, request.c_str(), request.length(), 0) != request.length())
return -1;
/*
//get response
response = "";
resp_leng= BUFFERSIZE;
*/
/*
parse headers ..
*/
size_t content_length = 0;
for (;;) {
stringstream ss;
for (;;) {
char t;
if (recv(sock, &t, 1, 0) <= 0)
goto _cleanup;
if (t != '\n'){
ss << t;
continue;
}
string ln = ss.str();
if (ln.size() == 1)
goto _data;
string CL = "Content-Length:";
if (ln.substr(0, CL.size()) == CL) {
sscanf(ln.substr(CL.size(), ln.npos).c_str(),"%d", &content_length);
}
break;
}
}
_data:
size_t rv = content_length;
if (len == 0) {
}
else {
verify(len == content_length);
u8* ptr = (u8*)pdata;
do
{
int rcv = recv(sock, (char*)ptr, len, 0);
verify(rcv > 0 && len>= rcv);
len -= rcv;
ptr += rcv;
}
while (len >0);
}
_cleanup:
//disconnect
closesocket(sock);
/*
//cleanup
WSACleanup();
*/
return rv;
}
size_t core_fsize(FILE* f)
struct CORE_FILE {
FILE* f;
string path;
size_t seek_ptr;
string host;
int port;
};
core_file* core_fopen(const char* filename)
{
size_t p=ftell(f);
fseek(f,0,SEEK_END);
size_t rv=ftell(f);
fseek(f,p,SEEK_SET);
return rv;
string p = filename;
CORE_FILE* rv = new CORE_FILE();
rv->f = 0;
rv->path = p;
if (p.substr(0,7)=="http://") {
rv->host = p.substr(7,p.npos);
rv->host = rv->host.substr(0, rv->host.find_first_of("/"));
rv->path = p.substr(p.find("/", 7), p.npos);
rv->port = 80;
size_t pos = rv->host.find_first_of(":");
if (pos != rv->host.npos) {
string port = rv->host.substr(pos, rv->host.npos );
rv->host = rv->host.substr(0, rv->host.find_first_of(":"));
sscanf(port.c_str(),"%d",&rv->port);
}
} else {
rv->f = fopen(filename, "rb");
}
return (core_file*)rv;
}
#define core_fseek fseek
size_t core_fseek(core_file* fc, size_t offs, size_t origin) {
CORE_FILE* f = (CORE_FILE*)fc;
if (origin == SEEK_SET)
f->seek_ptr = offs;
else if (origin == SEEK_CUR)
f->seek_ptr += offs;
else
die("Invalid code path");
if (f->f)
fseek((FILE*)f, f->seek_ptr, SEEK_SET);
return 0;
}
int core_fread(core_file* fc, void* buff, size_t len)
{
CORE_FILE* f = (CORE_FILE*)fc;
if (f->f) {
fread(buff,1,len,f->f);
} else {
HTTP_GET(f->host, f->port, f->path, f->seek_ptr, len, buff);
}
f->seek_ptr += len;
return len;
}
int core_fclose(core_file* fc)
{
CORE_FILE* f = (CORE_FILE*)fc;
if (f->f) {
fclose((FILE*)f);
}
else {
}
delete f;
return 0;
}
size_t core_fsize(core_file* fc)
{
CORE_FILE* f = (CORE_FILE*)fc;
if (f->f) {
size_t p=ftell(f->f);
fseek(f->f,0,SEEK_END);
size_t rv=ftell(f->f);
fseek(f->f,p,SEEK_SET);
return rv;
}
else {
return HTTP_GET(f->host, f->port, f->path, 0, 0,0);
}
}
#define MIN min
#define MAX max
/***************************************************************************
@ -593,7 +810,7 @@ chd_error chd_open(const wchar *filename, int mode, chd_file *parent, chd_file *
}
/* open the file */
file=fopen(filename, "rb");
file=core_fopen(filename);
if (file == 0)
{
err = CHDERR_FILE_NOT_FOUND;
@ -610,7 +827,7 @@ chd_error chd_open(const wchar *filename, int mode, chd_file *parent, chd_file *
cleanup:
if ((err != CHDERR_NONE) && (file != NULL))
fclose(file);
core_fclose(file);
return err;
}
@ -653,7 +870,7 @@ void chd_close(chd_file *chd)
/* close the file */
if (chd->owns_file && chd->file != NULL)
fclose(chd->file);
core_fclose(chd->file);
if (PRINTF_MAX_HUNK) printf("Max hunk = %d/%d\n", chd->maxhunk, chd->header.totalhunks);
@ -807,7 +1024,7 @@ chd_error chd_get_metadata(chd_file *chd, UINT32 searchtag, UINT32 searchindex,
/* read the metadata */
outputlen = min(outputlen, metaentry.length);
fseek(chd->file, metaentry.offset + METADATA_HEADER_SIZE, SEEK_SET);
core_fseek(chd->file, metaentry.offset + METADATA_HEADER_SIZE, SEEK_SET);
count = core_fread(chd->file, output, outputlen);
if (count != outputlen)
return CHDERR_READ_ERROR;

View File

@ -15,6 +15,7 @@ typedef s8 INT8;
#define INLINE inline
#endif
#define core_file FILE
//#define core_file FILE
typedef void* core_file;
#define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0]))