Skip to content

Instantly share code, notes, and snippets.

@c4pt0r
Created October 19, 2013 07:04
Show Gist options
  • Save c4pt0r/7052512 to your computer and use it in GitHub Desktop.
Save c4pt0r/7052512 to your computer and use it in GitHub Desktop.
Downloader Draft
// Copyright (c) 2013 The Wandoujia Authors. All rights reserved.
#ifndef PLATFORM_WDJ_CONNECTION_WRAPPER_WDJ_CONNECTION_DOWNLOADER_H_
#define PLATFORM_WDJ_CONNECTION_WRAPPER_WDJ_CONNECTION_DOWNLOADER_H_
#include <windows.h>
#include <map>
#include "net/win_http.h"
//
class EngineDownloader: async_wininet::WinHTTPListener {
public:
static EngineDownloader* GetInstance();
public:
class Listener {
public:
virtual void OnProgress(size_t cur_bytes, size_t total) = 0;
virtual void OnComplete(const std::string& buf) = 0;
virtual void OnError(DWORD code) = 0;
// if save to file, user need provide fp
virtual FILE* fp() { return NULL; }
};
void Init();
void Uninit();
DWORD Download(const std::string& url, Listener* listener);
void Stop(DWORD id);
void StopAll();
public:
virtual void OnRedirect(DWORD request_id);
virtual void OnBegin(DWORD request_id);
virtual void OnProgress(DWORD request_id);
virtual void OnComplete(DWORD request_id);
virtual void OnError(DWORD request_id);
private:
EngineDownloader() {}
virtual ~EngineDownloader() {}
private:
inline Listener* GetListener(DWORD request_id);
inline const async_wininet::WinHTTP::Request* GetRequest(DWORD request_id);
inline void RemoveListener(DWORD request_id);
private:
async_wininet::WinHTTP* downloader_;
typedef std::map<DWORD, Listener*> ListenerMap;
typedef std::map<DWORD, std::string> BufMap;
ListenerMap listeners_;
BufMap buf_;
};
#endif // PLATFORM_WDJ_CONNECTION_WRAPPER_WDJ_CONNECTION_DOWNLOADER_H_
//////////////////////////////////////////////////////////////////////
// Copyright (c) 2013 The Wandoujia Authors. All rights reserved.
#include "wdj_connection_wrapper/wdj_connection_downloader.h"
namespace {
static EngineDownloader* instance = NULL;
}
inline EngineDownloader::Listener* EngineDownloader::GetListener(DWORD request_id) {
if (listeners_.find(request_id) != listeners_.end())
return listeners_[request_id];
return NULL;
}
inline const async_wininet::WinHTTP::Request* EngineDownloader::GetRequest(DWORD request_id) {
return downloader_->FindRequest(request_id);
}
inline void EngineDownloader::RemoveListener(DWORD request_id) {
downloader_->RemoveRequest(request_id);
listeners_.erase(request_id);
buf_.erase(request_id);
}
void EngineDownloader::OnRedirect(DWORD request_id) {
}
void EngineDownloader::OnBegin(DWORD request_id) {
}
void EngineDownloader::OnProgress(DWORD request_id) {
using namespace async_wininet;
Listener* listener = GetListener(request_id);
if (listener) {
const WinHTTP::Request* req = GetRequest(request_id);
// if fp is not NULL, means need write to file
if (FILE* fp = listener->fp()) {
fwrite(req->internet_buffer.lpvBuffer,
req->internet_buffer.dwBufferLength, 1, fp);
} else {
// We need buffer! for download text
std::string t((char*)req->internet_buffer.lpvBuffer,
req->internet_buffer.dwBufferLength);
buf_[request_id] += t;
}
listener->OnProgress(req->internet_buffer.dwBufferTotal,
req->content_length);
}
}
void EngineDownloader::OnComplete(DWORD request_id) {
using namespace async_wininet;
Listener* listener = GetListener(request_id);
if (listener) {
const WinHTTP::Request* req = GetRequest(request_id);
// if fp is not NULL, means need write to file
if (FILE* fp = listener->fp()) {
fclose(fp);
listener->OnComplete("");
} else {
// We need buffer! for download text
listener->OnComplete(buf_[request_id]);
}
RemoveListener(request_id);
}
}
void EngineDownloader::OnError(DWORD request_id) {
using namespace async_wininet;
Listener* listener = GetListener(request_id);
if (listener) {
const WinHTTP::Request* req = GetRequest(request_id);
// if fp is not NULL, means need write to file
if (FILE* fp = listener->fp()) {
fclose(fp);
}
listener->OnError(req->error_code);
RemoveListener(request_id);
}
}
DWORD EngineDownloader::Download(const std::string& url, EngineDownloader::Listener* listener) {
async_wininet::WinHTTPRequestParam param;
param.url = url;
param.http_verb = async_wininet::kWinHTTPRequestGET;
DWORD request_id = downloader_->RequestUrl(param);
listeners_[request_id] = listener;
buf_[request_id] = std::string(4096, '\0');
return request_id;
}
EngineDownloader* EngineDownloader::GetInstance() {
if (instance == NULL) {
instance = new EngineDownloader();
instance->Init();
}
return instance;
}
void EngineDownloader::Init() {
if (downloader_ == NULL) {
downloader_ = new async_wininet::WinHTTP("WDJConnEngine", this);
}
}
void EngineDownloader::Uninit() {
if (downloader_) {
delete downloader_;
downloader_ = NULL;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment