otsdaq_utilities  v2_02_00
ChatSupervisor.cc
1 #include "otsdaq-utilities/Chat/ChatSupervisor.h"
2 #include "otsdaq-core/MessageFacility/MessageFacility.h"
3 #include "otsdaq-core/Macros/CoutMacros.h"
4 #include "otsdaq-core/CgiDataUtilities/CgiDataUtilities.h"
5 #include "otsdaq-core/XmlUtilities/HttpXmlDocument.h"
6 
7 #include <xdaq/NamespaceURI.h>
8 
9 #include <iostream>
10 
11 using namespace ots;
12 
13 #undef __MF_SUBJECT__
14 #define __MF_SUBJECT__ "Chat"
15 
16 XDAQ_INSTANTIATOR_IMPL(ChatSupervisor)
17 
18 //========================================================================================================================
19 ChatSupervisor::ChatSupervisor(xdaq::ApplicationStub* stub)
20 
21 : CoreSupervisorBase (stub)
22 {
23  INIT_MF("ChatSupervisor");
24 
25  ChatLastUpdateIndex = 1; //skip 0
26 }
27 
28 //========================================================================================================================
29 ChatSupervisor::~ChatSupervisor(void)
30 {
31  destroy();
32 }
33 
34 //========================================================================================================================
35 void ChatSupervisor::destroy(void)
36 {
37  //called by destructor
38 
39 }
40 
41 //========================================================================================================================
42 void ChatSupervisor::defaultPage(xgi::Input * cgiIn, xgi::Output * out )
43 {
44  *out << "<!DOCTYPE HTML><html lang='en'><frameset col='100%' row='100%'><frame src='/WebPath/html/Chat.html?urn=" <<
45  this->getApplicationDescriptor()->getLocalId() <<"'></frameset></html>";
46 }
47 
48 //========================================================================================================================
49 //forceSupervisorPropertyValues
50 // override to force supervisor property values (and ignore user settings)
51 void ChatSupervisor::forceSupervisorPropertyValues()
52 {
53  CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes,
54  "RefreshChat");
55 }
56 
57 //========================================================================================================================
58 // request
59 // Handles Web Interface requests to chat supervisor.
60 // Does not refresh cookie for automatic update checks.
61 void ChatSupervisor::request(const std::string& requestType, cgicc::Cgicc& cgiIn,
62  HttpXmlDocument& xmlOut, const WebUsers::RequestUserInfo& userInfo)
63 {
64  //__COUT__ << "requestType: " << requestType << std::endl;
65 
66  //Commands
67  //RefreshChat
68  //RefreshUsers
69  //SendChat
70 
71  cleanupExpiredChats();
72 
73  if(requestType == "RefreshChat")
74  {
75  std::string lastUpdateIndexString = CgiDataUtilities::postData(cgiIn,"lastUpdateIndex");
76  std::string user = CgiDataUtilities::postData(cgiIn,"user");
77  uint64_t lastUpdateIndex;
78  sscanf(lastUpdateIndexString.c_str(),"%lu",&lastUpdateIndex);
79 
80  insertChatRefresh(&xmlOut,lastUpdateIndex,user);
81  }
82  else if(requestType == "RefreshUsers")
83  {
84  insertActiveUsers(&xmlOut);
85  }
86  else if(requestType == "SendChat")
87  {
88  std::string chat = CgiDataUtilities::postData(cgiIn,"chat");
89  std::string user = CgiDataUtilities::postData(cgiIn,"user");
90 
91  escapeChat(chat);
92 
93  newChat(chat, user);
94  }
95  else if(requestType == "PageUser")
96  {
97  std::string topage = CgiDataUtilities::postData(cgiIn,"topage");
98  std::string user = CgiDataUtilities::postData(cgiIn,"user");
99 
100  __COUT__ << "Paging = " << topage.substr(0,10) << "... from user = " << user.substr(0,10) << std::endl;
101 
102  theRemoteWebUsers_.sendSystemMessage(allSupervisorInfo_.getGatewayDescriptor(),
103  topage, user + " is paging you to come chat.");
104  }
105  else
106  __COUT__ << "requestType request not recognized." << std::endl;
107 //
108 // //return xml doc holding server response
109 // xmlOut.outputXmlDocument((std::ostringstream*)out);
110 }
111 
112 //========================================================================================================================
113 //ChatSupervisor::escapeChat()
114 // replace html/xhtml reserved characters with equivalent.
115 // reserved: ", ', &, <, >
116 void ChatSupervisor::escapeChat(std::string &chat)
117 {
118  // char reserved[] = {'"','\'','&','<','>'};
119  //std::string replace[] = {"&#34;","&#39;","&#38;","&#60;","&#62;"};
120  // for(uint64_t i=0;i<chat.size();++i)
121  // for(uint64_t j=0;j<chat.size();++j)
122  // if(chat[i] ==
123 }
124 
125 //========================================================================================================================
126 //ChatSupervisor::insertActiveUsers()
127 void ChatSupervisor::insertActiveUsers(HttpXmlDocument *xmlOut)
128 {
129  xmlOut->addTextElementToData("active_users",
130  theRemoteWebUsers_.getActiveUserList(allSupervisorInfo_.getGatewayDescriptor()));
131 }
132 
133 //========================================================================================================================
134 //ChatSupervisor::insertChatRefresh()
135 // check if user is new to list (may cause update)
136 // each new user causes update to last index
137 // if lastUpdateIndex is current, return nothing
138 // else return full chat user list and new chats
139 // (note: lastUpdateIndex==0 first time and returns only user list. no chats)
140 void ChatSupervisor::insertChatRefresh(HttpXmlDocument *xmlOut, uint64_t lastUpdateIndex, std::string user)
141 {
142  newUser(user);
143 
144  if(!isLastUpdateIndexStale(lastUpdateIndex)) return; // if lastUpdateIndex is current, return nothing
145 
146  //return new update index, full chat user list, and new chats!
147 
148  char tempStr[50];
149  sprintf(tempStr,"%lu",ChatLastUpdateIndex);
150  xmlOut->addTextElementToData("last_update_index",tempStr);
151 
152  //get all users
153  xmlOut->addTextElementToData("chat_users","");
154  for(uint64_t i=0;i<ChatUsers_.size();++i)
155  xmlOut->addTextElementToParent("chat_user",ChatUsers_[i],"chat_users");
156 
157  if(!lastUpdateIndex) //lastUpdateIndex == 0, so just give the <user> entered chat message only
158  lastUpdateIndex = ChatHistoryIndex_[ChatHistoryIndex_.size()-1]-1; //new user will then get future chats
159 
160  //get all accounts
161  xmlOut->addTextElementToData("chat_history","");
162  for(uint64_t i=0;i<ChatHistoryEntry_.size();++i) //output oldest to new
163  {
164  if(isChatOld(ChatHistoryIndex_[i],lastUpdateIndex)) continue;
165 
166  xmlOut->addTextElementToParent("chat_entry",ChatHistoryEntry_[i],"chat_history");
167  xmlOut->addTextElementToParent("chat_author",ChatHistoryAuthor_[i],"chat_history");
168  sprintf(tempStr,"%lu",ChatHistoryTime_[i]);
169  xmlOut->addTextElementToParent("chat_time",tempStr,"chat_history");
170  }
171 }
172 
173 //========================================================================================================================
174 //ChatSupervisor::newUser()
175 // create new user if needed, and increment update
176 void ChatSupervisor::newUser(std::string user)
177 {
178  for(uint64_t i=0;i<ChatUsers_.size();++i)
179  if(ChatUsers_[i] == user)
180  {
181  ChatUsersTime_[i] = time(0); //update time
182  return; //do not add new if found
183  }
184 
185  __COUT__ << "New user: " << user << std::endl;
186  //add and increment
187  ChatUsers_.push_back(user);
188  ChatUsersTime_.push_back(time(0));
189  newChat(user + " joined the chat.","ots"); //add status message to chat, increment update
190 }
191 
192 //========================================================================================================================
193 //ChatSupervisor::newChat()
194 // create new chat, and increment update
195 void ChatSupervisor::newChat(std::string chat, std::string user)
196 {
197  ChatHistoryEntry_.push_back(chat);
198  ChatHistoryAuthor_.push_back(user);
199  ChatHistoryTime_.push_back(time(0));
200  ChatHistoryIndex_.push_back(incrementAndGetLastUpdate());
201 }
202 
203 //========================================================================================================================
204 //ChatSupervisor::isChatNew()
205 // return true if chatIndex is older than lastUpdateIndex
206 bool ChatSupervisor::isChatOld(uint64_t chatIndex, uint64_t last)
207 {
208  return (last - chatIndex < (uint64_t(1) << 62));
209 }
210 
211 //========================================================================================================================
212 //ChatSupervisor::isLastUpdateIndexStale()
213 bool ChatSupervisor::isLastUpdateIndexStale(uint64_t last)
214 {
215  return ChatLastUpdateIndex != last;
216 }
217 
218 //========================================================================================================================
219 //ChatSupervisor::incrementAndGetLastUpdate()
220 uint64_t ChatSupervisor::incrementAndGetLastUpdate()
221 {
222  if(!++ChatLastUpdateIndex) ++ChatLastUpdateIndex; //skip 0
223  return ChatLastUpdateIndex;
224 }
225 
226 //========================================================================================================================
227 //ChatSupervisor::cleanupExpiredChats()
228 // remove expired entries from Chat history and user list
229 void ChatSupervisor::cleanupExpiredChats()
230 {
231  for(uint64_t i=0;i<ChatHistoryEntry_.size();++i)
232  if(i >= CHAT_HISTORY_MAX_ENTRIES ||
233  ChatHistoryTime_[i] + CHAT_HISTORY_EXPIRATION_TIME < time(0)) //expired
234  {
235  removeChatHistoryEntry(i);
236  --i; //rewind loop
237  }
238  else
239  break; //chronological order, so first encountered that is still valid exit loop
240 
241  for(uint64_t i=0;i<ChatUsers_.size();++i)
242  if(ChatUsersTime_[i] + CHAT_HISTORY_EXPIRATION_TIME < time(0)) //expired
243  {
244  removeChatUserEntry(i);
245  --i; //rewind loop
246  }
247  else
248  break; //chronological order, so first encountered that is still valid exit loop
249 }
250 
251 //========================================================================================================================
252 //ChatSupervisor::removeChatHistoryEntry()
253 void ChatSupervisor::removeChatHistoryEntry(uint64_t i)
254 {
255  ChatHistoryEntry_.erase (ChatHistoryEntry_.begin()+i);
256  ChatHistoryTime_.erase (ChatHistoryTime_.begin()+i);
257  ChatHistoryAuthor_.erase (ChatHistoryAuthor_.begin()+i);
258  ChatHistoryIndex_.erase (ChatHistoryIndex_.begin()+i);
259 }
260 
261 //========================================================================================================================
262 //ChatSupervisor::removeChatHistoryEntry()
263 void ChatSupervisor::removeChatUserEntry(uint64_t i)
264 {
265  newChat(ChatUsers_[i] + " left the chat.","ots"); //add status message to chat, increment update
266  ChatUsers_.erase (ChatUsers_.begin()+i);
267  ChatUsersTime_.erase (ChatUsersTime_.begin()+i);
268 }
269 
270 
271 
272 
273 
274 
275 
276