ShellSession.cpp 5.13 KB
Newer Older
xiongziliang committed
1
/*
xiongziliang committed
2
 * MIT License
xzl committed
3
 *
xiongziliang committed
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 * Copyright (c) 2016 xiongziliang <771730766@qq.com>
 *
 * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
xzl committed
25 26 27
 */

#include "ShellSession.h"
28 29
#include "Common/config.h"
#include "Util/CMD.h"
xzl committed
30
#include "Util/onceToken.h"
31
#include "Util/NoticeCenter.h"
xiongziliang committed
32
using namespace toolkit;
xzl committed
33

xiongziliang committed
34
namespace mediakit {
xzl committed
35 36

ShellSession::ShellSession(const std::shared_ptr<ThreadPool> &_th,
37
                           const Socket::Ptr &_sock) :
38
        TcpSession(_th, _sock) {
39
    pleaseInputUser();
xzl committed
40 41 42 43 44
}

ShellSession::~ShellSession() {
}

45
void ShellSession::onRecv(const Buffer::Ptr&buf) {
xzl committed
46
	//DebugL << hexdump(buf->data(), buf->size());
xiongziliang committed
47
    GET_CONFIG_AND_REGISTER(uint32_t,maxReqSize,Shell::kMaxReqSize);
48
    if (_strRecvBuf.size() + buf->size() >= maxReqSize) {
xzl committed
49 50 51 52
		WarnL << "接收缓冲区溢出!";
		shutdown();
		return;
	}
53 54 55
	_beatTicker.resetTime();
	_strRecvBuf.append(buf->data(), buf->size());
	if (_strRecvBuf.find("\xff\xf4\xff\0xfd\x06") != std::string::npos) {
xzl committed
56 57 58 59 60 61 62
		WarnL << "收到Ctrl+C.";
		send("\033[0m\r\n	Bye bye!\r\n");
		shutdown();
		return;
	}
	size_t index;
	string line;
63 64 65
	while ((index = _strRecvBuf.find("\r\n")) != std::string::npos) {
		line = _strRecvBuf.substr(0, index);
		_strRecvBuf.erase(0, index + 2);
66
		if (!onCommandLine(line)) {
xzl committed
67 68 69 70 71 72 73
			shutdown();
			return;
		}
	}
}

void ShellSession::onManager() {
74
	if (_beatTicker.elapsedTime() > 1000 * 60 * 5) {
xzl committed
75 76 77 78 79 80
		//5 miniutes for alive
		shutdown();
		return;
	}
}

81
inline bool ShellSession::onCommandLine(const string& line) {
82
    auto loginInterceptor = _loginInterceptor;
83 84
    if (loginInterceptor) {
		bool ret = loginInterceptor(line);
xzl committed
85 86
		return ret;
	}
87 88 89 90 91 92 93 94 95 96 97 98
    try {
        std::shared_ptr<stringstream> ss(new stringstream);
        CMDRegister::Instance()(line,ss);
        send(ss->str());
    }catch(ExitException &ex){
        return false;
    }catch(std::exception &ex){
        send(ex.what());
        send("\r\n");
    }
    printShellPrefix();
	return true;
xzl committed
99 100
}

101
inline void ShellSession::pleaseInputUser() {
xzl committed
102
	send("\033[0m");
103
	send(StrPrinter << SERVER_NAME << " login: " << endl);
104 105
	_loginInterceptor = [this](const string &user_name) {
		_strUserName=user_name;
106
        pleaseInputPasswd();
xzl committed
107 108 109
		return true;
	};
}
110
inline void ShellSession::pleaseInputPasswd() {
xzl committed
111
	send("Password: \033[8m");
112
	_loginInterceptor = [this](const string &passwd) {
113 114 115 116 117 118 119
        auto onAuth = [this](const string &errMessage){
            if(!errMessage.empty()){
                //鉴权失败
                send(StrPrinter
                     <<"\033[0mAuth failed("
                     << errMessage
                     <<"), please try again.\r\n"
120
                     <<_strUserName<<"@"<<SERVER_NAME
121 122 123 124 125 126 127 128 129
                     <<"'s password: \033[8m"
                     <<endl);
                return;
            }
            send("\033[0m");
            send("-----------------------------------------\r\n");
            send(StrPrinter<<"欢迎来到"<<SERVER_NAME<<", 你可输入\"help\"查看帮助.\r\n"<<endl);
            send("-----------------------------------------\r\n");
            printShellPrefix();
130
            _loginInterceptor=nullptr;
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
        };

        weak_ptr<ShellSession> weakSelf = dynamic_pointer_cast<ShellSession>(shared_from_this());
        Broadcast::AuthInvoker invoker = [weakSelf,onAuth](const string &errMessage){
            auto strongSelf =  weakSelf.lock();
            if(!strongSelf){
                return;
            }
            strongSelf->async([errMessage,weakSelf,onAuth](){
                auto strongSelf =  weakSelf.lock();
                if(!strongSelf){
                    return;
                }
                onAuth(errMessage);
            });
        };

148
        auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastShellLogin,_strUserName,passwd,invoker,*this);
149 150 151 152
        if(!flag){
            //如果无人监听shell登录事件,那么默认shell无法登录
            onAuth("please listen kBroadcastShellLogin event");
        }
xzl committed
153 154 155 156
		return true;
	};
}

157
inline void ShellSession::printShellPrefix() {
158
	send(StrPrinter << _strUserName << "@" << SERVER_NAME << "# " << endl);
xzl committed
159 160
}

xiongziliang committed
161
}/* namespace mediakit */