目录
前言
MEGAcmd调试日志
一、MEGAcmd的主体流程
二、void megacmd() 函数
对于MEGAcmd结构的认知
前言
完了。
摸鱼的一个星期,回家果然就是啥也不想干,就是想着摸鱼。
好累啊,明明什么也没有干,但是就是想躺着。这不行啊!!!赶紧打起精神,旅游完一定要元气回归。加油加油
MEGAcmd调试日志
任务分配下来了。负责源码主流程的分析,目前的状况是要弄清楚signup的整体流程。这个流程其实老师也已经有指引着做一部分了,但是具体详细的内容还需要自己多分析。
一、MEGAcmd的主体流程
仔细看了一下,目前来说,我看见的程序入口是这样的:
首先整个程序的源文件即megacmd.cpp,里面包含了main主函数,这个就是程序运行的部分。在main主函数中,前面部分就是在初始化各种日志LOG以及管理器,最后(line5014)调用的同文件的void megacmd ( ) 函数,即程序主流程的核心循环流程。
二、void megacmd() 函数
void megacmd()
{
threadRetryConnections = new MegaThread();
threadRetryConnections->start(retryConnections, NULL);
LOG_info << "Listening to petitions ... ";
for (;; )
{
cm->waitForPetition();
api->retryPendingConnections();
if (doExit)
{
LOG_verbose << "closing after wait ..." ;
return;
}
if (cm->receivedPetition())
{
LOG_verbose << "Client connected ";
CmdPetition *inf = cm->getPetition();
LOG_verbose << "petition registered: " << inf->line;
delete_finished_threads();
if (!inf || !strcmp(inf->getLine(),"ERROR"))
{
LOG_warn << "Petition couldn't be registered. Dismissing it.";
delete inf;
}
// if state register petition
else if (!strncmp(inf->getLine(),"registerstatelistener",strlen("registerstatelistener")) ||
!strncmp(inf->getLine(),"Xregisterstatelistener",strlen("Xregisterstatelistener")))
{
cm->registerStateListener(inf);
// communicate client ID
string s = "clientID:";
s+=SSTR(currentclientID);
s+=(char)0x1F;
inf->clientID = currentclientID;
currentclientID++;
cm->informStateListener(inf,s);
#if defined(_WIN32) || defined(__APPLE__)
string message="";
ostringstream os;
MegaCmdListener *megaCmdListener = new MegaCmdListener(NULL);
api->getLastAvailableVersion("BdARkQSQ",megaCmdListener);
if (!megaCmdListener->trywait(2000))
{
if (!megaCmdListener->getError())
{
LOG_fatal << "No MegaError at getLastAvailableVersion: ";
}
else if (megaCmdListener->getError()->getErrorCode() != MegaError::API_OK)
{
LOG_debug << "Couldn't get latests available version: " << megaCmdListener->getError()->getErrorString();
}
else
{
if (megaCmdListener->getRequest()->getNumber() != MEGACMD_CODE_VERSION)
{
os << "---------------------------------------------------------------------" << endl;
os << "-- There is a new version available of megacmd: " << setw(12) << left << megaCmdListener->getRequest()->getName() << "--" << endl;
os << "-- Please, update this one: See \"update --help\". --" << endl;
os << "-- Or download the latest from https://mega.nz/cmd --" << endl;
#if defined(__APPLE__)
os << "-- Before installing enter \"exit\" to close MEGAcmd --" << endl;
#endif
os << "---------------------------------------------------------------------" << endl;
}
}
delete megaCmdListener;
}
else
{
LOG_debug << "Couldn't get latests available version (petition timed out)";
api->removeRequestListener(megaCmdListener);
delete megaCmdListener;
}
int autoupdate = ConfigurationManager::getConfigurationValue("autoupdate", -1);
if (autoupdate == -1 || autoupdate == 2)
{
os << "ENABLING AUTOUPDATE BY DEFAULT. You can disable it with \"update --auto=off\"" << endl;
autoupdate = 1;
}
if (autoupdate == 1)
{
startcheckingForUpdates();
}
message=os.str();
if (message.size())
{
s += "message:";
s+=message;
s+=(char)0x1F;
}
#endif
bool isOSdeprecated = false;
#ifdef MEGACMD_DEPRECATED_OS
isOSdeprecated = true;
#endif
#ifdef _WIN32
OSVERSIONINFOEX osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if (GetVersionEx((OSVERSIONINFO*)&osvi) && osvi.dwMajorVersion < 6)
{
isOSdeprecated = true;
}
#elif defined(__APPLE__)
char releaseStr[256];
size_t size = sizeof(releaseStr);
if (!sysctlbyname("kern.osrelease", releaseStr, &size, NULL, 0) && size > 0)
{
if (strchr(releaseStr,'.'))
{
char *token = strtok(releaseStr, ".");
if (token)
{
errno = 0;
char *endPtr = NULL;
long majorVersion = strtol(token, &endPtr, 10);
if (endPtr != token && errno != ERANGE && majorVersion >= INT_MIN && majorVersion <= INT_MAX)
{
if((int)majorVersion < 13) // Older versions from 10.9 (mavericks)
{
isOSdeprecated = true;
}
}
}
}
}
#endif
if (isOSdeprecated)
{
s += "message:";
s += "Your Operative System is too old.\n";
s += "You might not receive new updates for this application.\n";
s += "We strongly recommend you to update to a new version.\n";
s+=(char)0x1F;
}
if (sandboxCMD->storageStatus != MegaApi::STORAGE_STATE_GREEN)
{
s += "message:";
if (sandboxCMD->storageStatus == MegaApi::STORAGE_STATE_PAYWALL)
{
std::unique_ptr<char[]> myEmail(api->getMyEmail());
std::unique_ptr<MegaIntegerList> warningsList(api->getOverquotaWarningsTs());
s += "We have contacted you by email to " + string(myEmail.get()) + " on ";
s += getReadableTime(warningsList->get(0),"%b %e %Y");
if (warningsList->size() > 1)
{
for (int i = 1; i < warningsList->size() - 1; i++)
{
s += ", " + getReadableTime(warningsList->get(i),"%b %e %Y");
}
s += " and " + getReadableTime(warningsList->get(warningsList->size() - 1),"%b %e %Y");
}
std::unique_ptr<MegaNode> rootNode(api->getRootNode());
long long totalFiles = 0;
long long totalFolders = 0;
getNumFolderFiles(rootNode.get(),api,&totalFiles,&totalFolders);
s += ", but you still have " + std::to_string(totalFiles) + " files taking up " + sizeToText(sandboxCMD->receivedStorageSum);
s += " in your MEGA account, which requires you to upgrade your account.\n\n";
long long daysLeft = (api->getOverquotaDeadlineTs() - m_time(NULL)) / 86400;
if (daysLeft > 0)
{
s += "You have " + std::to_string(daysLeft) + " days left to upgrade. ";
s += "After that, your data is subject to deletion.\n";
}
else
{
s += "You must act immediately to save your data. From now on, your data is subject to deletion.\n";
}
}
else if (sandboxCMD->storageStatus == MegaApi::STORAGE_STATE_RED)
{
s += "You have exeeded your available storage.\n";
s += "You can change your account plan to increase your quota limit.\n";
}
else
{
s += "You are running out of available storage.\n";
s += "You can change your account plan to increase your quota limit.\n";
}
s += "See \"help --upgrade\" for further details.\n";
s += (char)0x1F;
}
// if server resuming session, lets give him a very litle while before sending greeting message to the early clients
// (to aovid "Resuming session..." being printed fast resumed session)
while (getloginInAtStartup() && ((m_time(nullptr) - timeLoginStarted() < RESUME_SESSION_TIMEOUT * 0.3)))
{
sleepMilliSeconds(300);
}
{
std::lock_guard<std::mutex> g(greetingsmsgsMutex);
while(greetingsFirstClientMsgs.size())
{
cm->informStateListener(inf,greetingsFirstClientMsgs.front().append(1, (char)0x1F));
greetingsFirstClientMsgs.pop_front();
}
for (auto m: greetingsAllClientMsgs)
{
cm->informStateListener(inf,m.append(1, (char)0x1F));
}
}
// if server resuming session, lets give him a litle while before returning a prompt to the early clients
// This will block the server from responging any commands in the meantime, but that assumable, it will only happen
// the first time the server is initiated.
while (getloginInAtStartup() && ((m_time(nullptr) - timeLoginStarted() < RESUME_SESSION_TIMEOUT * 0.7)))
{
sleepMilliSeconds(300);
}
// communicate status info
s+= "prompt:";
s+=dynamicprompt;
s+=(char)0x1F;
if (!sandboxCMD->getReasonblocked().size())
{
cmdexecuter->checkAndInformPSA(inf);
}
cm->informStateListener(inf,s);
}
else
{ // normal petition
processCommandInPetitionQueues(inf);
}
}
}
}
文件中也有标识( // main loop ),这个函数就是程序的核心循环,里面包含了程序不断循环监听的流程。
首先可以看到,函数的头两行,创建了一个新的MEGAThread线程,这个Retry线程就是不断的循环连接服务器,保证在线。
下来掉入一个无限for循环,在这个循环中进行以下流程:
- 对话监听器进入等待waitForPetition()
- api接口不断等待连接
- 如果退出,则执行退出程序
- 如果收到指令,日志登记,其中:
- 如果指令为ERROR或无指令的话,报错
- 如果是指令为registerstatelistener或者Xregisterstatelistener,则说明陈述的是请求需要注册,然后让对话监听器先监听该请求的状态。
余下的部分暂时还没有分析,需要继续。
对于MEGAcmd结构的认知
通过不断的函数调用追踪发现,在megacmd.cpp源文件中调用的大部分全局定义的类是从megaapi这个接口中调用的,并且该api接口调用的是sdk中的megaapi_impl,即api接口中类的定义与实现,大部分功能其实都是在这个megaapi_impl中实现的,很多函数就是跳转到这里进行研究,其实算是sdk打包的一部分,个人认为在之后的开发中这个impl文件是主要参考的部分。