TelnetServer.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. #include "TelnetServer.h"
  2. #include <time.h>
  3. #include <SimpleString.h>
  4. #if defined(_MSC_VER)
  5. struct CTelnetServer::SessionContext
  6. {
  7. int nConnectionID;
  8. string strInput;
  9. };
  10. #endif /*RVC_OS_WIN*/
  11. CTelnetServer::CTelnetServer(void)
  12. : CIOCPSocketServer(2)
  13. #if defined(_MSC_VER)
  14. ,m_bIgnoreArrowKey(true)
  15. #endif /*RVC_OS_WIN*/
  16. {
  17. }
  18. CTelnetServer::~CTelnetServer(void)
  19. {
  20. }
  21. #if defined(_MSC_VER)
  22. string CTelnetServer::GetLocalTimeString(bool bShort)
  23. {
  24. __time64_t now;
  25. _time64(&now);
  26. struct tm when;
  27. _localtime64_s(&when, &now);
  28. char buf[80];
  29. if (bShort)
  30. sprintf_s(buf, 80, "%02d:%02d:%02d", when.tm_hour, when.tm_min, when.tm_sec);
  31. else
  32. sprintf_s(buf, 80, "%04d-%02d-%02d %02d:%02d:%02d", when.tm_year + 1900, when.tm_mon+1, when.tm_mday,
  33. when.tm_hour, when.tm_min, when.tm_sec);
  34. return buf;
  35. }
  36. void CTelnetServer::OnEvent(const char *pFormat, ...)
  37. {
  38. va_list arg;
  39. va_start(arg, pFormat);
  40. OnConsoleOutput(false, pFormat, arg);
  41. }
  42. void CTelnetServer::OnError(const char *pFormat, ...)
  43. {
  44. va_list arg;
  45. va_start(arg, pFormat);
  46. OnConsoleOutput(true, pFormat, arg);
  47. }
  48. void CTelnetServer::OnConsoleOutput(bool bError, const char *pFormat, va_list arg)
  49. {
  50. _CrtSetDebugFillThreshold(0);
  51. char *buf = (char*)_alloca(1024);
  52. sprintf_s(buf, 24, "[%s] [%s] ", GetLocalTimeString().c_str(), bError?"Error":"Event");
  53. vsprintf_s(buf + strlen(buf), 1000, pFormat, arg);
  54. printf(buf);
  55. }
  56. void CTelnetServer::OnAccepte(int nConnectionID, const char *pRemoteAddr, int nPort)
  57. {
  58. OnEvent("accept connection from %s:%d\r\n", pRemoteAddr, nPort);
  59. {
  60. CAutoLock lock(&m_LockObject);
  61. auto pSessoinContext = new SessionContext();
  62. pSessoinContext->nConnectionID = nConnectionID;
  63. m_SessionContext[nConnectionID] = pSessoinContext;
  64. }
  65. string strReply = GetHelloString()+ GetPromptString();
  66. AsyncSend(nConnectionID, (char*)strReply.c_str(), strReply.size());
  67. }
  68. void CTelnetServer::OnSend(int nConnectionID, int nSendLen)
  69. {
  70. }
  71. void CTelnetServer::OnReceive(int nConnectionID, char *pData, int nRecvLen)
  72. {
  73. string strCmd;
  74. {
  75. CAutoLock lock(&m_LockObject);
  76. auto it = m_SessionContext.find(nConnectionID);
  77. if (it == m_SessionContext.end())
  78. {
  79. OnError("invalid connection id: %d\r\n", nConnectionID);
  80. return;
  81. }
  82. auto pSessionContext = (*it).second;
  83. // handle arrow keys
  84. if (nRecvLen >= 3 && pData[0] == 0x1b && pData[1] == 0x5b)
  85. return;
  86. // handle backspace char
  87. for(int i=0; i<nRecvLen; i++)
  88. {
  89. if (pData[i] == '\b')
  90. {
  91. if (pSessionContext->strInput.size() > 0)
  92. pSessionContext->strInput.erase(pSessionContext->strInput.size()-1, 1);
  93. }
  94. else
  95. pSessionContext->strInput += pData[i];
  96. }
  97. int nIndex = pSessionContext->strInput.find("\r\n");
  98. if (nIndex <0)
  99. return;
  100. strCmd = pSessionContext->strInput.substr(0, nIndex);
  101. pSessionContext->strInput.erase(0, nIndex+2);
  102. }
  103. if (strCmd.size() == 0) // press enter key
  104. {
  105. string strReply = GetPromptString();
  106. AsyncSend(nConnectionID, (char*)strReply.c_str(), strReply.size());
  107. return;
  108. }
  109. string strReplyMsg;
  110. if (!ParseCmdLine(nConnectionID, strCmd.c_str(), strReplyMsg))
  111. {
  112. OnError("parse command {%s} error, %s", strCmd.c_str(), strReplyMsg.c_str());
  113. strReplyMsg += GetHelloString();
  114. }
  115. strReplyMsg = CSimpleStringA::Format("\r\n%s\r\n%s", strReplyMsg.c_str(), GetPromptString().c_str());
  116. AsyncSend(nConnectionID, (char*)strReplyMsg.c_str(), strReplyMsg.size());
  117. }
  118. void CTelnetServer::OnClose(int nConnectionID)
  119. {
  120. {
  121. CAutoLock lock(&m_LockObject);
  122. auto it = m_SessionContext.find(nConnectionID);
  123. if (it == m_SessionContext.end())
  124. return;
  125. auto pSessionContext = (*it).second;
  126. m_SessionContext.erase(nConnectionID);
  127. delete pSessionContext;
  128. }
  129. OnEvent("connection [%d] closed\r\n", nConnectionID);
  130. }
  131. string CTelnetServer::GetErrorReplyString(string errMsg)
  132. {
  133. string strReplyMsg = "command parse error, ";
  134. strReplyMsg += errMsg;
  135. strReplyMsg += "\r\n";
  136. strReplyMsg += GetHelloString() + GetPromptString();
  137. return strReplyMsg;
  138. }
  139. bool CTelnetServer::IsCharIncluded(char ch, char chars[])
  140. {
  141. if (chars == NULL)
  142. return false;
  143. for(int i=0; i<sizeof(chars) / sizeof(chars[0]); i++)
  144. {
  145. if (chars[i] == ch)
  146. return true;
  147. }
  148. return false;
  149. }
  150. // default split char is: all chars exclude char & number
  151. vector<string> CTelnetServer::SplitString(const char *pLine, char notDelimiterChars[])
  152. {
  153. vector<string> list;
  154. char *p1 = (char*)pLine;
  155. char *p2 = p1;
  156. while(*p1)
  157. {
  158. while(*p2 && (IsCharAlphaNumeric(*p2) || IsCharIncluded(*p2, notDelimiterChars)))
  159. p2++;
  160. if (p2 != p1)
  161. list.push_back(string(p1, p2-p1));
  162. // skip blankspace
  163. while(*p2 && !IsCharAlphaNumeric(*p2) && !IsCharIncluded(*p2, notDelimiterChars))
  164. p2++;
  165. p1 = p2;
  166. }
  167. return list;
  168. }
  169. #endif /*RVC_OS_WIN*/