wirelessgateway/datatransfer/SH_Datatrans.cpp

514 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "SH_Datatrans.hpp"
#include "dirent.h"
#include <stdio.h>
DataTrans *pDataTrans = DataTrans::instance();
struct DowloadFile {
const char *filename;
FILE *stream;
};
DataTrans::DataTrans():
m_bDebug(false)
{
}
DataTrans::~DataTrans()
{
}
static int OnDebug(CURL *, curl_infotype itype, char * pData, size_t size, void *)
{
if(itype == CURLINFO_TEXT) {
//printf("[TEXT]%s\n", pData);
} else if(itype == CURLINFO_HEADER_IN) {
print_info("[HEADER_IN]%s\n", pData);
} else if(itype == CURLINFO_HEADER_OUT) {
print_info("[HEADER_OUT]%s\n", pData);
} else if(itype == CURLINFO_DATA_IN) {
print_info("[DATA_IN]%s\n", pData);
} else if(itype == CURLINFO_DATA_OUT) {
print_info("[DATA_OUT]%s\n", pData);
}
return 0;
}
static size_t OnWriteData(void* buffer, size_t size, size_t nmemb, void* lpVoid)
{
std::string* str = dynamic_cast<std::string*>((std::string *)lpVoid);
if( NULL == str || NULL == buffer ) {
return -1;
}
char* pData = (char*)buffer;
str->append(pData, size * nmemb);
return nmemb;
}
static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream)
{
struct DowloadFile *out=(struct DowloadFile *)stream;
if(out && !out->stream) {
out->stream=fopen(out->filename, "wb");//打开文件进行写入
if(!out->stream)
return -1;
}
return fwrite(buffer, size, nmemb, out->stream);
}
int DataTrans::download(char* pFilename,string& strUrl,string& strResponse,bool bDownload)
{
CURL *curl = NULL;
CURLcode res;
struct DowloadFile dlfile={
pFilename, //定义下载到本地的文件位置和路径
NULL
};
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init(); //初始化一个curl指针
if(curl) { //curl对象存在的情况下执行的操作
//设置远端地址
curl_easy_setopt(curl, CURLOPT_URL,strUrl.c_str());
if(bDownload){
//执行写入文件流操作
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);//当有数据被写入,回调函数被调用,
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &dlfile); //设置结构体的指针传递给回调函数
}else{
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
}
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 8);//连接超时,这个数值如果设置太短可能导致数据请求不到就断开了
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);//接收数据时超时设置如果10秒内数据未接收完直接退出
//启用时会汇报所有的信息存放在STDERR或指定的CURLOPT_STDERR中
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_USERPWD, "SUREN:SUREN");
//写入文件
res = curl_easy_perform(curl);
//释放curl对象
curl_easy_cleanup(curl);
if(res != CURLE_OK)
{
cout<<stderr<<res<<endl;
return -1;
}
}
printf("strResponse = %s\n",strResponse.c_str());
if(bDownload){
if(dlfile.stream)
{
//关闭文件流
fclose(dlfile.stream);
}
}else{
}
//释放全局curl对象
curl_global_cleanup();
return 0;
}
int DataTrans::Post(const std::string & strUrl, const std::string & strPost, std::string & strResponse)
{
CURLcode res;
CURL* curl = curl_easy_init();
if(NULL == curl) {
return CURLE_FAILED_INIT;
}
if(m_bDebug)
{
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
}
curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
return res;
}
int DataTrans::Get(const std::string & strUrl, std::string & strResponse)
{
CURLcode res;
CURL* curl = curl_easy_init();
if(NULL == curl) {
return CURLE_FAILED_INIT;
}
if(m_bDebug) {
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
}
curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
/**
* 当多个线程都使用超时处理的时候同时主线程中有sleep或是wait等操作。
* 如果不设置这个选项libcurl将会发信号打断这个wait从而导致程序退出。
*/
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
return res;
}
int DataTrans::Posts(const std::string & strUrl, const std::string & strPost, std::string & strResponse, const char * pCaPath)
{
CURLcode res;
CURL* curl = curl_easy_init();
if(NULL == curl) {
return CURLE_FAILED_INIT;
}
if(m_bDebug) {
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
}
curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
if(NULL == pCaPath) {
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
} else {
//缺省情况就是PEM所以无需设置另外支持DER
//curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
}
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
return res;
}
int DataTrans::Gets(const std::string & strUrl, std::string & strResponse, const char * pCaPath)
{
CURLcode res;
CURL* curl = curl_easy_init();
if(NULL == curl) {
return CURLE_FAILED_INIT;
}
if(m_bDebug) {
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
}
curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
if(NULL == pCaPath) {
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
} else {
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
}
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
return res;
}
int DataTrans::upload_file(const std::string &strUrl, const std::string &filename, std::string &response)
{
CURL *curl;
CURLM *multi_handle;
int still_running;
char res[60];
struct curl_httppost *formpost = NULL;
struct curl_httppost *lastptr = NULL;
struct curl_slist *headerlist = NULL;
static const char buf[] = "Expect:";
curl_global_init(CURL_GLOBAL_ALL);
/* Fill in the file upload field. This makes libcurl load data from
the given file name when curl_easy_perform() is called. */
/* Fill in the filename field */
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "filename", CURLFORM_FILE, filename.c_str(), CURLFORM_END);
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "submit", CURLFORM_COPYCONTENTS, "upload", CURLFORM_END);
curl = curl_easy_init();
multi_handle = curl_multi_init();
/* initalize custom header list (stating that Expect: 100-continue is not wanted */
headerlist = curl_slist_append(headerlist, buf);
if (curl && multi_handle) {
/* what URL that receives this POST */
curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, res);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
curl_multi_add_handle(multi_handle, curl);
curl_multi_perform(multi_handle, &still_running);
do {
struct timeval timeout;
int rc;
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd = -1;
long curl_timeo = -1;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
/* set a suitable timeout to play around with */
timeout.tv_sec = 1;
timeout.tv_usec = 0;
curl_multi_timeout(multi_handle, &curl_timeo);
if (curl_timeo >= 0) {
timeout.tv_sec = curl_timeo / 1000;
if (timeout.tv_sec > 1)
timeout.tv_sec = 1;
else
timeout.tv_usec = (curl_timeo % 1000) * 1000;
}
/* get file descriptors from the transfers */
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
/* In a real-world program you OF COURSE check the return code of the
function calls. On success, the value of maxfd is guaranteed to be
greater or equal than -1. We call select(maxfd + 1, ...), specially in
case of (maxfd == -1), we call select(0, ...), which is basically equal
to sleep. */
rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
switch (rc) {
case -1:
break;
case 0:
default:
/* timeout or readable/writable sockets */
print_info("perform!\n");
curl_multi_perform(multi_handle, &still_running);
print_info("running: %d!\n", still_running);
break;
}
} while (still_running);
curl_multi_cleanup(multi_handle);
/* always cleanup */
curl_easy_cleanup(curl);
/* then cleanup the formpost chain */
curl_formfree(formpost);
/* free slist */
curl_slist_free_all(headerlist);
}
return 0;
}
// int DataTrans::Send_file_socket(const std::string &filename)
// {
// int socketfd;
// struct sockaddr_in s_add,c_add;
// unsigned short portnum = 9092;
// int len;
// char buffer[4096];
// FILE *fp ;
// int file_block_length = 0;
// /*
// *创建socket
// */
// if((socketfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
// {
// print_error("Socket create error! \n");
// return -1;
// }
// /*
// *设置地址
// */
// bzero(&s_add,sizeof(struct sockaddr_in));
// s_add.sin_family = AF_INET;
// //s_add.sin_addr.s_addr = inet_addr(GlobalConfig::ServerIP.c_str());
// s_add.sin_addr.s_addr = inet_addr("192.168.1.19");
// s_add.sin_port = htons(portnum);
// if (connect(socketfd,(struct sockaddr *)(&s_add),sizeof(struct sockaddr)) < 0)
// {
// print_error("Connect failure!\n");
// return -1;
// }
// else
// print_info("Connect Success!\n");
// std::string filename = filename.substr();
// int file_name_length = (int)strlen(filename.c_str());
// if(send(socketfd,(char *)&file_name_length, sizeof(int), 0) < 0)
// {
// print_error("Send File_Name_Length Failed!\n");
// }else
// {
// print_info("Send File_Name_Length Success!\n");
// }
// //发送文件名
// if(send(socketfd,filename.c_str(),file_name_length,0) < 0)
// {
// print_error("Send File_Name Failed!\n");
// }else
// {
// print_info("Send File_Name Success!\n");
// }
// /*
// *发送文件
// */
// fp = fopen(filename.c_str(), "r");
// if (fp == NULL)
// {
// print_error("File: %s Not Found!\n", filename.c_str());
// }
// else
// {
// bzero(buffer, BUFFER_SIZE);
// while( (file_block_length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)
// {
// print_info("file_block_length = %d\n", file_block_length);
// /*
// *把数据写入buffer
// */
// if (send(socketfd, buffer, file_block_length, 0) < 0)
// {
// print_error("Send File:%s Failed!\n", filename.c_str());
// break;
// }
// bzero(buffer, sizeof(buffer));
// }
// fclose(fp);
// print_info("File: %s Transfer Finished!\n", filename.c_str());
// }
// close(socketfd);
// return 0;
// }
int DataTrans::Send_file_socket(const std::string &filename)
{
return 0;
}
int DataTrans::Send_Dir_socket(const char *dirname)
{
DIR *dirp;
std::vector<string> v;
std::string temp;
struct dirent *dp;
dirp = opendir(dirname);
while ((dp = readdir(dirp)) != NULL) {
if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
continue;
v.push_back(std::string(dp->d_name));
}
int socketfd = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in s_add,c_add;
unsigned short portnum = 12345;
int len;
char buffer[BUFFER_SIZE];
FILE *fp ;
int file_block_length = 0;
/*
*创建socket
*/
if(socketfd < 0) {
print_error("Socket create error! \n");
return -1;
} else {
print_info("Socket create success!\n");
}
/*
*设置地址
*/
bzero(&s_add,sizeof(struct sockaddr_in));
s_add.sin_family = AF_INET;
s_add.sin_addr.s_addr = inet_addr(GlobalConfig::ServerIP.c_str());
s_add.sin_port = htons(PORT);
if (connect(socketfd,(struct sockaddr *)(&s_add),sizeof(struct sockaddr)) < 0) {
print_error("Connect failure!\n");
return -1;
} else {
print_info("Connect Success!\n");
}
std::vector<std::string>::iterator iter;
for(iter = v.begin();iter != v.end();++iter) {
temp = *iter;
cout << temp.c_str() <<endl;
int file_name_length = (int)strlen(temp.c_str());
if (send(socketfd, (char *)&file_name_length, sizeof(int), 0) < 0) {//发送文件名长度
print_error("Send File_Name_Length Failed!\n");
} else {
print_info("Send File_Name_Length Success!\n");
}
//发送文件名
if(send(socketfd,temp.c_str(),file_name_length,0) < 0) {
print_error("Send File_Name Failed!\n");
} else {
print_info("Send File_Name Success!\n");
}
/*
*发送文件
*/
std::string filename = std::string(dirname + temp);
fp = fopen(filename.c_str(), "r");
if (fp == NULL) {
print_error("File: %s Not Found!\n", filename.c_str());
} else {
bzero(buffer, BUFFER_SIZE);
while( (file_block_length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0) {
print_info("file_block_length = %d\n", file_block_length);
/*
*把数据写入buffer
*/
if (send(socketfd, buffer, file_block_length, 0) < 0) {
print_error("Send File:%s Failed!\n", filename.c_str());
break;
}
bzero(buffer, sizeof(buffer));
}
fclose(fp);
print_info("File: %s Transfer Finished!\n", filename.c_str());
}
close(socketfd);
return 0;
}
}
void DataTrans::SetDebug(bool bDebug)
{
m_bDebug = bDebug;
}