TelnetServer.cpp 4.5 KB

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