/** * @file lltrustnet.cpp * @brief LLTrustNet implementation * @author Dale Glass * * Copyright (c) 2005-2007, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. */ #include "llviewerprecompiledheaders.h" #include "lltrustnet.h" #include "llcachename.h" #include LLTrustNet *gTrustNet = NULL; const LLString DELIMITER = "|"; LLString LLTrustNetScoreRequest::asString() { llinfos << "Requesting id " << mID << "; name " << mName << "; type " << mType << llendl; return "GetScore|" + mName + "|" + mID.asString() + "|" + mType; } LLString LLTrustNetRateRequest::asString() { std::ostringstream o; o << mScore; llinfos << "Sending score for id " << mID << "; name " << mName << "; type " << mType << llendl; return "Rate|" + mName + "|" + mID.asString() + "|" + mType + "|" + o.str() + "|" + mComment; } LLTrustNetScore::LLTrustNetScore(F32 score, LLString comments) { mOperation = TN_GET_SCORE; mScore = score; set(score,comments); if ( mScore != 0.0f ) { setState(TNS_RETRIEVED); } else { setState(TNS_UNKNOWN); } } void LLTrustNetDatum::addCallback(trustnet_callback_t callback, void *user_data) { LLTrustNetCallbackEntry ent(callback, user_data); mCallbacks.push( ent ); } void LLTrustNetDatum::notify(ETrustNetResult result) { LLUUID id = LLUUID::null; // If there's a parent we get the ID from it. There may not be one, such // as for data not associated with any particular avatar, such as log // entries and statistics. if ( mParent ) { id = mParent->getAvatar(); } while( ! mCallbacks.empty() ) { LLTrustNetCallbackEntry *ent = &mCallbacks.front(); ent->callback(mOperation, result, id, ent->user_data); mCallbacks.pop(); } } static std::vector tokenize(LLString text, U32 max_tokens = 0) { U32 count = 0; std::vector tokens; LLString::size_type last_pos = text.find_first_not_of(DELIMITER, 0); LLString::size_type pos = text.find_first_of(DELIMITER, last_pos); while(LLString::npos != pos && LLString::npos != last_pos && !(max_tokens > 0 && count >= max_tokens)) { llinfos << "token: " << text.substr(last_pos, pos - last_pos) << llendl; tokens.push_back(text.substr(last_pos, pos - last_pos)); last_pos = text.find_first_not_of(DELIMITER, pos); pos = text.find_first_of(DELIMITER, last_pos); count++; } if (LLString::npos != last_pos) { // We stopped due to max token count, but there's still more data // add it all as the last token llinfos << "extra token: " << text.substr(last_pos) << llendl; tokens.push_back(text.substr(last_pos)); } lldebugs << "Got " << count << " tokens" << llendl; return tokens; } //static void LLTrustNet::viewerCommCallback(LLString& data, LLViewerCircuit& circuit, void* userdata) { llinfos << "I got: " << data << llendl; std::vector tokens = tokenize(data); if (tokens.size() < 1) return; gTrustNet->mCircuit = &circuit; if ( tokens[0] == "Init" ) { gTrustNet->mConnectionState = TRUSTNET_NO_CONNECTION; } else if ( tokens[0] == "LoginInProgress" ) { gTrustNet->mConnectionState = TRUSTNET_LOGGING_IN; } else if ( tokens[0] == "AdapterRunning" ) { gTrustNet->mConnectionState = TRUSTNET_CONNECTED; } else if ( tokens[0] == "Score" && tokens.size() >= 4 ) { LLUUID avatar(tokens[1]); LLString type = tokens[2]; F32 score = 0.0; std::istringstream i(tokens[3]); i >> score; gTrustNet->setScore(avatar, type, score); } else { llwarns << "Unknown command " << tokens[0] << llendl; } } LLTrustNet::LLTrustNet() { mCircuit = NULL; mConnectionState = TRUSTNET_NO_ADAPTER; // Register callback gViewerCommunication->registerExtension( LLViewerExtension("DaleGlass.TrustNet", 1, viewerCommCallback, NULL, "Dale Glass", "TrustNet Reputation System") ); } LLTrustNetScore LLTrustNet::getScoreData(const LLUUID& avatar, const LLString& type) { // First check whether we already have it. If these map elements // don't exist, they'll be automatically created. The constructor // ensures they'll be created in an empty state that we use as // a placeholder for when it arrives. mCache[avatar].setAvatar(avatar); LLTrustNetScore score = mCache[avatar].mScores[type]; mCache[avatar].mScores[type].setParent(&mCache[avatar]); ETrustNetDatumState st = score.getState(); if ( st != TNS_RETRIEVED && st != TNS_FETCHING ) { LLString name; char first[DB_FIRST_NAME_BUF_SIZE]; char last[DB_LAST_NAME_BUF_SIZE]; if ( gCacheName->getName(avatar, first, last) ) { name = first; name += " "; name += last; //score.mState = SCORE_FETCHING; mCache[avatar].mScores[type].setState(TNS_FETCHING); LLTrustNetScoreRequest *req = new LLTrustNetScoreRequest(avatar, name, type); mQueue.push_back(req); //avdata.mScores[type] = score; } } return score; } F32 LLTrustNet::getScore(const LLUUID& avatar, const LLString& type) { if ( NULL == mCircuit ) { llwarns << "Circuit not yet established" << llendl; return 0.0f; } LLTrustNetScore score = getScoreData(avatar, type); return score.mScore; } ETrustNetDatumState LLTrustNet::getScoreState(const LLUUID& avatar, const LLString& type) { if ( NULL == mCircuit ) { llwarns << "Circuit not yet established" << llendl; return TNS_UNKNOWN; } LLTrustNetScore score = getScoreData(avatar, type); return score.getState(); } void LLTrustNet::setScore(const LLUUID& avatar, const LLString& type, F32 newscore) { mCache[avatar].mScores[type].set(newscore,""); //mCache[avatar].mScores[type].mState = SCORE_RETRIEVED; } LLColor4 LLTrustNet::getScoreColor(const LLUUID& avatar,const LLString& type) { F32 score = getScore(avatar, type); LLColor4 color; if ( score == 0.0f ) { // Neutral color = LLColor4::grey; } else if ( score > 0.0f ) { if ( score > 10.0f ) { // Self color = LLColor4(0.0f, 1.0f, 1.0f); } else { // Friend color = LLColor4(0.0f, score / 10, 0.0f); } } else { // Enemy color = LLColor4(score / 10, 0.0f, 0.0f); } return color; } LLString LLTrustNet::getConnectionStateString() const { switch( mConnectionState ) { case TRUSTNET_NO_ADAPTER: return "Adapter not being worn"; case TRUSTNET_NO_CONNECTION: return "No connection"; case TRUSTNET_CONNECTING: return "Connecting..."; case TRUSTNET_LOGGING_IN: return "Logging in..."; case TRUSTNET_LOGIN_ERROR: return "Login error"; case TRUSTNET_CONNECTED: return "Connected"; } return ""; } void LLTrustNet::processRequests() { //if ( mQueue.empty() ) return; while(!mQueue.empty()) { LLTrustNetRequest *req = mQueue.front(); LLString reqtext = req->asString(); if ( reqtext.empty() ) { llwarns << "BUG!" << llendl; } else { llinfos << "Requesting: " << reqtext << llendl; mCircuit->sendReply( reqtext ); } mQueue.pop_front(); delete req; } }