00001
00030 #include "llviewerprecompiledheaders.h"
00031 #include "llviewercommunication.h"
00032 #include "llviewermessage.h"
00033 #include "llagent.h"
00034 #include "llviewerstats.h"
00035 #include "llchat.h"
00036
00037 #include <vector>
00038 #include <string.h>
00039
00040 const LLString DELIMITER = "$";
00041 const LLString MAGIC_WORD = "VwrComm";
00042 const LLString VERSION = "0";
00043
00044 const LLString VIEWER_EXTENSION = "DaleGlass.Viewer";
00045
00046 const U32 MAX_TOKENS = 3;
00047
00048 const U32 OFF_MAGIC = 0;
00049 const U32 OFF_VERSION = 1;
00050 const U32 OFF_EXTENSION = 2;
00051 const U32 OFF_DATA = 3;
00052
00053 LLViewerCommunication *gViewerCommunication = NULL;
00054
00055 void LLViewerCircuit::sendReply(const LLString& data)
00056 {
00057 LLMessageSystem* msg = gMessageSystem;
00058
00059 msg->newMessageFast(_PREHASH_ChatFromViewer);
00060 msg->nextBlockFast(_PREHASH_AgentData);
00061 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00062 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00063 msg->nextBlockFast(_PREHASH_ChatData);
00064 msg->addStringFast(_PREHASH_Message, data);
00065 msg->addU8Fast(_PREHASH_Type, CHAT_TYPE_WHISPER);
00066 msg->addS32("Channel", mChannel);
00067
00068 gAgent.sendReliableMessage();
00069
00070 gViewerStats->incStat(LLViewerStats::ST_CHAT_COUNT);
00071 }
00072
00073 std::vector<LLString> tokenize(LLString text, U32 max_tokens = 0)
00074 {
00075 U32 count = 0;
00076
00077 std::vector<LLString> tokens;
00078
00079 LLString::size_type last_pos = text.find_first_not_of(DELIMITER, 0);
00080 LLString::size_type pos = text.find_first_of(DELIMITER, last_pos);
00081
00082 while(LLString::npos != pos && LLString::npos != last_pos && !(max_tokens > 0 && count >= max_tokens))
00083 {
00084 llinfos << "token: " << text.substr(last_pos, pos - last_pos) << llendl;
00085 tokens.push_back(text.substr(last_pos, pos - last_pos));
00086
00087 last_pos = text.find_first_not_of(DELIMITER, pos);
00088 pos = text.find_first_of(DELIMITER, last_pos);
00089
00090 count++;
00091 }
00092
00093 if (LLString::npos != last_pos)
00094 {
00095
00096
00097 llinfos << "extra token: " << text.substr(last_pos) << llendl;
00098 tokens.push_back(text.substr(last_pos));
00099 }
00100 lldebugs << "Got " << count << " tokens" << llendl;
00101
00102 return tokens;
00103 }
00104
00105 void protocol_handler(LLString& data, LLViewerCircuit& circuit, void* userdata)
00106 {
00107 lldebugs << data << llendl;
00108 std::vector<LLString> tokens = tokenize(data);
00109
00110 LLString reply;
00111 if ( tokens[0] == "Connect" )
00112 {
00113 reply = "OK";
00114 }
00115 else if ( tokens[0] == "Ping" )
00116 {
00117 reply = "Pong";
00118 }
00119 else
00120 {
00121 llwarns << "Unrecognized command: " << tokens[0] << ", data " << data << llendl;
00122 return;
00123 }
00124
00125 circuit.sendReply(reply);
00126 }
00127
00128 LLViewerCommunication::LLViewerCommunication()
00129 {
00130 registerExtension( LLViewerExtension(VIEWER_EXTENSION, 1, protocol_handler, NULL, "Dale Glass", "General viewer info") );
00131 }
00132
00133 bool LLViewerCommunication::parse(const LLString &text, const LLUUID& speaker)
00134 {
00135 llinfos << "Parsing message: " << text << llendl;
00136
00137 std::vector<LLString> tokens = tokenize(text, MAX_TOKENS);
00138
00139 if ( !(tokens.size() >= MAX_TOKENS && tokens[OFF_MAGIC] == MAGIC_WORD) ) return false;
00140 llinfos << "Viewer communication detected" << llendl;
00141
00142 if ( !(tokens[OFF_VERSION] == VERSION) )
00143 {
00144 llwarns << "Viewer/object protocol version " << tokens[OFF_VERSION] << " not recognized" << llendl;
00145 return false;
00146 }
00147 llinfos << "Version correct" << llendl;
00148
00149
00150
00151 if ( tokens[OFF_EXTENSION] == VIEWER_EXTENSION && tokens[OFF_DATA].find("Connect$") == 0 )
00152 {
00153 std::vector<LLString> tmp = tokenize(tokens[OFF_DATA]);
00154 if ( tmp.size() >= 2 )
00155 {
00156 S32 channel = atoi(tmp[1].c_str());
00157 LLViewerCircuit circuit( channel );
00158
00159 mCircuits[speaker] = circuit;
00160 llinfos << "Connection to object " << speaker << "established on channel " << channel << llendl;
00161 }
00162 else
00163 {
00164 llwarns << "Bad connection attempt, too few tokens" << llendl;
00165 }
00166 }
00167
00168
00169 std::map<LLString, LLViewerExtension>::iterator iter_e = mExtensions.find(tokens[OFF_EXTENSION]);
00170 if ( iter_e == mExtensions.end() )
00171 {
00172 llwarns << "Object requested inexistent extension " << tokens[OFF_EXTENSION] << llendl;
00173 return false;
00174 }
00175 LLViewerExtension* ext = &iter_e->second;
00176 llinfos << "Viewer extension found" << llendl;
00177
00178
00179 std::map<LLUUID, LLViewerCircuit>::iterator iter_c = mCircuits.find(speaker);
00180 if ( iter_c == mCircuits.end() )
00181 {
00182 llwarns << "Object " << speaker << " tried to communicate without an established connection" << llendl;
00183 return false;
00184 }
00185
00186 llinfos << "Viewer circuit found" << llendl;
00187
00188 ext->notify(tokens[OFF_DATA], iter_c->second);
00189
00190 return true;
00191 }
00192