SVG5/scurl.cpp
2025-10-12 13:55:56 +09:00

436 lines
12 KiB
C++

#include "scurl.h"
#include <QFileInfo>
#include <QtNetwork/QNetworkInterface>
#include <QtNetwork/QNetworkAddressEntry>
int SCURL::m_nUsage = 0;
quint64 SCURL::m_nFileSize = 0;
quint64 SCURL::m_nCurrentRead = 0;
int SCURL::m_nPrevCount = 0;
int SCURL::m_nErrorCount = 0;
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#ifdef WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
#include <sys/socket.h>
#include "mainwindow.h"
/* <DESC>
* Performs an FTP upload and renames the file just after a successful
* transfer.
* </DESC>
*/
SCURL* g_pThis = NULL;
typedef struct _GlobalInfo
{
CURLM *multi;
int still_running;
} GlobalInfo;
/* Information associated with a specific easy handle */
typedef struct _ConnInfo
{
CURL *easy;
char *url;
GlobalInfo *global;
char error[CURL_ERROR_SIZE];
} ConnInfo;
static curl_socket_t opensocket(void *clientp,
curlsocktype purpose,
struct curl_sockaddr *address)
{
g_pThis->m_SocketFD = *(curl_socket_t *)clientp;
/* the actual externally set socket is passed in via the OPENSOCKETDATA
option */
return g_pThis->m_SocketFD;
}
static int sockopt_callback(void *clientp, curl_socket_t curlfd,
curlsocktype purpose)
{
/* This return code was added in libcurl 7.21.5 */
return CURL_SOCKOPT_ALREADY_CONNECTED;
}
//static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
size_t SCURL::read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
{
unsigned long nread;
/* in real-world cases, this would probably get this data differently
as this fread() stuff is exactly what the library already would do
by default internally */
size_t retcode = fread(ptr, size, nmemb, (FILE*)stream);
m_nCurrentRead += retcode;
g_pThis->SetProgressExportPercent(m_nCurrentRead, m_nFileSize);
usleep(10);
if(retcode > 0)
{
nread = (unsigned long)retcode;
//fprintf(stderr, "*** We read %lu bytes from file\n", nread);
}
return retcode;
}
int SCURL::CurlProgress(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
{
if(g_pThis->m_bStop==true)
{
curl_socket_t sockfd;
auto res = curl_easy_getinfo(g_pThis->m_pCURL, CURLINFO_ACTIVESOCKET, &sockfd);
// ASSERT_EQ(res, CURLE_OK); - no point in doing anything if the socket is not there
close(sockfd);
curl_easy_reset( g_pThis->m_pCURL );
return CURLE_UNRECOVERABLE_POLL;
}
if( dltotal > 0 || dlnow > 0 || ultotal > 0 || ulnow > 0)
{
g_pThis->m_nFileSize = ultotal;
g_pThis->m_nCurrentRead = ulnow;
if(g_pThis->m_nCurrentRead==g_pThis->m_nPrevCount)
{
g_pThis->m_nErrorCount++;
if(g_pThis->m_nErrorCount>5)
{
curl_socket_t sockfd;
auto res = curl_easy_getinfo(g_pThis->m_pCURL, CURLINFO_ACTIVESOCKET, &sockfd);
// ASSERT_EQ(res, CURLE_OK); - no point in doing anything if the socket is not there
close(sockfd);
curl_easy_reset( g_pThis->m_pCURL );
return CURLE_UNRECOVERABLE_POLL;
}
}
else
{
g_pThis->m_nErrorCount = 0;
}
g_pThis->m_nPrevCount = ulnow;
//static int m_nPrevCount;
//static int m_nErrorCount;
//fprintf(stderr, "Up: %d/%d\n", ulnow, ultotal);
//CryLogAlways("UP: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T " DOWN: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T "\r\n", ulnow, ultotal, dlnow, dltotal);
}
return CURLE_OK;
}
SCURL::SCURL()
{
m_nUsage++;
g_pThis = this;
m_bStop = false;
connect(&m_Timer, SIGNAL(timeout()), this, SLOT(OnTimer()));
}
SCURL::~SCURL()
{
m_nUsage--;
disconnect(&m_Timer, SIGNAL(timeout()), this, SLOT(OnTimer()));
}
void SCURL::OnTimer()
{
if(m_nPrevCount==m_nCurrentRead)
{
m_nErrorCount++;
if(m_nErrorCount>2)
{
curl_easy_reset( m_pCURL );
m_Timer.stop();
}
}
else
{
m_nErrorCount = 0;
}
m_nPrevCount = m_nCurrentRead;
}
void SCURL::Init()
{
curl_global_init(CURL_GLOBAL_ALL);
}
void SCURL::Release()
{
curl_global_cleanup();
}
int SCURL::UploadFTP2(QString strFilename)
{
return 0;
}
int SCURL::UploadFTP(QString strFilename)
{
if(IsConnectNetwork()==false)
{
return -11;
}
CURLcode res;
FILE *hd_src;
struct stat file_info;
unsigned long fsize;
struct curl_slist *headerlist = NULL;
//static const char buf_1 [] = "RNFR " UPLOAD_FILE_AS;
//static const char buf_2 [] = "RNTO " RENAME_FILE_TO;
QFileInfo fi(strFilename);
QString strFile = fi.fileName();
QString strPath = fi.path();
strPath = strPath.replace("/data/video/", "");
int nRet = 0;
CommonData* pCommonData = MainWindow::GetCommonData();
NetworkShareInfo* pShareInfo = pCommonData->GetNetworkShareInfo();
QString strID;
QString strPassword;
int nPort = 21;
bool bUseSSL = false;
strID = pShareInfo->m_strID;
strPassword = pShareInfo->m_strPassword;
nPort = pShareInfo->m_strIP.toInt();
QString strTargetFolder = pShareInfo->m_strShareFolder;
if(pShareInfo->m_strVersion.contains("SSL")==true)
{
bUseSSL = true;
}
//QString strUrl = QString("ftp://192.168.1.19/OK/%1/%2").arg(strPath).arg(strFile);
QString strUrl = QString("%1/%2/%3").arg(strTargetFolder).arg(strPath).arg(strFile);
/* get the file size of the local file */
if(stat(strFilename.toStdString().c_str(), &file_info)) {
printf("Couldn't open '%s': %s\n", strFilename.toStdString().c_str(), strerror(errno));
return -1;
}
fsize = (unsigned long)file_info.st_size;
m_nFileSize = fsize;
m_nCurrentRead = 0;
m_nErrorCount = 0;
m_nPrevCount = -1;
SetProgressExportPercent(m_nCurrentRead, m_nFileSize);
printf("Local file size: %lu bytes.\n", fsize);
/* get a FILE * of the same file */
hd_src = fopen(strFilename.toStdString().c_str(), "rb");
/* get a curl handle */
m_pCURL = curl_easy_init();
if(m_pCURL) {
/* build a list of commands to pass to libcurl */
//headerlist = curl_slist_append(headerlist, strFileFrom.toStdString().c_str());
//headerlist = curl_slist_append(headerlist, strFileTo.toStdString().c_str());
/* call this function to get a socket */
//curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket);
//curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, &m_SocketFD);
/* call this function to set options for the socket */
//curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
curl_easy_setopt(m_pCURL, CURLOPT_CONNECTTIMEOUT_MS, 1000L); //1 Second
curl_easy_setopt(m_pCURL, CURLOPT_TIMEOUT_MS, 1000*60*10); //10 Minutes
curl_easy_setopt(m_pCURL, CURLOPT_PROTOCOLS, CURLPROTO_FTP);
/* we want to use our own read function */
curl_easy_setopt(m_pCURL, CURLOPT_READFUNCTION, read_callback);
/* enable uploading */
curl_easy_setopt(m_pCURL, CURLOPT_UPLOAD, 1L);
/* specify target */
curl_easy_setopt(m_pCURL, CURLOPT_URL, strUrl.toStdString().c_str());
/* now specify which file to upload */
curl_easy_setopt(m_pCURL, CURLOPT_READDATA, hd_src);
/* Set the size of the file to upload (optional). If you give a *_LARGE
option you MUST make sure that the type of the passed-in argument is a
curl_off_t. If you use CURLOPT_INFILESIZE (without _LARGE) you must
make sure that to pass in a type 'long' argument. */
curl_easy_setopt(m_pCURL, CURLOPT_INFILESIZE_LARGE,
(curl_off_t)fsize);
curl_easy_setopt(m_pCURL, CURLOPT_FTP_CREATE_MISSING_DIRS,
(long)CURLFTP_CREATE_DIR);
//curl_easy_setopt(curl, CURLOPT_USERNAME, "birdhead");
//curl_easy_setopt(curl, CURLOPT_PASSWORD, "1");
curl_easy_setopt(m_pCURL, CURLOPT_USERNAME, strID.toStdString().c_str());
curl_easy_setopt(m_pCURL, CURLOPT_PASSWORD, strPassword.toStdString().c_str());
curl_easy_setopt(m_pCURL, CURLOPT_PORT, nPort);
//curl_easy_setopt(m_pCURL, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(m_pCURL, CURLOPT_VERBOSE, 0L);
curl_easy_setopt(m_pCURL, CURLOPT_LOGIN_OPTIONS, "AUTH=LOGIN");
if(bUseSSL==true)
{
//curl_easy_setopt(m_pCURL, CURLOPT_FTP_USE_EPSV, 0L);
/* require use of SSL for this, or fail */
curl_easy_setopt(m_pCURL, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
//curl_easy_setopt(m_pCURL, CURLOPT_FTPPORT, nPort);
curl_easy_setopt(m_pCURL, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(m_pCURL, CURLOPT_SSL_VERIFYHOST, 0L);
//curl_easy_setopt(m_pCURL, CURLOPT_FTP_SSL, CURLFTPSSL_ALL);
curl_easy_setopt(m_pCURL, CURLOPT_FTP_SSL, CURLFTPSSL_TRY);
curl_easy_setopt(m_pCURL, CURLOPT_FTPSSLAUTH, CURLFTPAUTH_TLS);
curl_easy_setopt(m_pCURL, CURLOPT_NOPROGRESS, 0L);
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
//curl_setopt($ch, CURLOPT_FTP_SSL, true);
//curl_setopt($ch, CURLOPT_VERBOSE, true);
}
else
{
curl_easy_setopt(m_pCURL, CURLOPT_NOPROGRESS, 0L);
}
//curl_easy_setopt(m_pCURL, CURLOPT_TIMEOUT, 1L);
curl_easy_setopt(m_pCURL, CURLOPT_XFERINFOFUNCTION, CurlProgress);
//m_Timer.setSingleShot(true);
//m_Timer.start(500);
/* Now run off and do what you have been told! */
res = curl_easy_perform(m_pCURL);
//m_Timer.stop();
/* Check for errors */
if(res != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
nRet = -res;
}
/* clean up the FTP commands list */
curl_slist_free_all(headerlist);
/* always cleanup */
curl_easy_cleanup(m_pCURL);
}
fclose(hd_src); /* close the local file */
return nRet;
}
bool SCURL::IsConnectNetwork()
{
bool bIsConnect = false;
QList<QNetworkInterface> listNetworkInterface = QNetworkInterface::allInterfaces();
int nCount = listNetworkInterface.size();
int i=0;
for(i=0 ; i<nCount ; i++)
{
QNetworkInterface ni = listNetworkInterface[i];
//int nIndex = ni.index();
//int nMaximumTransmissionUnit = ni.maximumTransmissionUnit();
QString strName = ni.name();
//QString strHumanReadableName = ni.humanReadableName();
//InterfaceFlags flags() const;
QNetworkInterface::InterfaceType nType = ni.type();
//QString strHardwareAddress = ni.hardwareAddress();
QList<QNetworkAddressEntry> listNetworkAddresssEntry = ni.addressEntries();
if(nType==QNetworkInterface::Ethernet)
{
if(strName.contains("eth")==true)
{
if(listNetworkAddresssEntry.size()==0)
{
bIsConnect = false;
}
else
{
bIsConnect = true;
/*
int j=0;
for(j=0 ; j<listNetworkAddresssEntry.size() ; j++)
{
QNetworkAddressEntry nae = listNetworkAddresssEntry[j];
QHostAddress ha = nae.ip();
bool bIsLocal = ha.isLinkLocal();
bool bIsGlobal = ha.isGlobal();
}
*/
}
break;
}
}
}
return bIsConnect;
}
void SCURL::StopCURL()
{
m_bStop = true;
}