Switch to uploader thread for log file uploads.
This commit is contained in:
@@ -36,7 +36,7 @@ DownloadHelper::~DownloadHelper()
|
||||
}
|
||||
|
||||
void
|
||||
DownloadHelper::InternalInit(const string &/*url*/, const string &targetFileName, const string &/*user*/, const string &/*password*/, size_t /*filesize*/)
|
||||
DownloadHelper::InternalInit(const string &/*url*/, const string &targetFileName, const string &/*user*/, const string &/*password*/, size_t /*filesize*/, const string &/*httpPost*/)
|
||||
{
|
||||
// Open target file for writing.
|
||||
GetData()->targetFile = fopen(targetFileName.c_str(), "wb");
|
||||
|
||||
@@ -31,9 +31,6 @@ using namespace std;
|
||||
TransferHelper::TransferHelper()
|
||||
{
|
||||
m_data.reset(new TransferData);
|
||||
m_data->curlHandle = NULL;
|
||||
m_data->curlMultiHandle = NULL;
|
||||
m_data->targetFile = NULL;
|
||||
}
|
||||
|
||||
TransferHelper::~TransferHelper()
|
||||
@@ -42,8 +39,11 @@ TransferHelper::~TransferHelper()
|
||||
}
|
||||
|
||||
void
|
||||
TransferHelper::Init(const string &url, const string &targetFileName, const string &user, const string &password, size_t filesize)
|
||||
TransferHelper::Init(const string &url, const string &targetFileName, const string &user, const string &password, size_t filesize, const string &httpPost)
|
||||
{
|
||||
// Cleanup data.
|
||||
Cleanup();
|
||||
m_data->returnMessage.clear();
|
||||
// Initialise curl.
|
||||
m_data->curlHandle = curl_easy_init();
|
||||
if (!m_data->curlHandle)
|
||||
@@ -57,7 +57,7 @@ TransferHelper::Init(const string &url, const string &targetFileName, const stri
|
||||
if (curl_easy_setopt(m_data->curlHandle, CURLOPT_URL, m_data->curlUrl.c_str()) != CURLE_OK)
|
||||
throw NetException(__FILE__, __LINE__, ERR_SOCK_TRANSFER_INVALID_URL, 0);
|
||||
|
||||
InternalInit(url, targetFileName, user, password, filesize);
|
||||
InternalInit(url, targetFileName, user, password, filesize, httpPost);
|
||||
|
||||
// Use the multi interface for better abort handling.
|
||||
if (curl_multi_add_handle(m_data->curlMultiHandle, m_data->curlHandle) != CURLM_OK)
|
||||
@@ -128,6 +128,10 @@ TransferHelper::Process()
|
||||
void
|
||||
TransferHelper::Cleanup()
|
||||
{
|
||||
if (m_data->post) {
|
||||
curl_formfree(m_data->post);
|
||||
m_data->post = NULL;
|
||||
}
|
||||
if (m_data->curlMultiHandle) {
|
||||
curl_multi_cleanup(m_data->curlMultiHandle);
|
||||
m_data->curlMultiHandle = NULL;
|
||||
@@ -143,6 +147,14 @@ TransferHelper::Cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
string
|
||||
TransferHelper::ResetLastMessage()
|
||||
{
|
||||
string retVal(m_data->returnMessage);
|
||||
m_data->returnMessage.clear();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
boost::shared_ptr<TransferData>
|
||||
TransferHelper::GetData()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*****************************************************************************
|
||||
* PokerTH - The open source texas holdem engine *
|
||||
* Copyright (C) 2006-2012 Felix Hammer, Florian Thauer, Lothar May *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Affero General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Affero General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Affero General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*****************************************************************************/
|
||||
|
||||
#include <net/uploadcallback.h>
|
||||
|
||||
|
||||
UploadCallback::~UploadCallback()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <net/uploaderthread.h>
|
||||
#include <net/uploadhelper.h>
|
||||
#include <net/uploadcallback.h>
|
||||
#include <net/netexception.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <core/loghelper.h>
|
||||
@@ -28,8 +29,8 @@ using namespace std;
|
||||
using namespace boost::filesystem;
|
||||
|
||||
|
||||
UploaderThread::UploaderThread()
|
||||
: m_uploadInProgress(false)
|
||||
UploaderThread::UploaderThread(UploadCallback *callback)
|
||||
: m_uploadInProgress(false), m_callback(callback)
|
||||
{
|
||||
m_uploadHelper.reset(new UploadHelper());
|
||||
}
|
||||
@@ -39,15 +40,16 @@ UploaderThread::~UploaderThread()
|
||||
}
|
||||
|
||||
void
|
||||
UploaderThread::QueueUpload(const string &url, const string &user, const string &pwd, const string &filename, size_t filesize)
|
||||
UploaderThread::QueueUpload(const string &url, const string &user, const string &pwd, const string &filename, size_t filesize, const string &httpPost)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_uploadQueueMutex);
|
||||
m_uploadQueue.push(UploadData(url, user, pwd, filename, filesize));
|
||||
m_uploadQueue.push(UploadData(url, user, pwd, filename, filesize, httpPost));
|
||||
}
|
||||
|
||||
void
|
||||
UploaderThread::Main()
|
||||
{
|
||||
string lastfile;
|
||||
while (!ShouldTerminate()) {
|
||||
try {
|
||||
if (m_uploadInProgress) {
|
||||
@@ -55,29 +57,40 @@ UploaderThread::Main()
|
||||
}
|
||||
|
||||
if (!m_uploadInProgress) {
|
||||
string lastMsg(m_uploadHelper->ResetLastMessage());
|
||||
if (!lastMsg.empty() && m_callback) {
|
||||
m_callback->UploadCompleted(lastfile, lastMsg);
|
||||
}
|
||||
Msleep(UPLOAD_DELAY_MSEC);
|
||||
// The upload needs only local state, as no value needs to be returned.
|
||||
UploadData data;
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_uploadQueueMutex);
|
||||
if (!m_uploadQueue.empty()) {
|
||||
data = m_uploadQueue.front();
|
||||
lastfile = data.filename;
|
||||
m_uploadQueue.pop();
|
||||
}
|
||||
}
|
||||
if (!data.filename.empty() && data.filesize > 0) {
|
||||
path filepath(data.filename);
|
||||
string url(data.address);
|
||||
if (data.httpPost.empty()) {
|
||||
#if BOOST_FILESYSTEM_VERSION != 3
|
||||
m_uploadHelper->Init(data.address + filepath.leaf(), filepath.file_string(), data.user, data.pwd, data.filesize);
|
||||
url += filepath.leaf();
|
||||
#else
|
||||
m_uploadHelper->Init(data.address + filepath.filename().string(), filepath.file_string(), data.user, data.pwd, data.filesize);
|
||||
url += filepath.filename().string();
|
||||
#endif
|
||||
}
|
||||
m_uploadHelper->Init(url, filepath.file_string(), data.user, data.pwd, data.filesize, data.httpPost);
|
||||
m_uploadInProgress = true;
|
||||
}
|
||||
}
|
||||
} catch (const NetException &e) {
|
||||
LOG_ERROR("Upload failed: " << e.what());
|
||||
m_uploadInProgress = false;
|
||||
if (m_callback) {
|
||||
m_callback->UploadError(lastfile, e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,14 @@ readFunction(char *bufptr, size_t size, size_t nitems, void *userp)
|
||||
return fread(bufptr, size, nitems, (FILE *)userp);
|
||||
}
|
||||
|
||||
size_t
|
||||
writeFunction(char *bufptr, size_t size, size_t nitems, void *userp)
|
||||
{
|
||||
string msgPart(bufptr, size * nitems);
|
||||
((string *)userp)->append(msgPart);
|
||||
return size * nitems;
|
||||
}
|
||||
|
||||
UploadHelper::UploadHelper()
|
||||
{
|
||||
}
|
||||
@@ -43,22 +51,35 @@ UploadHelper::~UploadHelper()
|
||||
}
|
||||
|
||||
void
|
||||
UploadHelper::InternalInit(const string &/*url*/, const string &targetFileName, const string &user, const string &password, size_t filesize)
|
||||
UploadHelper::InternalInit(const string &/*url*/, const string &targetFileName, const string &user, const string &password, size_t filesize, const string &httpPost)
|
||||
{
|
||||
// Open target file for reading.
|
||||
GetData()->targetFile = fopen(targetFileName.c_str(), "rb");
|
||||
if (!GetData()->targetFile)
|
||||
throw NetException(__FILE__, __LINE__, ERR_SOCK_TRANSFER_OPEN_FAILED, 0);
|
||||
|
||||
GetData()->userCredentials = user + ":" + password;
|
||||
// Assume that the following calls never fail.
|
||||
curl_easy_setopt(GetData()->curlHandle, CURLOPT_READFUNCTION, readFunction);
|
||||
curl_easy_setopt(GetData()->curlHandle, CURLOPT_READDATA, GetData()->targetFile);
|
||||
curl_easy_setopt(GetData()->curlHandle, CURLOPT_INFILESIZE, filesize);
|
||||
curl_easy_setopt(GetData()->curlHandle, CURLOPT_USERPWD, GetData()->userCredentials.c_str());
|
||||
curl_easy_setopt(GetData()->curlHandle, CURLOPT_UPLOAD, 1L);
|
||||
curl_easy_setopt(GetData()->curlHandle, CURLOPT_PUT, 1L);
|
||||
curl_easy_setopt(GetData()->curlHandle, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(GetData()->curlHandle, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
|
||||
if (!user.empty() || !password.empty()) {
|
||||
GetData()->userCredentials = user + ":" + password;
|
||||
curl_easy_setopt(GetData()->curlHandle, CURLOPT_USERPWD, GetData()->userCredentials.c_str());
|
||||
}
|
||||
if (httpPost.empty()) {
|
||||
// Open target file for reading.
|
||||
GetData()->targetFile = fopen(targetFileName.c_str(), "rb");
|
||||
if (!GetData()->targetFile)
|
||||
throw NetException(__FILE__, __LINE__, ERR_SOCK_TRANSFER_OPEN_FAILED, 0);
|
||||
curl_easy_setopt(GetData()->curlHandle, CURLOPT_READFUNCTION, readFunction);
|
||||
curl_easy_setopt(GetData()->curlHandle, CURLOPT_READDATA, GetData()->targetFile);
|
||||
curl_easy_setopt(GetData()->curlHandle, CURLOPT_PUT, 1L);
|
||||
curl_easy_setopt(GetData()->curlHandle, CURLOPT_UPLOAD, 1L);
|
||||
curl_easy_setopt(GetData()->curlHandle, CURLOPT_INFILESIZE, filesize);
|
||||
} else {
|
||||
// Curl will handle file I/O.
|
||||
struct curl_httppost *last = NULL;
|
||||
curl_formadd(&GetData()->post, &last,
|
||||
CURLFORM_COPYNAME, httpPost.c_str(),
|
||||
CURLFORM_FILE, targetFileName.c_str(),
|
||||
CURLFORM_END);
|
||||
curl_easy_setopt(GetData()->curlHandle, CURLOPT_HTTPPOST, GetData()->post);
|
||||
curl_easy_setopt(GetData()->curlHandle, CURLOPT_WRITEFUNCTION, writeFunction);
|
||||
curl_easy_setopt(GetData()->curlHandle, CURLOPT_WRITEDATA, &GetData()->returnMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,8 @@ public:
|
||||
|
||||
protected:
|
||||
virtual void InternalInit(const std::string &url, const std::string &targetFileName,
|
||||
const std::string &user, const std::string &password, size_t filesize);
|
||||
const std::string &user, const std::string &password,
|
||||
size_t filesize, const std::string &httpPost);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -25,11 +25,14 @@
|
||||
|
||||
|
||||
struct TransferData {
|
||||
TransferData() : curlHandle(NULL), curlMultiHandle(NULL), targetFile(NULL), post(NULL) {}
|
||||
CURL *curlHandle;
|
||||
CURLM *curlMultiHandle;
|
||||
FILE *targetFile;
|
||||
std::string curlUrl;
|
||||
std::string userCredentials;
|
||||
struct curl_httppost *post;
|
||||
std::string returnMessage;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -35,7 +35,8 @@ public:
|
||||
// Set the parameters. Does not do any error checking.
|
||||
// Throws an exception on failure.
|
||||
void Init(const std::string &url, const std::string &targetFileName,
|
||||
const std::string &user = "", const std::string &password = "", size_t filesize = 0);
|
||||
const std::string &user = "", const std::string &password = "",
|
||||
size_t filesize = 0, const std::string &httpPost = "");
|
||||
|
||||
// Returns true when done, false should call again.
|
||||
// Throws an exception on error.
|
||||
@@ -44,11 +45,15 @@ public:
|
||||
// Close all handles.
|
||||
void Cleanup();
|
||||
|
||||
// Get and reset the last (error) message.
|
||||
std::string ResetLastMessage();
|
||||
|
||||
protected:
|
||||
boost::shared_ptr<TransferData> GetData();
|
||||
|
||||
virtual void InternalInit(const std::string &url, const std::string &targetFileName,
|
||||
const std::string &user, const std::string &password, size_t filesize) = 0;
|
||||
const std::string &user, const std::string &password,
|
||||
size_t filesize, const std::string &httpPost) = 0;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*****************************************************************************
|
||||
* PokerTH - The open source texas holdem engine *
|
||||
* Copyright (C) 2006-2012 Felix Hammer, Florian Thauer, Lothar May *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Affero General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Affero General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Affero General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*****************************************************************************/
|
||||
/* Network file upload callback. */
|
||||
|
||||
#ifndef _UPLOADCALLBACK_H_
|
||||
#define _UPLOADCALLBACK_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
class UploadCallback
|
||||
{
|
||||
public:
|
||||
virtual ~UploadCallback();
|
||||
|
||||
virtual void UploadCompleted(const std::string &filename, const std::string &returnMessage) = 0;
|
||||
virtual void UploadError(const std::string &filename, const std::string &errorMessage) = 0;
|
||||
};
|
||||
|
||||
#endif // _UPLOADCALLBACK_H_
|
||||
@@ -27,27 +27,29 @@
|
||||
|
||||
#define UPLOADER_THREAD_TERMINATE_TIMEOUT THREAD_WAIT_INFINITE
|
||||
class UploadHelper;
|
||||
class UploadCallback;
|
||||
|
||||
class UploaderThread : public Thread
|
||||
{
|
||||
public:
|
||||
|
||||
UploaderThread();
|
||||
UploaderThread(UploadCallback *callback = NULL);
|
||||
virtual ~UploaderThread();
|
||||
|
||||
void QueueUpload(const std::string &url, const std::string &user, const std::string &pwd, const std::string &filename, size_t filesize);
|
||||
void QueueUpload(const std::string &url, const std::string &user, const std::string &pwd, const std::string &filename, size_t filesize, const std::string &httpPost = "");
|
||||
|
||||
protected:
|
||||
struct UploadData {
|
||||
UploadData() : filesize(0) {}
|
||||
UploadData(const std::string &a, const std::string &u, const std::string &p, const std::string &f, size_t s)
|
||||
: address(a), user(u), pwd(p), filename(f), filesize(s) {}
|
||||
UploadData(const std::string &a, const std::string &u, const std::string &p, const std::string &f, size_t s, const std::string &h)
|
||||
: address(a), user(u), pwd(p), filename(f), filesize(s), httpPost(h) {}
|
||||
|
||||
std::string address;
|
||||
std::string user;
|
||||
std::string pwd;
|
||||
std::string filename;
|
||||
size_t filesize;
|
||||
std::string httpPost;
|
||||
};
|
||||
|
||||
typedef std::queue<UploadData> UploadDataQueue;
|
||||
@@ -62,6 +64,7 @@ private:
|
||||
|
||||
boost::shared_ptr<UploadHelper> m_uploadHelper;
|
||||
bool m_uploadInProgress;
|
||||
UploadCallback *m_callback;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,7 +31,8 @@ public:
|
||||
|
||||
protected:
|
||||
virtual void InternalInit(const std::string &url, const std::string &targetFileName,
|
||||
const std::string &user, const std::string &password, size_t filesize);
|
||||
const std::string &user, const std::string &password,
|
||||
size_t filesize, const std::string &httpPost);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user