llviewercommunication.cpp

Go to the documentation of this file.
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                 // We stopped due to max token count, but there's still more data
00096                 // add it all as the last token
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         // The connection step presents a small problem: To handle a command to a callback
00150         // there must be a connection, but there isn't one yet. So we handle it here.
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         // Find the extension
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         // Find the circuit
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         //LLViewerCircuit* circuit = &iter_c->second;
00186         llinfos << "Viewer circuit found" << llendl;
00187 
00188         ext->notify(tokens[OFF_DATA], iter_c->second);
00189 
00190         return true;
00191 }
00192 

Generated on Thu Jul 1 06:09:27 2010 for Second Life Viewer by  doxygen 1.4.7