📄 warsvrprotocol.cpp
字号:
#include "StdAfx.h"#include "WarSvrProtocol.h" // class implemented#ifndef WAR_AUTO_LOCK_H# include "WarAutoLock.h"#endif#ifndef WAR_SVR_ENGINE_H# include "WarSvrEngine.h"#endif#ifndef WAR_OS_H# include "WarOs.h"#endif#ifndef WAR_SVR_PROTOCOL_FTP_H# include "WarSvrProtocolFtp.h" // requiered FTP RFC's#endif#ifndef WAR_UNICODE_H# include "WarUnicode.h"#endif#ifndef WAR_LOG_H# include "WarLog.h"#endif#ifndef WAR_FSYS_H# include "WarFsys.h"#endif#ifndef WAR_PERFMON_DEF_H# include "WarPerfmonDef.h"#endif#define AUTO_LOCK WarAutoLock MyLock(mSvrLock);using namespace std;/////////////////////////////// PUBLIC /////////////////////////////////////////============================= LIFECYCLE ====================================WarSvrProtocol::WarSvrProtocol(war_socket_io_ptr_t& companionPtr, WarSvrDefinition& svrDefinion) :WarTransferSocket(companionPtr),WarPluginSupport<WarSvrProtocol>("WarSvrProtocol"),mProtocolType(PROT_INVALID),mConnectionState(PRELOGIN),mrSvrDefinition(svrDefinion),mIsLoggedIn(false){}// WarSvrProtocolWarSvrProtocol::~WarSvrProtocol(){ Logout();}// ~WarSvrProtocol//============================= OPERATORS ====================================//============================= OPERATIONS ===================================void WarSvrProtocol::OnClientConnect(){ SetCurrentState(WAR_SCKSTATE_CONNECTED); WAR_RUN_PLUGINS(WarSvrProtocol, OnClientConnect, (this)); VerifyRemoteIpAddress(); // Start receiving data if (mIoInBufferPtr.IsEmpty()) mIoInBufferPtr = new WarTransferBuffer(IO_BUFFER_LEN); //SetCwd(); if (!GetBoolOption("svr_NOHOSTLOOKUP")) { try { mLocalAddress.Resolv(true); } catch(WarException) { } } RecvWithCallback(mIoInBufferPtr);}void WarSvrProtocol::Send(const std::string& from){ IoQueueOut((war_ccstr_t)from.c_str(), from.size());};void WarSvrProtocol::Send(const war_ccstr_t from, size_t length){ IoQueueOut(from, length);}void WarSvrProtocol::FlushOut(){ IoFlushOut();}void WarSvrProtocol::SetConnectionState(ConnectionStatesE newState){ WarLog debug_log(WARLOG_DEBUG, "WarSvrProtocol::SetConnectionState()"); static const char *state_names[STATE_INVALID +1] = { {"PRELOGIN"}, {"IDLE"}, {"GETFILE"}, {"PUTFILE"}, {"QUITTING"}, {"STATE_INVALID"} }; assert(newState >= 0); assert(newState <= STATE_INVALID); assert(mConnectionState >= 0); assert(mConnectionState <= STATE_INVALID); if (debug_log) { debug_log << "Changing connection state from " << state_names[mConnectionState] << " to " << state_names[newState] << war_endl; } AUTO_LOCK mConnectionState = newState;}war_svrfile_ptr_t WarSvrProtocol::OpenFile(const WarSvrPath& filePath, const war_uint32_t openFlags) throw(WarException){ war_uint32_t my_flags = openFlags; if (!(openFlags & WarFileEnums::F_TEXT) && WarOs::GetOs().IsNt()) my_flags |= WarFileEnums::F_CALLBACK; filePath.VerifyHost(GetRemoteAddress().GetInAddr()); filePath.VerifyPermissions(openFlags); war_svrfile_ptr_t file_ptr = new WarSvrFile; file_ptr->Open(filePath, my_flags); return file_ptr;}// Resolve, convert 8-bit characters to unicode if we use unicode.void WarSvrProtocol::ResolvPath(war_ccstr_t filePath, WarSvrPath& resolvedPath) const throw(WarException){ war_svrpath_t my_path; if (!my_path.IsSlash(*filePath)) my_path << GetCwd().GetAlias().GetPath() << WAR_SLASH; DoResolvPath(filePath, my_path); ResolvPath(my_path, resolvedPath);}// Resolve - no character conversionvoid WarSvrProtocol::ResolvPath(const war_svrpath_t& fromPath, WarSvrPath& resolvedPath) const throw(WarException) { war_svrpath_t my_path; if (!fromPath.IsFirstChSlash()) my_path << GetCwd().GetAlias().GetPath() << WAR_SLASH; my_path << fromPath.GetPath(); my_path.Normalize(); my_path.Deparse(); resolvedPath = mProperties.ResolvPath(my_path); resolvedPath.Normalize();}void WarSvrProtocol::ResolvPath(war_ccstr_t filePath, bool useSecondPath) throw(WarException){ WarSvrPath& ruse_path = useSecondPath ? mCurrentFile2 : mCurrentFile; ResolvPath(filePath, ruse_path);}void WarSvrProtocol::SetCwd(war_ccstr_t newCwd)throw(WarException){ if ((newCwd == NULL) || !*newCwd) { string my_home = GetOption("user_HOME"); if (my_home.empty()) my_home= "/"; SetCwd(my_home.c_str()); return; } WarPath<char,WarSlash> new_cwd; if (!new_cwd.IsSlash(*newCwd)) new_cwd = mCwd.GetAlias().GetPath(); while(new_cwd.IsSlash(*newCwd)) ++newCwd; new_cwd << WAR_SLASH << newCwd; // Check if the path exist WarSvrPath resolved_cwd; ResolvPath(new_cwd.GetPath(), resolved_cwd); // Access check before physical test. Else, all kinds // of funny DoS atacks can be launched. resolved_cwd.VerifyHost(GetRemoteAddress().GetInAddr()); resolved_cwd.VerifyChdir(); war_stat_t my_stat; try { WarFsysStat(resolved_cwd.GetUrl(), my_stat); } catch(WarException& ex) { WarLog warn_log(WARLOG_WARNINGS, "WarSvrProtocol::SetCwd()"); warn_log << "Error: Can not change directory to " << resolved_cwd.GetUrl() << ex << war_endl; throw ex; } if ((my_stat.st_mode & S_IFDIR) != S_IFDIR) WarThrow(WarError(WAR_FERR_NOT_A_DIRECTORY), NULL); // Accept and set the new path mCwd = resolved_cwd;}void WarSvrProtocol::Logout(){ AUTO_LOCK; if (!mIsLoggedIn) return; // WAR_ERR_PLUGIN_DONE is not supported here WAR_PLUGINS_BEGINPRC(WarSvrProtocol, OnLogout, (this)) WAR_PLUGIN_ENDPRC(); // Kill references mAuthDataPtr = NULL; mAuthPtr = NULL; //mIoOutBufferPtr = NULL; //mIoInBufferPtr = NULL; mIsLoggedIn = false; WAR_PERFMON_DEC(WAR_PRFSVR_USERS_ONLINE);}WarSvrEnums::WarLoginResultE WarSvrProtocol::Login( war_ccstr_t virtualHost, war_ccstr_t userName, war_ccstr_t userPasswd) throw(WarException){ war_auth_ptr_t auth_module_ptr; war_authdata_ptr_t session_data_ptr; string user_name = userName ? userName : ""; string virtual_host = virtualHost ? virtualHost : ""; WarCollector<char> user_passwd(WarCollector<char>::SM_ERASE); user_passwd = userPasswd ? userPasswd : ""; if (GetProtocolType() == PROT_FTP) { string anon_names = GetOption("ftpd_ANONUSERS"); for(char *p = strtok(&anon_names[0], "; "); p; p = strtok(NULL, "; ")) { if (strcmp(p, userName) == 0) { user_name = ""; break; } } } WarLoginResultE login_result = LF_INVALID; // WAR_ERR_PLUGIN_DONE is not supported here WAR_PLUGINS_BEGINPRC(WarSvrProtocol, OnLoginPreAuth, (this, virtualHost, userName, userPasswd, user_name, user_passwd, virtual_host)) WAR_PLUGIN_ENDPRC(); login_result = GetAuth().Login( *this, virtual_host.c_str(), user_name.empty() ? NULL : user_name.c_str(), user_passwd.GetValue().c_str(), auth_module_ptr, session_data_ptr); // WAR_ERR_PLUGIN_DONE is not supported here WAR_PLUGINS_BEGINPRC(WarSvrProtocol, OnLoginPostAuth, (this, virtualHost, userName, userPasswd, user_name, user_passwd, virtual_host, login_result, auth_module_ptr, session_data_ptr)) WAR_PLUGIN_ENDPRC(); if (login_result == LF_OK) { assert(auth_module_ptr.IsEmpty() == false); assert(session_data_ptr.IsEmpty() == false); mAuthPtr = auth_module_ptr; mAuthDataPtr = session_data_ptr; mAuthDataPtr->MergeProperties(mProperties); mLoginVirtualHost = virtualHost ? virtualHost : ""; mLoginName = userName ? userName : ""; mUserFancyName = mLoginName; if (mUserFancyName.empty()) { if (mAuthDataPtr->IsAnonymous()) mUserFancyName = "anonymous"; else mUserFancyName = "***UNKNOWN***"; } if (mAuthDataPtr->IsPwdEmail()) { mUserFancyName += '['; mUserFancyName += userPasswd ? userPasswd : ""; mUserFancyName += ']'; } mUserFancyName += '!'; mUserFancyName += GetRemoteAddress().Explain(); WAR_PERFMON_INC(WAR_PRFSVR_USERS_ONLINE); mIsLoggedIn = true; } return login_result;}void WarSvrProtocol::AddToSessionFiles(const WarSvrPath& filePath) { if ((filePath.GetPerms() & SHARED_UPLOAD) != SHARED_UPLOAD) return; // Not a shared upload path if (mOwnFiles.size() < (size_t)GetIntOption("svr_MAXOWNUPLOADFILES")) mOwnFiles.insert(filePath);}void WarSvrProtocol::DeleteFromSessionFiles(const WarSvrPath& filePath){ ownfiles_t::iterator P = mOwnFiles.find(filePath); if (P != mOwnFiles.end()) mOwnFiles.erase(P);}void WarSvrProtocol::VerifyRemoteIpAddress() const throw(WarException){ // Check IP access-list if (!GetProperties().mIpAccessList.IsAllowed( GetRemoteAddress().GetInAddr())) { WarLog db_log(WARLOG_DEBUG, "WarSvrProtocol::VerifyRemoteIpAddress()"); if (db_log) { db_log << "The remote IP address " << GetRemoteAddress().Explain() << " is banned in the current IP access-list. " "Access is denied." << war_endl; } WarThrow(WarError(WAR_ERR_IP_IS_DENIED), NULL); }}//============================= ACCESS ===================================WarSvrEngine& WarSvrProtocol::GetEngine() constthrow(WarException){ return WarSvrEngine::GetEngine();}WarUserEngine& WarSvrProtocol::GetAuth() throw(WarException){ return GetSvrDefinition().GetAuth();}const WarUserEngine& WarSvrProtocol::GetAuth() const throw(WarException){ return GetSvrDefinition().GetAuth();}WarSvrProtocol::ConnectionStatesE WarSvrProtocol::GetConnectionState() { AUTO_LOCK return mConnectionState;}//============================= INQUIRY ===================================bool WarSvrProtocol::IsFileOwnedBySession(const WarSvrPath& filePath) const{ return mOwnFiles.find(filePath) != mOwnFiles.end();}bool WarSvrProtocol::IsAllowed(const struct in_addr& hostAddr) const{ return mProperties.mIpAccessList.IsAllowed(hostAddr);}const std::string WarSvrProtocol::GetSiteName() const{ return GetSvrDefinition().GetSiteName();}const std::string WarSvrProtocol::GetNativeSiteName() const{ return GetSvrDefinition().GetNativeSiteName();}/////////////////////////////// PROTECTED ///////////////////////////////////void WarSvrProtocol::OnSent(const WarError& status, war_transfer_buffer_ptr_t& buffer){ WarSocket::OnSent(status, buffer); AUTO_LOCK if (mIoOutBufferPtr.IsEmpty()) { mIoOutBufferPtr = buffer; // Keep the old buffer. mIoOutBufferPtr->Reset(); }}void WarSvrProtocol::OnReceived(const WarError& status, war_transfer_buffer_ptr_t& buffer){ WarSocket::OnReceived(status, buffer);}void WarSvrProtocol::DoResolvPath(war_ccstr_t filePath, war_svrpath_t& path) const throw(WarException){ path << filePath;}void WarSvrProtocol::PreProtocolCommand() throw(WarException){ WarThreadSpesificData *ptls = WarGetTsd(); if (NULL == ptls) WarThrow(WarError(WAR_THREADERR_NO_TSD), NULL); ptls->mpSvrProtocol = this;}void WarSvrProtocol::PostProtocolCommand() throw(WarException){ WarThreadSpesificData *ptls = WarGetTsd(); if (NULL == ptls) WarThrow(WarError(WAR_THREADERR_NO_TSD), NULL); ptls->mpSvrProtocol = NULL;}/////////////////////////////// PRIVATE ///////////////////////////////////void WarSvrProtocol::IoQueueOut(war_ccstr_t buffer, size_t length){ size_t bytes_to_go = length; war_ccstr_t send_buf = buffer; while(bytes_to_go) { IoAllocateOutputBuffer(); if (bytes_to_go < mIoOutBufferPtr->GetFreeCapacity()) { mIoOutBufferPtr->CopyToBuffer(send_buf, bytes_to_go); break; } else { if (mIoOutBufferPtr->GetFreeCapacity() > 0) { size_t batch_bytes = WarMin(bytes_to_go, mIoOutBufferPtr->GetFreeCapacity()); mIoOutBufferPtr->CopyToBuffer( send_buf, bytes_to_go); send_buf += bytes_to_go; bytes_to_go -= batch_bytes; } IoFlushOut(); } }}void WarSvrProtocol::IoAllocateOutputBuffer(){ AUTO_LOCK if (mIoOutBufferPtr.IsEmpty()) mIoOutBufferPtr = new WarTransferBuffer(IO_BUFFER_LEN);}void WarSvrProtocol::IoFlushOut(){ AUTO_LOCK; if (!mIoOutBufferPtr.IsEmpty() && mIoOutBufferPtr->GetBytesUsed() > 0) { if (GetTransferMode() == TM_FAST) { QueueOutputData(mIoOutBufferPtr); } else { SendWithCallback(mIoOutBufferPtr); } mIoOutBufferPtr = NULL; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -